Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Eren Erener
Eren Erener
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
12 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: adresi assembly bitlik ekrana ilgili karakter kaydedicisine kaydedicisinin komutlar komutu program reg16 reg32 segment yigina X86 Assembly Eren Erener
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Başlangıç
Kategori : X86 Assembly
Yayınlanma Tarihi : 10.9.2005
Okunma Sayısı : 87980
Yorum Sayısı : 1     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Burak Selim Şenyurt
Kurumsal Yazılımcının Oyun Geliştirme ile İmtihanı 28.3.2024
Burak Selim Şenyurt
Matematik ve Oyun Programlama - Missile Command - Final 28.3.2024
Turhal Temizer
Conda install environment.yml Package 28.3.2024
Turhal Temizer
Mac OS/X Removing CUDA 28.3.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
80x86 KOMUT SETİ (Bölüm 1)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu makalemizde 80x86 gerçek mod komutlarını inceleyeceğiz.

80x86 KOMUT SETİ (Bölüm 1)

X86 tabanlı mikroişlemcilerin icra ettiği makine kodları sabit olmasına rağmen, programlama dillerinin komut ve ifadeleri farklı olabilir. Assembly programlama dilininde diğer programlama dillerinde olduğu gibi bir dizi komutu vardır. Bu komutlar genelde mnemonik’ler (nivmonik diye okunur) şeklindedir. Örneğin LEA mnemoniği Load Effective Adres kelimelerinin kısaltılmış şeklidir. Bu makalemizde x86 Assembly programlama dilinin komutlarını anlatmaya çalışacağım ve bu makalede açıklanan komutları öğrendiğinizde kendi başınıza program yazabilir hale geleceksiniz. Aslında 80386 ve sonrası mikroişlemciler için daha birçok komut mevcuttur ve bu komutlar assembly dilinde program yazma işini kolaylaştırır. Bu komutları ilerleyen makalelerimizde açıklamaya çalışacağım.

80x86 komutları genelde 8 grup altında incelenir.

1) Veri taşıma komutları

    mov, lea, les , push, pop, pushf, popf

2) Dönüştürme komutları

    cbw, cwd, xlat

3) Aritmetic komutlar

    add, inc sub, dec, cmp, neg, mul, imul, div, idiv

4) Mantıksal, kaydırma, çevirme ve bitsel işlemler için komutlar

    and, or, xor, not, shl, shr, rcl, rcr

5) I/O (Giriş/Çıkış) komutları

    in, out

6) Karakter dizi (String) komutları

    movs, stos, lods

7) Program akış kontrol komutları

    jmp, call, ret, Jxx (şartlı dallanma komutları)

8) Diğer komutlar

    clc, stc, cmc

Veri Taşıma Komutları

Veri taşıma komutları bir değeri bir yerden başka bir yere taşımaya yarar. mov, xchg, lds, lea, les, lfs, lgs, lss, push, pusha, pushad, pushf, pushfd, pop, popa, popad, popf, popfd, lahf, ve sahf komutları veri taşıma komutlarıdır.

MOV komutu

Bu komutun kullanım şekilleri aşağıdaki gibidir.

                mov     reg, reg
                mov     mem, reg
                mov     reg, mem
                mov     mem, immediate data
                mov     reg, immediate data
                mov     ax/al, mem
                mov     mem, ax/al
                mov     segreg, mem16
                mov     segreg, reg16
                mov     mem16, segreg
                mov     reg16, segreg

MOV komutu assembly dilinde çok kullanılan bir komuttur. Yukarıdaki kullanım şekilleri için İngilizce ifadeler kullanılmıştır, çünkü internetten erişebileceğiniz komut seti referanslarında hep bunlar karşınıza çıkacak. Tüm komutlar için geçerli olan bu İngilizce ifadelerin Türkçe karşılıkları aşağıdaki gibidir.


    reg : register à kaydedici,

    mem : memory à hafıza (RAM-ROM veya Giriş/Çıkış portları olabilir)

    immediate data à acil adresleme ile kullanılan direkt veri

    segreg : segment register à segment kaydedicisi

    mem16 : memory 16 bit à 16 bitlik hafıza alanı (dw direktifi ile tanımlanan veriler)

    reg16 : register 16 bit à 16 bitlik kaydedici (AX, BX .. gibi)

 

