Bu makalemde 80x86 
komutlarını değişik örneklerle anlatmaya devam edeceğim. Bu makalede toplama ve 
çıkartma işlemlerine bir nokta koyup çarpma ve bölme işlemlerine bir giriş 
yapmak istiyorum.
  
80x86 KOMUT SETİ (Bölüm 3)
  
NEG komutu
  
NEG negatif 
kelimesinin kısaltmasıdır. Tek operandı vardır. Kullanım formatı aşağıdaki 
gibidir.
  
        
neg    reg 
        neg    mem
  
yani operandı 
herhangi bir kaydedici veya hafıza adresi olabilir. Yaptığı iş operandın 
değerinin negatifini almaktır. Daha doğru bir deyişle operandını 0dan çıkartır. 
Binary düzende düşünecek olursanız 1lein yerine sıfır 0ların yerine 1 getirir 
ve bu sonuca 1 ekler.
  
        
mov    al,0fh 
        neg    ax
  
yukarıdaki işlemden 
sonra AXin içeriği F1h olacaktır. 
  
0Fh    
= 0000 1111 
tersi  = 1111  0000 
1111 0000 +1 = 1111 0001 = F1h 
 
Bu komutun ne amaçla kullanılabileceğini makalenin sonlarına doğru 
anlayacaksınız.
  
MUL ve IMUL 
Komutları
  
MUL çarpma IMUL ise 
işareti dikkate alarak çarpma işlemlerini yapar. Kullanım formatı aşağıdaki 
gibidir.
  
İşaretsiz çarpma:
 
 
        mul    reg 
        mul    mem 
 
İşaretli çarpma:  
 
        imul    reg 
        imul    mem 
        imul    reg, reg, 
imm   (*) 
        imul    reg, mem, 
imm (*) 
        imul    reg, imm         
(*) 
        imul    reg, reg          
(**) 
        imul    reg, mem        
(**) 
         
 
*-    Sadece 286 ve sonrası işlemcilerde. 
**-  Sadece 386 ve sonrası işlemcilerde. 
 
  
IMUL komutunun 286 
ve 386 dan sonraki kullanım formatlarına bakacak olursanız, bu güne kadar 
gördüğümüz formatlardan biraz farklı olduğunu görürsünüz. Bu kullanım şekilleri 
programcıların kafasını biraz karıştırmakla beraber tek bir komut satırı ile 
çabucak çarpma işlemini yapmasını sağlar. Nede olsa Intel karmaşık komut setini 
benimsemiştir.
  
Çarpma komutları 
bayt-bayt, word-word veya Doubleword-Doubleword çarpma yapabilir. Tabi ki 
Doubleword çarpım için 386 ve sonrası işlemci kullanmanız gerekiyor, çünkü 32 
bitlik kaydediciler 386 ile birlikte gelmiştir.
  
Ayrıca çarpma işlemi 
toplamadan daha büyük sonuçlar çıkarabilir. Yani 2 basamaklı bir değeri başka 
bir 2 basamaklı değer ile toplarsanız sonuç en fazla 3 basamaklı çıkarken 
çarpmada bu 4 basamağa kadar çıkabilir. Daha fazla basamaklı sayıların 
çarpımında sonuç çarpılan veya çarpandan çok daha fazla basamaklı çıkabilir. Bu 
gerçeği göz önüne alarak işlemci tasarımcıları sonucu her zaman çarpan ve 
çarpılanın boyutundan daha büyük bir kaydedicide saklama yoluna gitmişlerdir. 
Bunları aşağıdaki şekil ve açıklamalarla daha iyi anlayacaksınız.
  
Byte Çarpma
  
 
  
27h ile 17hı 
çarpmak için;
  
        
mov    al, 27h 
        mov    dl, 17h 
        mul     dl
  
komutlarını 
kullanabilirsiniz. Burada "mul dl" komutu ile DL*AL işlemi yani bu 
kaydedicilerdeki değerler olan 17h ve 27h sayıları çarpılır. Peki sonuç nerede? 
Yukarıdaki şekle baktığınızda sonucun AX içinde olacağını görebilirsiniz. Bu 
çarpma işleminden sonra AXte 0381h değeri görülür.
  
