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: bitlik degeri degerlikli ekrana hafizada islemi komutlari komutu kullanim reg16 reg32 sonrasi sonucu sonucun yerine 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 : 23.2.2006
Okunma Sayısı : 71726
Yorum Sayısı : 4     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
Turhal Temizer
Conda install environment.yml Package 24.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 24.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 24.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 24.11.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 3)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
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ı 0’dan çıkartır. Binary düzende düşünecek olursanız 1’lein yerine sıfır 0’ların yerine 1 getirir ve bu sonuca 1 ekler.

        mov    al,0fh
        neg    ax

yukarıdaki işlemden sonra AX’in 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 AX’te 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. DX’te 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 word’u DX’te düşük değerlikli kısmıda AX’te 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 doubleword’u EDX’te düşük değerlikli doubleword’ü ise EAX’te 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 assembler’a 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ç AX’te 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 DX’te sıfır demektir, aksi durumlarda bu bayraklar set olur.

3- Double word çarpmada ise C ve O sıfır ise EDX’te 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 Intel’in 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 Intel’in 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ünen’e göre küçük sonuç üretir, bu yüzden bu komutları kullanırken bölünen’in boyutu bölen’in 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 byte’dı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

Word’u Byte’a 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 AX’te
        div     bl        ; ax, bl’ye bölündü

bu işlemden sonra AX, 0105h olur. AH’taki 01h kalan ve AL’deki 05h ise bölümdür. Nitekim 16’nın (yani 10h) 3’e 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.

Doubleword’u Word’e 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.

Quadword’u Doubleword’e Bölmek



Peki ya sonuç tam değilse?

Mesela 11h’ı (yani 17’yi) 3’e bölerseniz sonuç normalde 5,666... şeklinde olur, bu işlemi div komutu ile yaptığınızda ise AX’te 0205h değerini görürsünüz, yani bölüm 5 ve kalan 2. Özetle 17’nin içinde 5 tane 3 ve 1 tane’de 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 byte’lar 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 AL’de ne 3 ne 2 var sadece 20h var. Diğer bir gerçek 3’un 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 10’a bölsek zaten hex’den decimal’e dönüşüm işlemi yapmış oluruz;

        mov    ax, 20h
        mov    bl, 0Ah
        div     bl            ;AX=0203 yapar.

Keşke AX’teki 0203h değerinde 0’ların yerine 3 gelseydi;

        or    ax,3030h    ;AX’teki 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 AX’teki 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 al’deki düşük değerlikli byte hafızanın düşük numaralı adresine ax’teki yüksek değerlikli byte’ta hafızanın yüksek numaralı adresine yerleşmiş olur, böylece ax ile al’nin 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 ascii’den binary’ye 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 0’ları 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ş) BCD’dir.

1234 hafızada 01 02 03 04 byte dizisi olarak saklanırsa bu paketlenmemiş BCD’dir, şayet aynı değer hafızada 12 34 byte dizisi olarak saklanırsa bu da paketlenmiş BCD’dir. 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 AL’de 
        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 AL’deki 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 ASCII’ye 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) AL’den 6, AH’tan 1 çıkartılır. AH’tan 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 Intel’in 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
  • Yazılan Yorumlar
  • Yorum Yaz
ARA
7
2010
Mükemmel bir anlatım ve ayrıntılıları ile düşünüp anlattığınız için teşekkür ederiz hocam
TEM
11
2006
Sevgili tamer abi bu maili okursan [email protected] a lütfen bi mail at tamer karakan a
HAZ
23
2006
Okudugum en guzel tutoriallar, tebrik ediyorum.
MAR
28
2006
evet hocam bekliyoruz.Yada sadece ben mi bekliyorum.Sakın yazına ara verme yada yazmakdan vazgeçme.Bi şey yazın arkadaşlar!!! takip ediyoruz hocam deyin.!!yok ben daha yazmam diyorsanız o zaman geçmiş yazıların hatırına mapped-IO da anlatın bari. hayır kaynak var var olmasınada senin gibi anlatan yok.Sanki herkes assembly biliyor.Bilmek marifet değil anlatmak marifet.Anlatan bilen insan biliyordur zaten.Şunu da belirteyim ki yazmıyacak da olsanız buraya kadar ki makaleleriniz üzerine makale görmedim.Bunu için çok müteşşekürüm!!!!
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