MOV komutunu kullanırken yapamayacağınız iki şey vardır, bunlardan birincisi “mem, mem” tipinde bir kullanımdır. Yani hafızanın bir konumunda diğer bir konumuna doğrudan taşıma yapamazsınız. Bu işlemi yapmak için taşınacak veri önce mikroişlemci kaydedicilerinden birine getirilmelidir.

    MOV  sayi1, sayi2         ;yanlış kullanım

Yukarıdaki gibi bir komut satırı yazarsanız, derleyiciniz hata mesajı verir. Böyle bir işlemi yapmak için genel amaçlı bir kaydediciyi kullanmanız gerekir.

    MOV        AX, sayi1
    MOV        sayi2, AX       ;sayi1 ve sayi2 değişkenlerinin word türünden olduğunu varsayıyoruz.

MOV komutu ile yapamayacağınız ikinci şey ise segment kaydedicilerine doğrudan bir veri taşımaktır. Yani acil adresleme modunu segment kaydedicilerine uygulayamazsınız.

    MOV        DS, 1525h ; bu kullanım hatalıdır.

Segment kaydedicilerine bir değer yükleyebilmek için genellikle genel amaçlı kaydedicileri kullanılır. Ayrıca segment kaydedicilerine ancak 16 bitlik boyutunda değerler yüklenebileceğinden genel amaçlı kaydedicilerin 8 bitlik kısımlar değil 16 bitlik kısımları kullanılabilir.

    MOV        AX, 1525h
    MOV        DS, AX

Bunların dışında operandların boyutları eşit olmak zorundadır.

    MOV        AX, toplam  ; burada toplam değişkeninin boyutu kesinlikle word tipinde yani iki byte uzunluğunda olmalıdır.

Şayet acil adresleme kullanarak bir veri taşıyorsanız işlemci operandın boyutunu kaydediciye uyarlar.

    MOV        AX, 15h  ; Bu komut işlenince AX’in içinde 0015h değerini görürsünüz.

Dikkat edilemesi gereken diğer bir husus ise hafıza operandlarıdır. Örneğin MOV [BX], 5 gibi bir komut ile hafızaya neyin yükleneceği belli değildir (Burada BX kaydedicisine değil hafızaya taşıma yapıldığına dikkat edin) MOV [BX], 5 gibi bir komutla acaba hafızaya byte boyutunda bir 5 değerimi (05) yoksa word boyutunda bir 5 değerimi (0005) yüklenecek? Bunu kodlarınızda belirtmeniz gerekir. Derleyici bu komut satırına hata verir. Doğru kullanım aşağıdaki gibi olmalıdır.

                mov     byte ptr [bx], 5
                mov     word ptr [bx], 5
                mov     dword ptr [bx], 5       (*)
 (*) 80386 ve sonrası işlemcilerde kullanılabilir
mov byte ptr [bx], 5 satırını açıklayalım. Burada BX=0000 olduğunu varsayalım, böyle bir durumda ds:0000 adresine bir taşıma işlemi gerçekleşeceltir. Ama bu adresten itibaren 05’mi yoksa 0005’mi yoksa 00000005’mi taşınacaktır? İşte bunu ptr operatörü belirler. mov byte ptr [bx], 5 komut satırı için ds:0000 adresine 1 byte’lık bir veri yani 05 taşınır. Şayet operatör byte ptr değilde word ptr olsaydı o zaman ds:0000 ve ds:0001 adreslerine dırasıyla 05 ve 00 değerleri taşınacaktı.

XCHG komutu

xchg (exchange) komutu operandlarındaki değerleri yer değiştirir.

80x86 ailesi için dört değişik kullanım şekli vardır;

                xchg    reg, mem
                xchg    reg, reg
                xchg    ax, reg16
                xchg    eax, reg32              (*)
  (*) 80386 ve sonrası işlemcilerde kullanılabilir LDS, LES, LFS, LGS, ve LSS komutları

Bu komutlar 32 bitlik bir hafıza bölgesindeki değeri bir segment kaydedicisine ve bir genel amaçlı kaydediciye bir defada yükler. Kullanım formatı aşağıdaki gibidir;

                LxS     hedef, kaynak