Pratik olarak 8 
bitlik bir değerin karesini almak için;
  
        
mov    al,sayi 
        mul     al
  
komutlarını 
kullanabilirsiniz.
  
Word 
Çarpma
  
 
  
Bu tür bir çarpma 
işleminde operand AX ile çarpılır ve sonuç DX-AX kaydedicilerinden okunur. DXte 
daha önce ne olduğu önemli değildir çünkü çarpmadan sonra buraya sonucun yüksek 
değerlikli byteı yerleşir. Sonucun düşük değerlikli byteı ise AX 
kaydedicisinde saklanır.
  
Burada dikkat 
ederseniz çarpma işlemiyle birlikte AX kaydedicisindeki "çarpılan" da 
kaybedilecektir. Benim tavsiyem bu tür çarpmalarda çarpan ve çarpılanı birer 
değişken olarak programınızın data segmentinde tanımlamanızdır. Aşağıdaki 
örnekleri inceleyin,
  
100h ile 2345h 
değerlerini çarpalım;
  
        
mov    ax, 2345h 
        mov    bx, 100h 
        mul     bx
  
bu işlemden sonra DX=0023h 
ve AX=4500h olur. Yani asıl sonuç olan 234500h değerinin yüksek değerlikli 
wordu DXte düşük değerlikli kısmıda AXte görülür. Fakat çarpılan değer yani 
2345h bu işlemden sonra kaybolacaktır. Şayet bu çarpılan değer sizin için 
önemliyse;
  
        
carpilan    db    2345h 
        .. 
        .. 
        .. 
        
mov    ax, carpilan 
        mov    bx,100h 
        mul     bx
  
böylece 2345h değeri 
daima "carpılan" ismi ile hafızada korunur. Aynı şeyi tabi ki çarpan için yani 
100h değeri içinde yapabilirsiniz.
  
        
carpilan    db    2345h 
        carpan     db    
100h 
        .. 
        .. 
        .. 
        
mov    ax, carpilan 
        mov    bx, carpan 
        mul     bx
  
Double Word Çarpma
  
Double word 
boyutundaki verilerin çarpımında da word dekine benzer bir yapı kullanılır. 
Çarpılan değer EAX kaydedicisine yerleştirilip, MUL veya IMUL komutunun peşinden 
gelen operand ile bu değer çarpılır. Daha sonra elde edilen sonucun yüksek 
değerlikli doublewordu EDXte düşük değerlikli doublewordü ise EAXte 
saklanır. Yani sonuç 64 bitliktir.
  
 
  
        
carpilan    dd    12345678h 
        carpan     dd    
34522344h 
        .. 
        .. 
        .386 
        .. 
        .. 
        
mov    ax, carpilan 
        mov    bx, carpan 
        mul     bx
  
Yukarıdaki örnekte 
sonuç olarak işlemci 03B878D610295FE0h değerini hesaplar. Bu çarpma işleminden 
sonra EDX=03B878D6h ve EAX=10295FE0h olur. 
  
Buradaki .386 32 
bitlik kaydedicileri kullanmak için assemblera verilen bir direktif (talimat) 
dır. EDX ve EAX gibi 32 kaydedicilerin 32 bitlik alanlarını kullanmak için nu 
talimatı vermeniz gerekir. 32 bitlik programlama, 16 bitlik programlama nedir 
bunlar? Şimdilik sadece 32 bitlik programların 16 bitliklere göre daha avantajlı 
olduğunu görebilirsiniz. Çünkü 32 bitlik programlama ile kaydedici boyutlarımı 2 
katına çıkıyor ve bir kaydedicide hesaplayabileceğimiz değerlerde aynı oranda 
artıyor, bu işlemi 16 bitlik bir programlama ile de halledebilmemize rağmen 2 
katı daha fazla komut yazmamız gerekir.
  
