80x86 KOMUT SETİ (BÖLÜM 5)
İlgili etiketler: al?nin bitlerin degere degeri degerini desimal farkli islemi kaydir komutu komutu operandin registerinde registerinin seviyeli X86 Assembly Mustafa Arkan
Yayınlanma Tarihi : 31.5.2006
Okunma Sayısı : 34432
Ana Sayfa / Makaleler / X86 Assembly / 80x86 KOMUT SETİ (BÖLÜM 5)
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. Al'nin değerini desimal 10 ile böler, elde edilen değeri ah'a aktarır. Bölümden kalan değeride tekrar al'ye aktarır.Yapılan işlemin sonucunda, elde edilen sayının sol dijiti ah'da, sağ dijiti ise al'de yer alır.AAM komutu, parity, sign ve zero flaglarını al'ye 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 ;al'nin değeri 9
mov bl,09 ;bl'nin değeri 9
mul bl ;ax = 00 51h
aam ;ax = 08 01h
al registerinin değerini 0Ah'a böl
0Ah=d'10' 51h = 0101 0001b
_________________ = 08h
0Ah = 0000 1010b
bölümün sonuç değerini ah'a , kalan'ı al'ye aktar ah = 08h
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ı al'ye aktardığı değere göre uygun şekilde etkiler.
Örneğimizde desimal 35 sayısı, desimal 5'e 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 ; bl'ye al değerini koy
div bl ;ax = 00 07
ah registerinin içeriğini
0Ah ile çarp
0Ah=d'10' 03h = 0000 0011b
1Eh = 0001 1110b
çarpım sonucundaki değere al'nin değerini ekle ve al'ye yaz 1Eh = 0001 1110b
05h = 0000 0101b
23h = 0010 0011b
_________________ = 7
DAA ve DAS komutu:
DAA komutu ile yapılan toplama işlemi sonucunda her bir byte'da iki adet desimal dijit bulunur. ADD komutunun arkasından kullanılan DAA komutu, al'nin 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 9'dan büyük veya AF set ise, al registeri 6 ile toplanarak, AF set edilir.
II.Durum: al registerinin yüksek seviyeli 4 biti 9'dan 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
al registerlerini topla
09h = 0000 1001b
05h = 0000 1001b
0Eh = 0000 1110b
al registerinin düşük seviyeli biti 0'dan 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 9'dan büyük veya AF set ise, al registerinden 6 çıkartılarak, AF set edilir.
II.Durum: al registerinin yüksek seviyeli 4 biti 9'dan 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
al registerindeki değerden bl registerindeki değeri çıkart 13h = 0001 0011b
al registerinin düşük seviyeli biti 0'dan küçük olduğu için 6 değerini çıkardık ve sonuç değere ulaştık 0Eh = 0000 1110b
08h = 0000 1000b
CBW ve CWD Komutu:
CBW:Byte'ın worde çevrilmesi.
CWD:Word'un 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 dx'i 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 dx'in tüm bitlerine aktararak sonuca ulaşmamızı sağlar.
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
II.Durum test al,01
I. ve II. Durumda, al registerinin değeri desimal 1 ile karşılaştırılmaktadır; al registerindeki değer desimal 1'e eşit ise
I.Durumda: al'nin değeri korunacak ve zero bayrağının reset durumuna gelmesine sebeb olacak, bu sayede jz'yi izleyen komut ile program devam etmiş olacaktır. Fakat değer 1'den farklı ise sonuç 0 olarak al'ye 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 al'nin değeri 1'e 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 1'er 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 1'er 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
al'ye 30h değerini koy al=30h 00110000 48 -
değerleri 1 bit sağa kaydır, en düşük seviyeli biti CF'na taşı al=18h 00011000 24 0
değerleri 1 bit sağa kaydır, en düşük seviyeli biti CF'na 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 1'er 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 1'er bit sola kaydırarak sonuç üzerindeki değişiklikleri inceleyeceğiz.
mov al,0Ch ;al=0Ch
shr al,01 ;al=30h
Şekil 2 - Shl komutu ile bitlerin sola kaydırılması
al'ye 0Ch değerini koy al=0Ch 00001100 12 -
değerleri 1 bit sola kaydır, en yüksek seviyeli biti CF'na taşı al=18h 00011000 24 0
değerleri 1 bit sola kaydır, en yüksek seviyeli biti CF'na 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.
aamsonuc db '00$',10,13
dassonuc db '00$'
knm db 10,13,'$'
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
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.
lea dx,aamsonuc ;sonucu yaz
lea dx,knm ;alt satıra geç
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
add al,30h ;al değerini ascii karaktere çevir.
int 21h ;sonucu yaz
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.
80x86 KOMUT SETİ (BÖLÜM 5) Assembly ve X86 Programlama Mustafa Arkan
ali özer / üye hakkında
hocalarım gercekten makaleleriniz cok güzel ama neredeyse 3 ay olacak hala devamı gelmedi yoksa bitirdinizmi.ne olur devam edin.ben bu dili öğrenmek istiyorum.