Bu komutları aşağıdaki gibi kullanabilirsiniz;

                lds     reg16, mem32
                les     reg16, mem32
                lfs     reg16, mem32    (*)
                lgs     reg16, mem32    (*)
                lss     reg16, mem32    (*)
  (*) 80386 ve sonrası işlemcilerde kullanılabilir Reg16 genel amaçlı herhangi bir kaydedici olabilir mem32 ise double word boyutunda bir veri olmalıdır, bunu “dd” direktifi ile oluşturabilirsiniz. Daha önce bu komutlardan biri olan LES komutu için “X86 Assembly Dilinde Değişken Bildirimi -1” adlı makalede çok güzel bir örnek vermiştim. Erişmek istediğimiz adresin segment ve ofset bölümlerini birleştirerek bir değişken oluşturuyor sonrada bunu program çalışırken istediğimiz gibi kullanıyorduk.

LEA Komutu

LEA (Load Effective Address – Etkin Adresi Yükle) sadece offset adreslerini hedef operandına yükleyen bir pointer gibi düşünebilirsiniz. Genel kullanım formatı

                lea     dest, source   şeklindedir.                 lea     reg16, mem                 lea     reg32, mem      (*)   (*) 80386 ve sonrası işlemcilerde kullanılabilir. MOV komutunu da LEA komutu yerine kullanabilirsiniz, fakat hangi komutu kullanacağınıza adresleme moduna göre  seçmelisiniz. Bazen MOV komutu LEA dan daha hızlı çalışabilir, tüm bu bilgilere herhangi bir intel komut setinden faydalanarak bakabilirsiniz.

Daha önceki makalelerimizde ekrana bir karakter dizisini yazdırmıştık, bunun için kaynak kodumuzda ekrana yazdılıralacak olan veriyi aşağıdaki gibi tanımlamıştık;

    Dizi     DB "Merhaba Assembly",0Ah,0Dh,24h

Daha sonra bu dizinin adresini DX kaydedicisine yüklememiz gerektiğinde aşağıdaki komutu kullanmıştık;

    MOV      DX,OFFSET Dizi

Bu komutun yaptığı işi LEA kullanarakta yapabiliriz;

    LEA        DX, Dizi

PUSH ve POP komutları

80x86 push ve pop komutları Stack Memory (Yığın hafıza bölgesi) ile ilgili işlemlerde kullanılır. Yğın hafıza bölgesini sizler .exe tipi program hazırlarken .Stack direktifi ile belirliyorsunuz. İşte bu bölge genellikle programdaki dallanma veya altrutinlerin çalışması sırasında, dönüş adreslerinin ve bayrak kaydedicisinin durumlarını saklamak için kullanılır. Push komutu bu yığın olarak adlandırılan hafıza bölgesine verileri iterken, pop komutuda bu bölgeden veri almada kullanılır.

                push reg16                 pop reg16                 push reg32           (**)                 pop     reg32           (**)                 push segreg                 pop segreg          (CS hariç)                 push memory                 pop memory                 push immediate_data  (*)                 pusha                   (*)                 popa                    (*)                 pushad                  (**)                 popad                   (**)                 pushf                 popf                 pushfd                  (**)                 popfd                   (**)                 enter imm, imm    (*)                 leave                   (*)   (*) 80286 ve sonrası işlemcilerde kullanılabilir (**) 80386 ve sonrası işlemcilerde kullanılabilir
Push ve pop komutları kullanıldığında yığın hafıza bölgesinin işaretçisi olan SP kaydedicisi değişir. Tabiî ki bu yığına itilen veya yığından çekilen değerin boyutuna bağlıdır. Bu komutlar 2 veya 4 byte’lık değerler ile işlem yaptığından yığına 2 bytelık bir değer itildiğinde (mesela bu AX kaydedicisinin içeriği olabilir) SP’nin değeri 2 byte azalır. Şayet yığına 4 byte’lık değer itilirse SP’nin değeri 4 azalır. Unutulmaması gereken önemli bir hususta yığın hafıza bölgesine itilen en son değerin çekilecek olan ilk değer olmasıdır. Tabiî ki yığına birden fazla word ya da doubleword itildiyse aralardaki değerler ile işlem yapmak adresleme modlarıyla mümkündür fakat bu SP’de herhangibir değişiklik yapmaz. Yığın hafıza bölgesi ile ilgili unutulmaması gereken üç önemli kural vardır. Segment kaydedicilerinden olan SS yığın hafıza bölgesinin segment adresini gösterir. Yığına bir şeyler itildikçe SP azalır eökildikçe artar. SS:SP her zaman yığının tepesi olarak tabir edilen noktayı gösterir.
LAHF ve SAHF Komutları