MUL komutu bayrak 
kaydedicisinin C ve O bitlerini etkiler. Bu bayraklar beraber 
değerlendirildiğinde aşağıdaki sonuçlar çıkartılır.
  
1- Byte boyutundaki 
bir operand AL ile çarpılırsa sonuç AXte görülür. AH=0 ise C ve O sıfır olur, 
aksi durumlarda bu bayraklar set (1) olur.
  
2- Word çarpmada C 
ve O sıfır ise DXte sıfır demektir, aksi durumlarda bu bayraklar set olur.
  
3- Double word 
çarpmada ise C ve O sıfır ise EDXte sıfır demektir, aksi durumlarda bu 
bayraklar yine set olur.
  
Yukarıdaki üç durum 
soldaki sıfırların çarmada bir değeri olmadığından, sonucu optimize etmenize 
yardımcı olacaktır.
  
IMUL 
ile Diğer Çarpma Formatları
  
IMUL (Integer 
Multiplication) komutu ile yukarıdaki MUL komutu için verilmiş kalıpları 
kullanabilirsiniz, bununla beraber IMUL komutuna özel çok operandlı kullanım 
formatlarıda mevcuttur. Tüm kullanım formatları bu makalenin başında verildiği 
gibidir fakat kaydedicilerin 8 16 ve 32 bitlik durumları da göz önüne almamız 
gerekir. Şimdi henüz açıklamadığımız 286 ve 386 sonrası işlemcilerde 
kullanılabilen komut formatlarını aşağıdaki örneklerle inceleyelim.
  
imul operand1, 
operand2, imm     ;Genel kullanım formatı 
 
        imul    reg16, reg16, 
imm8 
        imul    reg16, reg16, 
imm16 
        imul    reg16, mem16, 
imm8 
        imul    reg16, mem16, 
imm16 
        imul    reg16, imm8
 
        imul    reg16, imm6 
        imul    reg32, reg32, 
imm8       (*) 
        imul    reg32, reg32, 
imm32     (*) 
        imul    reg32, mem32, 
imm8     (*) 
        imul    reg32, mem32, 
imm32   (*) 
        imul    reg32, imm8                
(*) 
        imul    reg32, imm32              
(*) 
 
* Sadece 80386 ve sonrası işlemcilerde kullanılabilir
  
Yukarıdaki komut 
formatlarının 3 operandlı olanları
  
        
operand1 := operand2 x imm
  
ve 2 operandlı 
olanlarıda 
  
        
operand1 := operand1 x imm
  
şeklinde çalışır. 
Her zaman son kullanılacak olan operandın "imm" yani sayısal bir değer olduğuna 
dikkatinizi çekerim.
  
        
mov    bx, 4        ; BX = 
0004h 
        imul    ax, bx, 3   
; AX = 4 * 3 = 000Ch
  
Bu komutlar ile 8x8 
bit çarpım söz konusu değildir, imm8 olarak yukarıda gördüğünüz operand sadece 
komutunun makine kodunun olmasını sağlar. Ayrıca bu çarpma işlemlerinde sonucun 
boyutu operandta belirtilen kaydedicilerin boyutuyla aynıdır, yani makalenin 
başında anlattığımız mul komutu gibi sonuç operandın 2 katı olmaz. Bu durumda 
sonucun hedef kaydediciye sığmaması durumuna karşı C ve O bitleri birlikte kontrol 
edilmelidir, bu durumlara Intelin komut setinden bakabilirsiniz.
  
Bununla beraber bu formattaki çarpma komutları Z bitini her zaman 
doğru bir şekilde etkilemeyebilir, şayet sonucun sıfır olup olmadığı sizin için 
önemli ise ancak sonucu sıfır ile karşılaştırdıktan sonra Z bitini kontrol 
etmelisiniz. Aynı şekilde sonucun işaretini öğrenmek için işaret bayrağı yerine 
C ve O bitlerinin sıfır olup olmadığı kontrol 
edilmelidir.
  
