80x86 String Komutları (Bölüm 4)
Çeşitli bilgilerin birleşerek biraya gelmelerine string denir. “Merhaba”
kelimesi bir string’dir. ASSEMBLY’de stringleri kontrol edebilen komutlar vardır
ve bu komutlar hafıza blokları üzerinde çalışırlar.
Bu makalemizde 80 X 86 ailesinde kullanılan string komutlarını (MOVS, CMPS, LODS,
SCAS, STOS ) incelemeye çalışacağız, komutlarımız byte, word ve double word
dizileri üzerinde işlemler gerçekleştirmek için kullanılmaktadır. Aşağıda ilgili
komutlar ve kullanım şekillerini tablo halinde görebilirsiniz.
Komut Kullanım Şekli
MOVS movsb,movsw,movsd
CMPS cmpsb,cmpsw,cmpsd
SCAS scasb,scasw,scasd
STOS stosb,stosw,stosd
LODS lodsb,kodsw,lodsd
String komutlarını ile işlem yaparken, Indis registerleri olarak adlandırılan SI
ve DI registerlerinden, bellekteki bir bilgiyi bir adresten başka bir adrese
taşırken kullanıyoruz. SI registerine taşınacak bilgi dizisinin başlangıç
adresini, DI registerine de diziyi taşımak istediğimiz belleğin başlangıç
adresini yerleştirerek yapmak istediğimiz işlemi gerçekleştirebiliriz.
Indis registerlerinin program içeirisinde kullanım şeklini gösteren örneğimizi
inceleyebilirsiniz.
Byte1 db ‘a’
;byte1 için ayrılan alana ’a’ değerini koy
Byte2 db ‘*’
;byte2 için ayrılan alana ’*’ değerini koy
Movs Byte2,Byte1 ;byte2 bilgi dizisini, byte1 bilgi
dizisine kopyala
Lea di,Byte2
;taşımak istediğimiz belleğin başlangıç adresi di registerine koy
Lea si,Byte1
;taşınacak bilgi dizisinin başlangıç adresini si registerine koy
Movsb
;si registerinde bulunan byte dizisini di registeri ile gösterilen adrese byte
olarak taşı
String işlemlerinde kullanılan komutları daha detaylı incelemeye başlayalım;
MOVS Komutu:
movs komutunun kullandığı veri tipine göre farklı kullanım şekilleri vardır,
data segmentinde ve ofset adresi SI rejisterinde bulunan byte / word / double
word dizilerini ES ve DI registerleri ile gösterilen adrese taşır. CX
registerinde tutulan deger adedince taşıma işlemi tekrarlanır.movsb ile byte
dizileri, movsw ile word dizileri ve movsd ile double word dizileri üzerinde
işlemler yapılır.
REP: kendisinden sonra gelen string komutunun cx registerinin değeri 0 olana dek
tekrarlar.
Komut |
Anlamı |
İşlem |
movsb |
byte dizisi
taşı |
si’de
bulunan byte dizisini, cx registerinde tutulan değer adedince di
registerine taşı |
movsw |
word dizisi
taşı |
si’de
bulunan word dizisini, cx registerinde tutulan değer adedince di
registerine taşı |
movsd |
double
dizisi olarak taşı |
si’de
bulunan double word dizisini, cx registerinde tutulan değer adedince di
registerine taşı |
CMPS Komutu:
REPE, REPZ, REPNE ve REPNZ komutlarının parametresi olarak bellekteki iki
stringi birbirleriyle karşılaştırma işleminde kullanılır. Stringlerden biri Data
Segmentte diğeri ise Extra Segmentte tutulur. Data Segmentindeki stringin ofset
adresi SI registerine, Extra segmentteki stringin ofset adresi ise DI
registerine yerleştirilir. Cx registerindeki değer adadince karşılaştırma işlemi
tekrarlanır.
Not:REPE: eşit oduğu zaman tekrarla REPZ: zero flag “0” oldugu zaman tekrarla
REPNE: eşit olmadığı zaman tekrarla REPNZ: zero flag “0” olmadıgı zaman tekrarla
Komut |
Anlamı |
İşlem |
cmpsb |
byte dizisi
karşılaştır |
data
segmentte ve extra segmentte tutulan byte dizisini, cx registeri
adedince karşılaştır |
cmpsw |
word dizisi
karşılaştır |
data
segmentte ve extra segmentte tutulan word dizisini, cx registeri
adedince karşılaştır |
cmpsd |
double word
dizisi karşılaştır |
data
segmentte ve extra segmentte tutulan double word dizisini, cx registeri
adedince karşılaştır |
LODS Komutu:
Lods komutu string komutları içinde tektir. Komut öncesinde herhangi bir komut
kullanmaya gerek yoktur. Ofset adresi DS:SI rejisterinde bulunan byte / word /
double word dizilerini al, ax, eax registerlerine, si registerinin değerini
arttırarak veya azaltarak kopyalar.
Komut |
Anlamı |
İşlem |
lodsb |
byte dizisi
kopyala |
ofset adresi
ds:si registerinde bulunan byte dizisini, si registerinin değerini
arttırarak, al registerine taşı |
lodsw |
word dizisi
kopyala |
ofset adresi
ds:si registerinde bulunan word dizisini, si registerinin değerini
arttırarak, ax registerine taşı |
lodsd |
double word
dizisi kopyala |
ofset adresi
ds:si registerinde bulunan double word dizisini, si registerinin
değerini arttırarak, eax registerine taşı |
SCAS Komutu:
Ofset adresi DS:SI rejisterinde bulunan byte / word / double word dizileri
içerisindeki değerle al, ax, eax registerlerindeki değerleri karşılaştırarak
arama yapmak için kullanılır.
Scas komutu AF, Cf, OF, PF, SF ve ZF bayraklarını ayarlarak arama işlemini
gerçekleştirir.
Komut |
Anlamı |
İşlem |
scasb |
byte dizisi
içerisinde ara |
ofset adresi
ds:si registerinde bulunan byte dizisi içerisindeki değerle, al
registerindeki değeri karşılaştırarak arama yap |
scasw |
word dizisi
içerisinde ara |
ofset adresi
ds:si registerinde bulunan word dizisi içerisindeki değerle, ax
registerindeki değeri karşılaştırarak arama yap |
scasd
|
double word
dizisi içerisinde ara |
ofset adresi
ds:si registerinde bulunan double word dizisi içerisindeki değerle, eax
registerindeki değeri karşılaştırarak arama yap |
STOS Komutu:
Stos komutu es:di ile gösterilen adreste bulunan akümülator içerisinde
belirtilen değeri saklar. Bu işlemden sonra yön bayrağının durumuna göre işlemci
di registerini arttırır veya azaltır. Stos komutu byte, word yada double word
üzerinde işlemler yapmak için uygundur.
Komut |
Anlamı |
İşlem |
stosb |
al
içerisinde byte dizisi sakla |
es:di ile
gösterilen adresteki al registerinde, istenilen byte dizisi saklanır |
stosw |
ax
içerisinde word dizisi sakla |
es:di ile
gösterilen adresteki ax registerinde, istenilen word dizisi saklanır |
stosd |
eax
içerisinde double word dizisi sakla |
es:di ile
gösterilen adresteki eax registerinde, istenilen double word dizisi
saklanır |
Şekil 1 - Programın Ekran Görüntüsü.
Örneğimizde, kelime içerisindeki küçük harfler büyük harflere dönüştürülecek.
Dönüştürme işleminde kucuk harf olup olmadığını anlamak için “a = ASCII 61h”
oldugu için bu değer ile karşılaştırma yapacağız. Eğer harf bu değerden buyuk
ise küçük harf olduğunu anlayacağız ve harfi buyuğe çevirmek için 20h değerini
çıkaracağız. Harf değerimizden küçükse büyük harf olduğuna karar vereceğiz ve
çıkarma işlemi yapmayacağız. Dönüştürme işleminden sonra programı terk edeceğiz.
Programın ekran çıktısından da gördüğünüz gibi klavyeden ilk harf grubunun
tamamı küçük harf ikinci harf grubunun bir elemanı ise büyük harf olarak
girilmiştir. Sonuçta enter tuşuyla harf girişi tamamlanıp sonuç değeri elde
edilmiştir. Umarım string komutlarının kullanımı konusunda faydalı olur.
.model small
.stack 64
.data
snc db 10,13,’ ’,’$’,10,13
; sonuc için ayrılan alan
.code
mov ax,@data
mov ds,ax
mov es,ax
dizi_al:
mov ah,01
;klavyeden karakter isteniyor
int 21h
;girilen al’de
cmp al,13
;al’deki değeri enter ile karşılaştır
jz yaz
;enter’e basılmışsa yaz’a atla
inc si
;si ile kelime içinde bir sonraki karaktere ilerle
cmp al,61h
;al içindeki değerle a=61h karşılaştır
jg degis
;girilen değerden buyukse degis’e atla
jl sbt
;girilen değerden kucukse sbt’e atla
degis:
sub al,20h
;al değerinden 20h çıkar
sbt:
sub al,0h
;al değerinden 0h çıkar
mov [snc+si],al
;kelime içerisinde sıradaki harfe son al değerini yukle
jmp dizi_al
;dizi başlangıcına atla
yaz:
mov ah,09h
;ekrana snc’de tutulan değer yazılıyor
lea dx,snc
int 21h
dosa:
;programı terket
mov ah,4ch
int 21h
end
Aslında string komutları ile yapılan işlemler bilgisayar kullanıcılarına o kadar
yakın ki, mesela msword uygulamalarında kullanılan kopyala-yapıştır gibi.
Yorumlarınızı bekliyorum.
Makale:
80x86 String Komutları Assembly ve X86 Programlama Mustafa Arkan
|