Makalemizde, 80X86 komut sistemine ait aritmetik ve lojik komutları
açıklamaya devam edeceğiz.
AAM ve AAD Komutu:
AAM komutu, çarpma işlemi sonucunda, AX registerinde oluşan değeri ASCII formata dönüştürme amaçlı
kullanılır. Daha önce anlatılan AAA ve AAS komutlarında olduğu gibi AAM ve AAD
komutlarıda operandsız yazılırlar. AH ve AL registerlerini gizli operand olarak
kulanmaktadırlar.
AAM komutu, çarpma işlemi ile ax registerinde oluşan değerin ardından
kullanılır. Alnin değerini desimal 10 ile böler, elde edilen değeri aha
aktarır. Bölümden kalan değeride tekrar alye aktarır.Yapılan işlemin sonucunda,
elde edilen sayının sol dijiti ahda, sağ dijiti ise alde yer alır.AAM komutu,
parity, sign ve zero flaglarını alye aktardığı değere göre uygun şekilde
etkiler.
Örneğimizde mul komutu, çarpım sonucu olan 00 51 değerini ax registerine
aktarırken, aam komutuda bu değeri 00 81 olarak ASCII formatına dönüştürmüştür.
mov al,09 ;alnin değeri 9
mov bl,09 ;blnin değeri 9
mul bl ;ax =
00 51h
aam ;ax = 08 01h
I. adım
al registerinin değerini 0Aha böl
0Ah=d10 |
51h = 0101 0001b
_________________ = 08h
0Ah = 0000 1010b |
II.adım
bölümün sonuç değerini aha , kalanı
alye aktar |
ah = 08h
al = 01h |
III.adım
Sonuç
|
ax = 0801h |
AAD komutu ise bölme işleminde bölünenin
sonucunda, AX registerinde oluşan değeri ASCII formata dönüştürme amaçlı
kullanılır.AAD komutu, bölünen değerin yüksek seviyeli kısmını (ah registerinin
içeriğini) desimal 10 ile çarpar ve al (düşük seviyeli kısmı) ile
toplayarak al içerisine aktarır.
Yapılan işlem sonucunda ah registeri sıfırlanır, al registerinde bulunan BCD
sayısı, başka bir BCD sayısı ile bölünebilir duruma getirilmiş olur. AAD komutu,
parity, sign ve zero flaglarını alye aktardığı değere göre uygun şekilde
etkiler.
Örneğimizde desimal 35 sayısı, desimal 5e bölünmekte ve sonuç yine desimal
olarak elde edilmektedir. AAD komutunu kullanarak, ax üzerine paketlenmemiş
olarak aktarılan sayıyı, bölme işlemi için uygun hale getiriyoruz.
mov ax, 0305 ;ax = 03 05
aad ;ax = 00 23
mov bl,05 ; blye al
değerini koy
div bl ;ax = 00 07
I. adım
ah registerinin içeriğini
0Ah ile çarp
0Ah=d10 |
03h = 0000 0011b
0Ah = 0000 1010b
*_________________
1Eh = 0001 1110b |
II.adım
çarpım sonucundaki değere alnin değerini ekle ve alye yaz |
1Eh = 0001
1110b
05h = 0000 0101b
+_________________
23h = 0010 0011b |
III.adım
Sonuç
|
23h = 0010 0011b
_________________
= 7
05h = 0000 0101b |
DAA ve DAS komutu:
DAA komutu ile yapılan toplama işlemi sonucunda her bir byteda iki adet
desimal dijit bulunur. ADD komutunun arkasından kullanılan DAA komutu, alnin
içeriği olan değere ve AF (auxilary flag) ile CF (carry flag)nin durumuna bağlı
olarak iki farklı şekilde işleme sokulur.
I. Durum: al registerinin düşük seviyeli 4 biti 9dan büyük veya AF set ise, al
registeri 6 ile toplanarak, AF set edilir.
II.Durum: al registerinin yüksek seviyeli 4 biti 9dan büyük veya CF set ise, al
registeri ile 60h toplanarak CF set edilir.
Örneğimizde 9 ve 5 değerlerini toplayarak
komutumuzla istenilen sonucu elde edeceğiz.
mov al,09 ; al = 9
add al,05 ; al = 0E
daa ; al =14
I. adım
al registerlerini topla
|
09h = 0000 1001b
05h = 0000 1001b
+__________________
0Eh = 0000 1110b |
II.adım
al registerinin düşük seviyeli biti 0dan küçük olduğu için 6 değerini
ekledik ve sonuç değere ulaştık |
0Eh = 0000
1110b
06h = 0000 0110b
+_________________
14h = 0001 0100b |
DAS komutu ile yapılan çıkartma işleminin al registeri üzerindeki sonucuna ve
auxuiliary ile carry flaglarının durumuna bağlı olarak iki farklı şekilde
kullanılır.
I. Durum: al registerinin düşük seviyeli 4 biti 9dan büyük veya AF set ise, al
registerinden 6 çıkartılarak, AF set edilir.
II.Durum: al registerinin yüksek seviyeli 4 biti 9dan büyük veya CF set ise, al
registerinden 60h çıkartılarak CF set edilir.
DAS komutu, auxiliary, carry, parity, sign ve zero flaglarını etkiler.
Örneğimizde, desimal 13 den 5 i çıkartma işlemini al registerinde
yaptığımız için sonuç 0E oluyor. al registerindeki değerin desimal sayı olması
için çıkartma komutunun ardından DAS düzenleyici komutu kullanılıyor.
mov al,13 ;al=13h
mov bl,05 ;bl=05h
sub al,bl ;al = 0Eh
das ;al
= 08
I. adım
al registerindeki değerden bl registerindeki değeri çıkart |
13h = 0001 0011b
05h = 0000 1001b
-__________________
0Eh = 0000 1110b |
II.adım
al registerinin düşük seviyeli biti 0dan küçük olduğu için 6 değerini
çıkardık ve sonuç değere ulaştık |
0Eh = 0000
1110b
06h = 0000 0110b
-__________________
08h = 0000 1000b |
CBW ve CWD Komutu:
CBW:Byteın worde çevrilmesi.
CWD:Wordun double worde çevrilmesi
Aritmetik işlemler sırasında operandlar
farklı uzunluklara (byte,word veya double word) sahip olabilirler. Bu gibi
durumlarda, işlem öncesinde operandların uzunluklarının düzenlenmesi
gerekir.Küçük uzunluğa sahip operandın uzunluğunu, büyük uzunluğa sahip
operandın uzunluğuna denkleştirilmektedir.İşaretsiz sayılarla temsil edilen
operandlar, rahat bir şekilde düzenlenir. Fakat işaretli sayılarla temsil edilen
operandlarda değişim o kadar rahat olmamaktadır.
İşaretli sayıları içeren operandların uzunluklarının düzenlenmesi için CBW ve
CWD komutları geliştirilmiştir. CBW komutu al ve ah, CWD komutu ise ax ve dxi
gizli operand olarak kullanırlar.
CBW komutu, al içerisindeki işaretli sayının işaret bitini ahın tüm bitlerine,
CWD komutu da ax içindeki sayının işaret bitinin değerini dxin tüm bitlerine
aktararak sonuca ulaşmamızı sağlar.
TEST Komutu:
Test komutunun çalışma prensibi ve flagları etkileme biçimide
dahil olmak üzere And ile aynıdır. Farklı olarak, komut ile birlikte kullanılan
operandların değerlerini değiştirmez. Diğer lojik komutlarında olduğu gibi,
carry, owerflow bayrakları test işleminin sonrasında reset edilirler, auxiliary
dışındaki diğer bayraklarda işlem sonucuna uygun şekilde etkileneceklerdir.
Farkı olmamasına rağmen,
hangi durumda and, hangi durumda test komutunu kullanmalıyız sorusu aklımıza
gelecektir. Örneğimizi inceleyelim;
I. Durum |
and al,01
jz *
...
... |
II.Durum |
test al,01
jz *
...
... |
I. ve II. Durumda, al registerinin değeri
desimal 1 ile karşılaştırılmaktadır; al registerindeki değer desimal 1e eşit
ise
I.Durumda: alnin değeri korunacak ve zero bayrağının reset durumuna gelmesine
sebeb olacak, bu sayede jzyi izleyen komut ile program devam etmiş olacaktır.
Fakat değer 1den farklı ise sonuç 0 olarak alye yerleştirilecek ve zero
bayrağı set edilecektir, sonucunda ise * yerine kullanılan adrese dallanılacak
ve program bu adreste bulunan komut ile sürecektir.
Fakat alnin değeri 1e eşit değil ve başka işlemler için bize gerekli ise sorun
çıkacaktır.Sonuçtan da anlaşıldığı gibi, al registerinin karşılaştırma öncesi
değeri, karşılaştırma sonrası adımlarda da gerekli ise test komutunu tercih
etmeliyiz.
SHR ve SHL Komutu:
SHR Komutu ile, soldaki
operandın en düşük seviyeli biti carry bayrağına kopyalanır ve operandın tüm
bitleri sağa doğru 1er bit kayar. En soldaki bitin değeri 0 yapılır. Bu işlem
SHR ile verilen ikinci operandın değeri kadar tekrarlanır.
Örneğimizde, 30h değerini iki kere 1er biti sağa kaydırarak sonucun nasıl
değiştiğini inceleyeceğiz.
mov al,30h ;al=30h
shr al,01 ;al=18h
shr al,01 ;al=0Ch
Şekil 1 - Shr komutu ile bitlerin sağa
kaydırılması
Adımlar |
Hexadesimal |
Binary |
Desimal |
CF |
I. adım:
alye 30h değerini koy |
al=30h |
00110000 |
48 |
- |
II.adım:
değerleri 1 bit sağa kaydır, en düşük seviyeli biti CFna taşı |
al=18h |
00011000 |
24 |
0 |
III.adım:
değerleri 1 bit sağa kaydır, en düşük seviyeli biti CFna taşı |
al=0Ch |
00001100 |
12 |
0 |
Programda da görüldüğü gibi her bir sağa
kaydırma işlemi ile sayıyı ikiye bölmektedir.Her bir shr işlemi sonrasında carry
bayrağı 0 ise çift sayı, 1 ise tek sayıdır.
SHL Komutu ile, soldaki operandın en yüksek seviyeli biti carry bayrağına
kopyalanır ve operandın tüm bitleri sola doğru 1er bit kayar. En soldaki bitin
değeri 0 yapılır. Bu işlem SHL ile verilen ikinci operandın değeri kadar
tekrarlanır.
Örneğimizde 0Ch değerini iki kere 1er bit sola kaydırarak sonuç üzerindeki
değişiklikleri inceleyeceğiz.
mov al,0Ch ;al=0Ch
shr al,01 ;al=18h
shr al,01 ;al=30h
Şekil 2 - Shl komutu ile bitlerin sola
kaydırılması
Adımlar |
Hexadesimal |
Binary |
Desimal |
CF |
I. adım:
alye 0Ch değerini koy |
al=0Ch |
00001100 |
12 |
- |
II.adım:
değerleri 1 bit sola kaydır, en yüksek seviyeli biti CFna taşı |
al=18h |
00011000 |
24 |
0 |
III.adım:
değerleri 1 bit sola kaydır, en yüksek seviyeli biti CFna taşı |
al=0Ch |
00110000 |
48 |
0 |
Programda da görüldüğü gibi her bir sola
kaydırma işlemi ile sayıyı iki ile çarpmış oluyoruz.
RCR ve RCL Komutu:
RCR Komutu, işleme tabi tutulan bitlerin herbirini bir
pozisyon sağa kaydırır. Düşük seviyeli bit pozisyonundaki değer carry bayrağına,
carry bayrağının değeride yüksek seviyeli bit pozisyonuna aktarılır. İşlem
ikinci operand değeri kadar tekrarlanır.
Şekil 3 - Rcr komutu ile bitlerin sağa
kaydırılması
RCL Komutu, işleme tabi tutulan
bitlerin herbirini bir pozisyon sola kaydırır. Carry flağının değeri düşük
seviyeli bit pozisyonuna, yüksek seviyeli bit pozisyonundaki değer ise
carry flağına aktarılır. İşlem ikinci operand değeri kadar tekrarlanır.
Şekil 4 - Rcl komutu ile bitlerin sola
kaydırılması
Şekil 5 - Programın ekran görüntüsü
Bu bölümde anlattığımız aam,das,shr ve rcl
komutlarını kullanarak örnek bir program hazırladım. aam komutu kullanılan
prosedürde shr komutunu işleme katmak istediğimiz al registerinin içeriğini bir
bit sağa kaydırmak için, das ile ilgili prosedürde ise rcl komutuyla al
registerinin içeriğini bir bit sola kaydırdım.
.model small
.stack 64
.data
aamsonuc db 00$,10,13
dassonuc db 00$
knm db 10,13,$
;....................................................
.code
mov ax,@data
mov ds,ax
mov es,ax
call aamornek
call dasornek
;....................................................
aamornek proc
mov al,12h
shr al,01
;al registerinin içeriğini bir bit sağa kaydır, al=9h
mov bl,9h
;bl=9h
mul bl
;ax=51h
aam
;ax=81h
add ax,3030h
;al ve ah değerlerini ascii karakterlere çevir.
mov byte ptr [aamsonuc],ah
mov byte ptr [aamsonuc+1],al
;ax registerini sonuc dizisi içerisine yerleştir.
mov ah,09h
lea dx,aamsonuc
;sonucu yaz
int 21h
mov ah,09h
lea dx,knm
;alt satıra geç
int 21h
aamornek endp
;....................................................
dasornek proc
mov al,28h
rcr al,01
;al registerinin içeriğini bir bit sola kaydır, al=14h
mov bl,05h
;bl=5h
sub al,bl
;al=Fh
das
;al=9h
add al,30h
;al değerini ascii karaktere çevir.
mov ah,02h
mov dl,al
int 21h
;sonucu yaz
dasornek endp
;....................................................
mov ah,4ch
int 21h
end
;programdan çıkış
;....................................................
Programımız, anlatılan komutların sağlaması olarak da
değerlendirilebilir. Ben kodu çalıştırdım ve gördüm ki kullandığım komutlar
işini başarıyla gerçekleştiriyor.
Makalemizde aritmetik lojik komutların
çalışma şekillerini, bayraklar üzerindeki etkilerini anlatmaya çalıştım.
Benzer özelliklere sahip komutların kullanılması sizlerin tercihine kalmış,
gerçekleştireceğiniz uygulamalar ve elde etmek istediğiniz performans doğrultusunda ihtiyacınıza en uygun olanı
belirleyebilirsiniz.
Makale:
80x86 KOMUT SETİ (BÖLÜM 5) Assembly ve X86 Programlama Mustafa Arkan
|