IMUL komutu için 
Intelin 80286 ve sonrası işlemcilere koyduğu bu adresleme biçimleri çok boyutlu 
diziler ile yapılan işlemleri hatırı sayılır biçimde kolaylaştırmıştır. Bu 
konuya çok boyutlu dizileri ve karmaşık veri yapılarını anlatırken bir daha 
değinmeyi düşünüyorum.
  
DIV ve IDIV Komutları
  
DIV division yani 
bölme kelimesinin kısaltmasıdır. Bölme işlemi çarpmanın tersine bölünene göre 
küçük sonuç üretir, bu yüzden bu komutları kullanırken bölünenin boyutu 
bölenin boyutunun iki katı olmak zorundadır, an azından Intel bu komutlar için 
böyle bir form öngörmüştür. Bu yüzden bölünenin boyutu en az word türünde 
olmalıdır, çünkü x86 Assembly dilinde en küçük veri tipi bytedır. Bu durumda 
byte türünden  bir değeri bölmek isterseniz bunu CBW komutu ile word 
boyutuna dönüştürmeniz gerekir, hatırlarsanız bu tür komutları daha önceki 
makalelerimizde açıklamıştık.
  
Div ve idiv 
komutlarının genel kullanım formatları aşağıdaki gibidir.
  
        
div    reg        ; İşaretsiz 
çarpma 
        div    mem 
 
        idiv    reg       
; İşaretli çarpma 
        idiv    mem
  
Wordu Bytea Bölmek
  
 
  
Örnek: 10h:3h 
işlemini yapmak istiyoruz, bu değerlerin ikisinin de byte türünden olduğunu 
varsayalım;
  
        
mov    al, 10h 
        mov    bl, 03h ; bl 
yerine başka bir kaydedicide olabilir!   
        cbw              
; 10h şimdi 0010h ve AXte 
        div     bl        
; ax, blye bölündü
  
bu işlemden sonra AX, 
0105h olur. AHtaki 01h kalan ve ALdeki 05h ise bölümdür. Nitekim 16nın (yani 
10h) 3e bölümü ile de bu sonuç üretilir. Bu tür bölme işleminde elde 
edebileceğiniz en büyük bölüm 255 (FFh işaretsiz değerler için) yada 127 (7Fh 
işaretli değerler için) değerleridir.
  
Doublewordu Worde Bölmek
  
 
  
Bu tür bölme 
işleminde elde edebileceğiniz en büyük bölüm 32767 (FFFFh işaretsiz değerler 
için) yada 16383 (7FFFFh işaretli değerler için) değerleridir.
  
Quadwordu Doubleworde Bölmek
  
 
  
Peki ya sonuç tam değilse?
  
Mesela 11hı (yani 
17yi) 3e bölerseniz sonuç normalde 5,666... şeklinde olur, bu işlemi div 
komutu ile yaptığınızda ise AXte 0205h değerini görürsünüz, yani bölüm 5 ve 
kalan 2. Özetle 17nin içinde 5 tane 3 ve 1 tanede 2 vardır ve div ve idiv 
komutları tamsayı bölme işlemlerini gerçekleştirebilir. Ondalıklı bölme 
işlemleri için floating point kaydedicileri kullanılır ve bu kaydediciler 
matematik işlemcisinin içindedir. 80486 DX işlemcisine kadar matematik işlemci 
normal işlemcinin yanına opsiyonel olarak konulurdu mesela işlemci 80386 ise 
matematik işlemcisi 80387 olurdu. Artık matematik işlemcisi normal işlemcinin 
içine gömülü olarak geliyor. Bu arada floating point ünitelerini kullanmak için 
yüksek seviyeli assembly kodları yazmak gerekir ve bu iş bizim için henüz çok 
erken. Fakat kalanı 10 ile çarpıp sonrada bölünen ile karşılaştırıp şayet 
bölünenden büyükse tekrar bölene bölme işlemine gidebilirsiniz, aynı kağıt 
üzerinde normal bölme işlemi yapar gibi, fakat floating point ünitelerini 
kullanmak inanın bu işten daha pratiktir ve daha kolay sonuç verir.
  