Bu komutlar bayrakları AH kaydedicisine yükler veya AH’a yüklenen bayrak kaydedicilerinin durumlarını kayar nokta kaydedicisine ( floating point register ) yükler. Bu komutlar 8086 zamanından kalma ve günümüzdeki modern assembly programlarında pek kullanılmayan komutlardır.

Genişletme İşlemleri

Bazen byte boyutundaki bir değeri word boyutuna veya word boyutundaki bir değeri doubleword boyutuna genişletmek gerekebilir. Bu gibi durunlarda aşağıdaki komutlar kullanılır.

                movzx   hedef, kaynak       ;Hedef kaynağın iki katı büyüklüğünde olmalıdır.                 movsx   hedef, kaynak       ;Hedef kaynağın iki katı büyüklüğünde olmalıdır.                 cbw                 cwd                 cwde                 cdq                 bswap   reg32                 xlat   MOVZX, MOVSX, CBW, CWD, CWDE, ve CDQ Komutları cbw (convert byte to word) AL kaydedicisinin 1 byte’lık içeriğini AX’e genişletir. Şayet AL’deki değer pozitifse AH’ın tüm bitleri ‘0’ değerini alır. AL’deki değer negatifse AH’ın tüm bitleri ‘1’ olur.

               cbw
cwd (convert word to double word) komutu AX’in değerini DX:AX’e genişletir. CBW komutundaki kurallar bu komut içinde geçerlidir.

               cwd
Bu komut 80386 ve sonrası işlemcilere özeldir. CWD komutunda olduğu gibi word boyutundaki bir değeri double word boyutuna genişletmede kullanılır. CWD AX’i DX:AX’e genişletirken bu komut AX’i EAX’e genişletir.

               cwde
cdq komutu EAX kaydedicisindeki 32 bit’lik değeri EDX:EAX ‘e genişletir. Bu komutda 80386 ve sonrası işlemlerde kullanılır.

               cdq
 
Örnekler:
 
; AL’ deki 8 bitlik değeri 32 bitlik dx:ax’e genişletmek için
 
                cbw
                cwd
 
; AL’ deki 8 bitlik değeri 32 bitlik eax’e genişletmek için
 
                cbw
                cwde
 
; AL’ deki 8 bitlik değeri 64 bitlik edx:eax’e genişletmek için
 
                cbw
                cwde
                cdq
movsx komutuda yukarıdaki komutlara benzer iş yapar, kullanım formatları aşağıdaki gibidir.

                movsx   reg16, mem8                 movsx   reg16, reg8                 movsx   reg32, mem8                 movsx   reg32, reg8                 movsx   reg32, mem16                 movsx   reg32, reg16 Örnekler:

                movsx   ax, al          ;CBW komutunun yaptığı işi yapar.                 movsx   eax, ax         ;CWDE komutunun yaptığı işi yapar.                 movsx   eax, al         ;CBW ve CWDE komutlarının birlikte yaptığı işi yapar. movzx komutu movsx komutu gibi kullanılır fakat negatif değerleri genişletmek için kullanılmaz, çünkü movzx komutu genişletme işleminde sadece bitleri ‘0’ yapabilir. Bu komutun sonundaki zx harfleri İngilizcede zero extend yani sıfır ile genişlet gibi bir anlam taşır.

Tüm bu genişletme komutları genellikle aritmetik işlemlerde ve özellikle bölme komutlarında kullanılır.

BSWAP Komutu Bildiğiniz gibi x86 hafızası little endian yapıya sahiptir, bununla beraber big endian hafızaya sahip bilgisayarlarda çok sayıda mevcuttur. Örneğin Apple’ın Machintosh bilgisayarları big andian hafıza yapısına sahiptir. BSWAP komutu bu farklı hafıza sistemlerine sahip olan bilgisayarlar arasında veri haberleşmesi yapılması için kullanılır. BSWAP operandında belirtilen 32 bitlik kaydedicinin içindeki değeri byte-byte ters çevirir. Düşük değerlikli sekiz biri en yüksek değerlikli bölgeye, 8-15 arasındak bitleri 16-23 arasına, 16-23 arasındaki bitleri 8-15 arasına ve son olarak 24-31 arasındaki bitleride 0-7 arasına yerleştirir.