Malesef Tüm Sonuçlar Binary
  
Toplama, çıkartma, 
çarpma ve bölme komutlarını gördük, artık bu komutları kullanarak basit bir 
hesap makinesi programı yazmak isteyebilirsiniz, böyle bir programı yazmaya 
başladığınızda karşınıza sonuçları ekranda desimal formatta göstermek gibi bir 
problem çıkacaktır. Evet ekrana yazdırmak için daha önce programlar yazdık fakat 
bunu sadece stringler ile gerçekleştirdik. DB direktifi ile deklare edilen 
kelime katarları (stringler) hafızada byte-byte ve ardışık olarak saklanır aynı 
zamanda bu bytelar elbette harflerin veya sayıların ASCII kod karşılıklarıdır. 
8086 komut seti (bölüm 1) başlıklı makalemizde saat programı yapmıştık ve 
kaydedicilerde elde ettiğimiz sonuçları  bir tablo vasıtasıyla ASCII 
karakterlerini ekranda göstermiştik. Bu yöntem sıkça kullanılmaz, hatta daha 
önce bu iş için bu yöntemi kullanan bir program görmedim diyebilirim.
  
Representation yani 
gösterme veya sunum işlemi çok geniş bir yelpazede incelenebilir, bu tamamen 
kullanıcının hayal gücüne kalmış bir olaydır. Benim burada anlatmaya çalışacağım 
olay ise ekran text modunda iken hafızadaki binary ifadelerin ASCII karakter 
karşılıklarını ekranda göstermek olacaktır.
  
Diyelim ki bir işlem 
yaptınız ve sonucunu 20h (32) olarak AL kaydedicisinde saklamayı başardınız ve 
bunu ekranda göstereceksiniz, bunu direk olarak ekrana yazdırırsanız sadece 
imleci 1 kez ilerletmiş olursunuz çünkü 20h ascii kod tablosunda space yani 
boşluk karakterine karşılık gelir, klavyedeki en büyük tuş yani. Peki 32yi nasıl 
yazdıracağız? Unutmayın ki ascii kod tablosunda sadece rakamların, harflerin ve 
bir dizi kontrol karakterinin kod karşılıkları vardır sayıların kod karşılıkları 
yoktur. Bu bağlamda biz 32 yi değil 3 ve 2 yi yan yana ekranda göstermeyi 
düşünmeliyiz. Ama şu anda ALde ne 3 ne 2 var sadece 20h var. Diğer bir gerçek 
3un ascii kod karşılığı 33h ve 2 nin ki ise 32h dır. 30h ile 39h arası ascii 
kod tablosunda rakamlar için ayrılmıştır.
  
şimdi ekrana 
sırasıyla 33hı ve 32hı gönderirsek kullanıcı 32 yi görecektir. Problemi 
özetleyelim elimizde bir baytlık 20h var ve bizim bunu 2 byte lık 3332h dizisine 
dönüştürmemiz gerekiyor. Keşke bir komut bu işlemi bizim yerimize yapsa!
  
Böyle bir komut 
varmı yokmu oraya geleceğiz ama 20h ile 3332h arasında güzel bir bağ var. 20h ı 
0ah yani 10a bölsek zaten hexden decimale dönüşüm işlemi yapmış oluruz;
  
        
mov    ax, 20h 
        mov    bl, 0Ah 
        div     bl            
;AX=0203 yapar.
  
Keşke AXteki 0203h 
değerinde 0ların yerine 3 gelseydi;
  
        
or    ax,3030h    ;AXteki 0203h artık 3233h oldu.
  
birde al ile ahı 
yer değiştirsek! Acaba buna gerçekten gerek var mı? Hatırlarsanız ekrana bir 
string yazdırmak için DOS kesmelerinden 09h nolu fonksiyonunu kullanmıştık ve bu 
fonksiyon hafızadaki stringleri yazdırıyordu, yani biz AXteki bu 3233h değerini 
önce bir hafızaya atalım sonra 32h ile 33hın yerini değiştirmek gerekiyor mu 
düşünürüz;
  
        
mov    sonuc, ax    ; sonuc=3332h olur.
  