BU komut sadece 80486 ve sonrası işlemcilerde kullanılabilir. Kullanım formatı aşağıdaki gibidir.

               bswap   reg32  XLAT Komutu Genellikle tablo olarak tasarlanan dizilere erişmek için kullanılır. AL kaydedicisine tablonun elemanlarından birini yükler. Bu komutu aşağıdaki örneğe bakarak daha iyi anlayabilirsiniz.

    Tablo DB   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

Bu tablonun 11. elemanını AL’ye yüklemek istersek;

    MOV        AL, 0Ah                   ; İndeks değeri (0 dan 0Ah’a kadar 11 tane değer var)
    LEA         BX, Tablo                 ; BX’e (taban kaydedicisi) Tablonun ofset adresi yükleniyor
    XLAT                                     ; Tablonun 11. elemanına erişilip ASCII karakterin hex karşılığı AL’ye yükleniyor (AL=41h)

Şimdi yukarıda açıkladığımız komutlardan birkaçını kullanarak bir program yazalım ve daha sonra da inceleyelim. Öncelikle Push ve Pop komutlarını DS kaydedicisinin değerini belirlemek için kullanabilirim. .exe tipi programlarda DS kaydedicisinin değerini belirlemek için bu güne kadar hep aşağıdaki iki satırı kullandık,

    MOV          AX, @data
    MOV          DS, AX

Yığın komutlarınıda veri taşımak için kullanabileceğimizden,

    MOV          AX, @DATA
    PUSH         AX
    POP           DS

Yukarıdaki üç satırda DATA segmentin adresini önce AX kaydedicisine yükledik, sonra bu kaydedicideki değeri yığına ittik son olarakta yığından bu değeri çekip DS kaydedicisine yükledik.

Kullandığım sistemin saat bilgisini ekrana yazdırmak istiyorum. Tabiî ki bu gibi işlemler için hali hazırda DOS’un kesmeleri mevcuttur. Fonksiyon 2Ch sistem zamanı ile ilgili bilgileri işlemcinin kaydedicilerine getirir.

    MOV        AH,2Ch
    INT           21h

Bu komutlar işlenince CX ve DX kaydedicileri saat bilgisi ile yüklenirler,

    CH = saat CL = dakika DH = saniye DL = salise

Kaydedicilerin içindeki değerlerin binary olduğunu ve debugger programlarında bu değerlerin hexadecimal formatta göründüğünü unutmayalım. Biz bu programda kullanıcı ekranına desimal formatta değerler yazdıracağımızdan ya çevirme işlemi yapacağız yada tablo oluşturup hex bilgilerin karşılığına tablodan bakacağız.

Çevirme işlemleri için çarpma, bölme gibi komutları bilmeniz gerekir ama henüz o komutlarla ilgili örnekler çözmedik. Bunun yerine biz hex-decimal tablolar oluşturup bu tablolardan desimal değerleri bulalım ve ekrana yazdıralım. Fakat tabloların sınırlarını belirlemek için elimizdeki bilgiyi iyi tanımamız gerekir.

En büyük saat bilgisi 23:59 yani  0 ile 59 elemanlarını kapsayan bir tablo oluşturmam yeterli.

               SaatTablo                  DB          "00$","01$","02$","03$","04$","05$","06$","07$","08$","09$"
                                              DB          "10$","11$","12$","13$","14$","15$","16$","17$","18$","19$"
                                              DB          "20$","21$","22$","23$","24$","25$","26$","27$","28$","29$"
                                              DB          "30$","31$","32$","33$","34$","35$","36$","37$","38$","39$"
                                              DB          "40$","41$","42$","43$","44$","45$","46$","47$","48$","49$"
                                              DB          "50$","51$","52$","53$","54$","55$","56$","57$","58$","59$"

Yukarıdaki tablo bize 60 elamanlı gibi görünebilir fakat hafızada 60*3=180 byte yer kaplar, çünkü x86 hafızası byte adreslenebilir ve her rakam veya karakter hafızada 1 byte’lık yer kaplar.

Diyelim ki CH’taki saat bilgisi 0Ah, bu saat 10 demek. Tabloda “10$”  olan kısım acaba tablonun hangi adresidir? Sayacak olursanız 30. elemanın 1 31. elemanın 0 yani 30 elemandan itibaren 10 değerinin mevcut olduğunu görürsünüz. Tabloda her saat değeri için 3 byte’lık değer ayrılmıştır ve bu programda CH veya CL deki değerler yardımıyla indeks adresi hesaplanırken 3 ile çarpmak gerekir.