x86 tabanlı 
işlemciler hafızayı adreslerken little endian byte sıralamasını kullanırlar, bu 
yüzden aldeki düşük değerlikli byte hafızanın düşük numaralı adresine axteki 
yüksek değerlikli byteta hafızanın yüksek numaralı adresine yerleşmiş olur, 
böylece ax ile alnin içeriklerini takas etmemize de gerek kalmaz. Artık sonuc 
değişkenini referans göstererek ekrana yazdırma kesmesini kullanabilirsiniz.
  
        
lea      dx,sonuc 
        mov    ah,9 
        int      21h
  
AAA,  AAS Komutları
  
Klavyeden giriş 
yapıldığında, basılan tuşa ait kod hafızada ascii formatta saklanır, 
mikroişlemci hesaplamaları binary yapar bu yüzden asciiden binaryye dönüşüm 
yapmak gerekir. Şayet ekrana bir karakter basılacaksa bu karakter ekrana 
gönderilmeden önce ascii forma dönüştürülmelidir.
  
 
  
Bizler günlük 
yaşamımızda desimal değerleri kullanırız, bu desimal değerleri hafızada binary 
rakamlar olan 1 ve 0ları kullanarak gösterebiliriz, buna BCD (Binary Coded 
Decimal) kodlama diyoruz. Desimal numaralar hafızada BCD olarak gösterilmenin 
yanında ASCII olarakta gösterilebilir. İşte AAA, DAA, AAS gibi komutları bunun 
için kullanıyoruz.
  
Örneğin klavyeden 
girilen 1234 hafızada 31 32 33 34 olarak ASCII formda saklanır. BCD gösterimin 
ise iki farklı çeşidi vardır, bunlar packed BCD (paketlenmiş BCD) ve unpacked 
(paketlenmemiş) BCDdir.
  
1234 hafızada 01 02 
03 04 byte dizisi olarak saklanırsa bu paketlenmemiş BCDdir, şayet aynı değer 
hafızada 12 34 byte dizisi olarak saklanırsa bu da paketlenmiş BCDdir. AAA, AAS, 
AAD ve AAM komutlarının hepsi ascii değerlere dönüşüm için kullanılır. Bu 
komutların operandı yoktur AL kaydedicisindeki değerleri dönüştürürler.
  
AAA (Ascii Adjust 
After Addition) komutu toplama komutundan sonra sonucu ascii ye ayarlar. 
Aşağıdaki örnekleri inceleyin;
  
   
34h = 0011 0100b 
   35h = 0011 0101b 
+_______________ 
   69h = 0110 1001b
  
  
Sonuç 09 
olması gerekir AAA komutu 6 değerini siler. Sonuç AL’de 09 olarak görülür.
  
   
36 = 0011 0100 
   35 = 0011 0101 
+_______________ 
   6B = 0110 1011
  
  
Sonuç 11 
olması gerekir AAA komutu B değerinin yerine 1 koyar ve toplama sonucu 9 
değerini aştığından AH kaydedicisine de 1 koyar, yani AX = 0101 olur.
  
Tüm bu 
işlemlerden sonra OR komutunu kullanarak sonucu ASCII gösterim için 
hazırlayabiliriz.
  
        SUB    
AH, AH       ; AH temizleniyor  
       
MOV   AL, 6          ; 
ilk değer ALde   
       
ADD    AL, 8         ; AL 
+ 08h işlemi yapıldı sonuç 0Eh 
       
AAA                    
; AX = 0104h 
       
OR     AL,30h       ; AL = 34h
  
34h artık ascii 
olarak 4 demektir. Tabi burada AH kaydedicisini de kontrol edip şayet 01 ise bu 
değeri de 30h ile OR işlemine tabii tutmalıyız. Bu tür işlemler için genelde 
ekrana tek bir karakter basma fonksiyonu kullanılır yani ALdeki değer teker 
teker ekrana bastırılır. Henüz mantıksal komutları görmedik bu yüzden aşağıdaki 
programı tam olarak anlamayabilirsiniz, bu yüzden açıklamalara dikkat edin.
  
 
  
  
  Şekil  - 
Makine dilinden insan diline dönüşüm
  
Pekte güzel bir 
ekran çıktısı olmasa da bu program dönüşümleri anlamak için iyi bir örnektir. 
Yukarıdaki şekilde program ilk çakıştırıldığında klavyeden sırayla 2 ve 3 
girilmiş ve sonuç 5 olarak ekrana basılmış. Daha sonra 7 ve 8 değerleri girilmiş 
ve sonuç 15 olarak ekrana basılmış. Gerçektende sonuçlar doğru :) Unutulmaması 
gereken bir nokta AAA komutunun C bitini etkilediğidir, şayet AAA komutundan 
önceki bayrakların durumu sizin için önemliyse bayrakların durumunu saklamanız 
gerekir.
  
AAS (Ascii Adjust 
after Subtract) komutuda AAA gibi çalışır, çıkartma komutundan sonra sonucu 
ASCIIye ayarlamak için kullanılır. AAS komutu sekiz bitlik AL kaydedicisinin 
yüksek değerlikli 4 bitini kontrol eder, şayet AF bayrağı 1 ise (başka bir 
deyişle bu 4 bit Ah...Fh arasında ise) ALden 6, AHtan 1 çıkartılır. AHtan 1 
çıkartmak normalde 00 olan AHı FF yapmak yani rakamın negatifliğini ayarlamak 
demektir.
  
        
mov    al,35h    ; ascii 5 
        sub     al,31h    
; 5 - 1 = 4 
        aas                
; AF=0 olduğundan bir değişiklik olmaz sonuç hala 04h 
        or      
al,34h    ; ascii 4
  
sonucun negatif 
çıktığı bir örnek;
  
        
mov    al,34h    ;ascii 4 
        sub     al,38h    
;ascii 8 -- sonuç FCh (negatif) 
        aas                 
; AX = FF06 (yanlış sonuç)
  
yukarıdaki gibi bir 
durumda SUB komutu ile A ve C bayrakları set (1) olur. Bu durumda sonucu 
doğrudan 30h ile OR işlemine tabi tutmak hatalı olacaktır. FCh sonucu desimal -4 
değerine eşittir bu yüzden burada programcı OR komutu ile doğru ascii değeri 
ekrana yazdırmadan önce NEG komutu ile tersini alabilir. Bu durumda sonuc 4 
olacaktır. Tabiki bu 4 değeri ekrana yazdırılmadan önce önüne - işareti 
konulmalı.
  
            
mov    al,34h 
            sub     
al,38h 
            jnc      
devam 
            neg     
al 
devam:  aas 
            or       
al,30h
  
yukarıdaki kod 
parçası sonuç negatif olsa da pozitif olsa da, sonucun mutlak değerini doğru bir 
şekilde ascii değere dönüştürür.
  
Unutmayalım ki 
klavye bize ekran text moundayken daima ascii değerler verecektir, bu çarpma ve 
bölme işlemlerinde de problem oluşturur. Klavyeden girilen değerlere sanki 30 
eklenmiş gibi geleceğinden çarpma işleminin sonucu girilen değerde bir 
modifikasyon yapmadığımız sürece yanlış hesaplarız. Bu tür modifikasyonları 
yapmak için başka mantıksal komutlara ihtiyacımız olacak, bu yüzden bu komutları 
anlatmadan 
DAA, DAS, AAD ve AAM gibi komutları açıklamak istemiyorum.
  
Gelecek makalemde Intelin komut setini anlatmaya devam edeceğim, bir sonraki 
makaleye kadar hoşçakalın.
  
                
                Makale: 
                80x86 KOMUT SETİ (Bölüm 3) Assembly ve X86  Programlama Eren Erener 
             |