CH’ta saat 10’u temsilen 0Ah değeri bulunuyorsa 0Ah*3 = 1Eh = 30 hesabı yapılmalıdır. Tüm bu işlemleri yapıp ekrana yazdırılıcak değeride DX kaydedicisine yüklemeliyiz. Çünkü ekranda bir karakter dizisini yazdırmak için INT 21h’ın 9. fonksiyonu karakter dizisinin başladığı adresi DX kaydedicisinde bulunmasını ister. Tüm bu işlemleri yapan kod satırları aşağıdaki gibidir.

               MOV      AL, CH                  ;Şimdi saat bilgisi,
               MUL       Uc                       ;3 ile çarpılarak tablodaki desimal karşılığı bulundu.
               MOV      DI, AX                   ;Bu adres indeks olarak düşünüldüğünden DI ya yüklendi.
               LEA       DX, SaatTablo[DI]   ;Ve BX’e saat bilgisinin desimal karşılığı olan tablo konumu yüklendi.

MUL komutunu önümüzdeki makalelerde inceleyeceğiz, çok fazla kullanım formatı mevcuttur. Bizim için burada, sadece CH veya CL deki değerleri 3 ile çarpsın yeter. Fakat MUL komutu sadece AL deki değeri bir değişken yada AL kaydedicisi ile çarpabildiğinden önce CH yada CL deki bilgileri AL’ye taşımamız gerekiyor. Daha sonra 3 değeri ile çarpıp tablodan adresi buluyoruz. Tabiî ki Uc bir değişken ve data segmentinde tanımlı olmalıdır.

               Uc           DB          3

Al deki değer 3 ile çarpıldığında sonuç 16 bitlik AX kaydedicisinde saklanır. Bu noktadan sonra bu adresi DX kaydedisine yükleyip ekranda string yazdırma kesmesini çağırırsak işlem tamam olacaktı ama, SaatTablo taban adresine göre hesapladığımız indeks adresi halen AX kaydedicisinin içinde ve LEA  DX, SaatTablo[AX] gibi bir komut satırı kullanamam çünkü böyle bir adresleme modu mevcut değil. Indeks olarak kullanılacak adresler 8086 assembly dilinde SI, DI veya BX kaydedicilerinin birinde olmalıdır, bu yüzden bizde hesapladığımız indeks değerini DI ya yükledik. Son olarak ekranda bir string yazdıracağımızdan DX kaydedicisinin içine yazdıracağımız stringin başlangıç adresini atarak ve daha önce de kullandığımız INT 21h fonksiyon 9h ı kullanabiliriz.

Bununla beraber “:” karakterinide saat bilgisini yazdırırken saat ile dakika arasına yerleştirelim, tabiî ki bu bilgide data segmentinde bir adreste saklı kalsın.

                Ayirac               DB          ‘:’

Birde saat kelimesini data segmentte tanımlayalım,

                Saat                   DB          ‘Saat $’

Şimdi kabataslak ne yapacağım belli oldu, programımın algoritmasını da yazdıktan sonra kodlarımı yazmaya başlayabilirim.

1-       Ekrana “Saat” yazdır

2-       Sistem saatini ilgili kaydedicilere yükle

3-       Tablodan saat bilgisinin desimal karşılığını bul

4-       Ekrana yazdır

5-       : karakterini ekrana yazdır

6-       Sistem dakikasının karşılığını bul

7-       Ekrana yazdır

8-       Dur


Şekil 1 - Saat bilgisini ekranda gösteren program.

 


Şekil 2 - Programın ekran çıktısı.

Elbette bu program daha kısa veya pratik bir şekilde yapılabilirdi. Bunun için komut bilgimizi genişletmeliyiz. Ayrıca değişken bildirimlerini de şu ana kadar tam olarak anlatmadım. Bu konularla ilgili makalelerimiz yolda fakat şu anda sizlerin mevcut bilgilerinizle bu programa birde salise kısmını ekleyebilmeniz gerekir.

Bu programa ait assembly kaynak kodlarını buradan, kodların derlenmiş halini buradan download edebilirsiniz. Bir sonraki makalede görüşmek üzere.

Makale:
80x86 KOMUT SETİ (Bölüm 1) Assembly ve X86 Programlama Eren Erener
  • Yazılan Yorumlar
  • Yorum Yaz
ARA
7
2010
çok güzel bir anlatımdı teşekkür ederim
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor