Bölüm 4.2: Değişkenler

Mikroişlemciler
DB / DW / DDAdlandırma kurallarıBellek yerleşimiORG 100h ve .COMDiziler ve DUPLEA ve OFFSETEQU sabitleriToplama ve karşılaştırmaÇift sözcük
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Tanımlama

DB, DW, DD, DUP ve ? ile değişken ve dizi tanımlamak.

Bellek yerleşimi

Derleyicinin değişkenleri hangi bağıl konumlara, hangi bayt sırasıyla yerleştirdiğini çıkarmak.

Adresler

LEA ve OFFSET ile değişken adresini almak ve dizi elemanlarına indisle erişmek.

Programlar

Değişkenler arasında veri taşıyan, toplayan ve karşılaştıran programları adım adım izlemek.

Değişkenler

Değişkenler

  • Bir değişken bir bellek konumunu temsil eder.
  • Programcı için var1 adını kullanmak, 5A73:235B adresini kullanmaktan çok daha kolaydır.
  • Derleyici iki temel tür destekler:
    • BYTE (8 bit): ad DB değer (Define Byte)
    • WORD (16 bit): ad DW değer (Define Word)
  • DD (Define Double word, 32 bit) de vardır: 4 bayt.
counter DB 10h     ; BYTE
sum     DW 0FFFFh  ; WORD
counter10sumFFsum+1FF…1 bayt2 bayt

Değişkenler

Adlandırma ve İlk Değer

  • Değişken adları harfle başlamalıdır; sonrasında harf ve rakam kombinasyonları içerebilir.
  • Yazmaç ve komut adları (AX, MOV…) değişken adı olamaz.
  • Ad belirtilmeyen değişkenler de olabilir: adları yoktur ama adresleri vardır.
  • Herhangi bir sayısal değer (ikili, onluk, onaltılık, karakter) alabilir.
  • İlk değer atanmamış değişkenler için ? kullanılır (emu8086 belleğe 00 koyar).
Tanım?
sayi1 DB 5geçerli
1sayi DB 5rakamla başlıyor
ax DW 0yazmaç adı
DB 0Ahadsız, ama adresi var
sonuc DW ?ilk değersiz
harf DB 'A'41h

Değişkenler

Değer Aralıkları

DirektifBoyutİşaretsizİşaretliÖrnek
DB1 bayt0 … 255−128 … 127x DB -1 → FFh
DW2 bayt0 … 65535−32768 … 32767y DW -2 → FE FF
DD4 bayt0 … 4 294 967 295−231 … 231−1z DD 1 → 01 00 00 00
Bellekte yalnızca bit deseni saklanır; işaretli mi işaretsiz mi olduğu, değeri kullanan komuta bağlıdır (ör. JGE işaretli, JAE işaretsiz karşılaştırır). DB 300 bir bayta sığmaz → assembler hata verir.

Değişkenler · Kodu adım adım çalıştır

Kod İzleme: FFh 255 mi, −1 mi?

ORG 100h
MOV AL, x        ; FFh
ADD AL, 1        ; 255 + 1 ?
MOV AL, x
CBW              ; işaretli: −1
MOV BX, y        ; FFFEh
NEG BX           ; −(−2)
RET
x DB -1
y DW -2
bellekFFx · 0110FEy · 0111FFy+1 · 011200FFhAXişaretsiz 255işaretli 255AL: 255 / −10000hBXişaretsiz 0işaretli 0CF0OF0ZF0

Bellekte x = FFh, y = FE FF (little-endian FFFEh). AL = x = FFh: işaretsiz 255, işaretli −1.

bellekFFx · 0110FEy · 0111FFy+1 · 01120000hAXişaretsiz 0işaretli 0AL: 0 / 00000hBXişaretsiz 0işaretli 0CF1OF0ZF1işaretsiz taşma: CF

ADD AL, 1: işaretsiz bakışla 255 + 1 = 256 bayta sığmaz → AL = 00h, CF = 1. İşaretli bakışla −1 + 1 = 0 doğru: OF = 0.

bellekFFx · 0110FEy · 0111FFy+1 · 011200FFhAXişaretsiz 255işaretli 255AL: 255 / −10000hBXişaretsiz 0işaretli 0CF1OF0ZF1

AL yeniden FFh.

bellekFFx · 0110FEy · 0111FFy+1 · 0112FFFFhAXişaretsiz 65535işaretli −1AL: 255 / −10000hBXişaretsiz 0işaretli 0CF1OF0ZF1işaret genişletme

CBW AL'yi işaretli kabul eder: MSB = 1 → AH = FFh, AX = FFFFh = −1 (16 bit).

bellekFFx · 0110FEy · 0111FFy+1 · 0112FFFFhAXişaretsiz 65535işaretli −1AL: 255 / −1FFFEhBXişaretsiz 65534işaretli −2CF1OF0ZF1

BX = y = FFFEh: işaretsiz 65534, işaretli −2.

bellekFFx · 0110FEy · 0111FFy+1 · 0112FFFFhAXişaretsiz 65535işaretli −1AL: 255 / −10002hBXişaretsiz 2işaretli 2CF1OF0ZF0NEG: −(−2) = 2

NEG BX: 0 − (−2) = 0002h. Bit deseninin anlamını komut seçti: ADD/CF işaretsiz, CBW/NEG işaretli yorumladı.

DB/DW yalnızca bit desenini saklar; işaretli mi işaretsiz mi olduğuna değeri kullanan komut karar verir.

Değişkenler

Değişkenin Türü ve Boyut Denetimi

  • Assembler her değişken adının yanında bir tür saklar: DB → BYTE (1), DW → WORD (2), DD → DWORD (4).
  • Komuttaki diğer işlenen yazmaçsa boyutlar eşleşmelidir; eşleşmezse derleme durur.
  • Sabit yazarken boyutu değişkenin türü belirler: MOV w, 5 bir sözcük yazar.
  • Değişken adı olmayan [BX] gibi işlenenlerin türü yoktur; sabitle kullanılırken BYTE PTR ya da WORD PTR gerekir.
  • BYTE PTR türü yalnızca o komut için değiştirir; değişkenin tanımı aynı kalır.
Komut (w DW 1234h, b DB 5)Sonuç
MOV AL, whata: 1 bayt / 2 bayt
MOV AL, BYTE PTR wAL = 34h (düşük bayt)
MOV AL, BYTE PTR w+1AL = 12h (yüksek bayt)
MOV w, 5w = 0005h (sözcük)
MOV AX, bhata: 2 bayt / 1 bayt
MOV [BX], 5hata: boyut belirsiz
MOV b, whata: bellekten belleğe
INC bb = 6 (bayt artırılır)
Tür denetimi derleme anında yapılır ve gözden kaçan pek çok hatayı yakalar. İşlemci çalışırken türü bilmez; yalnızca komutun kodladığı boyutta okur ya da yazar.

Değişkenler · Kodu adım adım çalıştır

Kod İzleme: Aynı Belleğe İki Ad (LABEL)

ORG 100h
MOV AX, sozcuk     ; WORD
MOV BL, baytlar    ; düşük
MOV BH, baytlar+1  ; yüksek
MOV baytlar, 0FFh  ; tek bayt
MOV CX, sozcuk     ; sözcük
RET
sozcuk LABEL WORD
baytlar DB 34h, 12h
bellek34baytlar011512baytlar+10116sozcuk (WORD) = 1234hAX1234hBX0000hCX0000hWORD olarak okundu

sozcuk LABEL WORD yer ayırmaz; yalnızca 0115h adresine WORD türünde ikinci bir ad verir. MOV AX, sozcuk iki baytı birden okur: AX = 1234h.

bellek34baytlar011512baytlar+10116sozcuk (WORD) = 1234hAX1234hBX0034hCX0000h

baytlar aynı adresin BYTE türündeki adıdır: BL = 34h. PTR yazmaya gerek kalmadı.

bellek34baytlar011512baytlar+10116sozcuk (WORD) = 1234hAX1234hBX1234hCX0000h

baytlar+1 ikinci bayt: BH = 12h. BX = 1234h; little-endian sıranın sonucu.

bellekFFbaytlar011512baytlar+10116sozcuk (WORD) = 12FFhAX1234hBX1234hCX0000htek bayt yazıldı

Tür BYTE olduğu için MOV baytlar, 0FFh yalnızca 0115h adresine yazar: bellek FF 12.

bellekFFbaytlar011512baytlar+10116sozcuk (WORD) = 12FFhAX1234hBX1234hCX12FFh

Aynı bellek WORD adıyla okununca değişiklik görülür: CX = 12FFh. İki ad, tek bellek konumu.

bellekFFbaytlar011512baytlar+10116sozcuk (WORD) = 12FFhAX1234hBX1234hCX12FFh

RET. LABEL bellekte bayt üretmedi; program boyutu iki baytlık tanım kadar arttı.

ad LABEL tür, kendisinden sonraki ilk bayta yeni bir ad ve tür verir. Bir tamponu hem bayt bayt hem sözcük sözcük işlemek için PTR yazmaktan daha okunaklıdır.

Bellek Yerleşimi

Örnek Kod

ORG 100h
MOV AL, var1   ; AL ← var1
MOV BX, var2   ; BX ← var2
RET            ; programı bitir
VAR1 DB 7      ; BYTE, 7
var2 DW 1234h  ; WORD, 1234h
  • Kod önce, değişkenler RET'ten sonra: CPU onlara hiç ulaşmaz.
  • Derleyici kaynağı bir bayt dizisine çevirir ve değişken adlarını bellek konumlarıyla değiştirir.
  • Büyük-küçük harfe duyarsızdır: VAR1 ile var1 aynı değişkendir.
0100A001010801020101038B01041E0105090106010107C3010807010934010A12MOV AL, [0108h]MOV BX, [0109h]RETVAR1var2

Bellek Yerleşimi · Kodu adım adım çalıştır

Kod İzleme: var1 ve var2

AX0000AHALBX0000BHBLIP01000B56:0107 … 010A0107C3010807010934010A12

Program 0B56:0100'e yüklendi; DS = CS = 0B56h, IP = 0100h.

AX0007AHALBX0000BHBLIP01030B56:0107 … 010A0107C3010807010934010A12

MOV AL, [0108h]: VAR1'in değeri → AL = 07h. IP = 0103h.

AX0007AHALBX1234BHBLIP01070B56:0107 … 010A0107C3010807010934010A12

MOV BX, [0109h]: 34h düşük, 12h yüksek bayt → BX = 1234h. IP = 0107h.

AX0007AHALBX1234BHBLIP00000B56:0107 … 010A0107C3010807010934010A12

RET (0107h'de C3) yığından 0000h'yi alır: IP = 0000h, PSP'deki INT 20h programı bitirir. 0108h'den sonrası veridir.

ORG 100h
MOV AL, var1   ; AL ← var1
MOV BX, var2   ; BX ← var2
RET            ; programı bitir
VAR1 DB 7      ; BYTE, 7
var2 DW 1234h  ; WORD, 1234h

Bellek Yerleşimi

Derleyici Ne Yapar?

  • Kaynak kodu bir dizi bayta dönüştürür; değişken adlarını bağıl konumlarla değiştirir: MOV AL, var1 → MOV AL, [0108h].
  • .COM dosyaları yüklendiğinde DS, CS yazmacının değerini alır (ES ve SS de aynıdır).
  • Bağıl konum (offset), bellek kesiminin başlangıcından itibaren olan uzaklıktır.
  • VAR1'in bağıl konumu 0108h, tam adresi 0B56:0108'dir.
  • var2'nin bağıl konumu 0109h, tam adresi 0B56:0109'dur.
    • WORD türünde olduğu için 2 bayt kaplar (0109h ve 010Ah).
    • Düşük bayt düşük adreste saklanır: 34h, 12h'den önce yer alır (little-endian).
Kesim değeri (0B56h) DOS'un programı nereye yüklediğine bağlıdır ve her çalıştırmada farklı olabilir; bağıl konumlar ise derleme anında sabittir.

Bellek Yerleşimi

ORG 100h Direktifi

  • Derleyiciye çalıştırılabilir dosyanın yükleneceği adresi söyler; değişken adları adreslerle değiştirilirken dikkate alınır.
  • .COM dosyalarında kullanılır; bu dersteki örneklerin çoğu emu8086 .COM şablonuyla yazılır.
  • İşletim sistemi kesimin ilk 256 baytında (PSP) programla ilgili verileri tutar; komut satırı parametreleri bu alandadır.
  • .EXE dosyaları 0000h bağıl konumuna yüklenir ve değişkenler için ayrı bir kesim kullanır.
  • Direktifler gerçek makine koduna dönüştürülmez.
PSP: DOS bilgileri, komut satırı (80h–FFh)0000hkod: ORG 100h, ilk komut0100hdeğişkenler (RET'ten sonra)boşyığın: SP = FFFEh'den aşağı büyürFFFEhFFFFhCS = DS = ES = SStek kesim, en fazla 64 KBIP = 0100h

Bellek Yerleşimi

Hizalama: Sözcük Hangi Adreste?

çift adres: 1 yol döngüsü340200120201tek adres: 2 yol döngüsü··0200340201120202··020316 bitlik veri yoluiki baytı birlikte taşır1. döngü: 0201 · 2. döngü: 0202sözcük başına +4 saat turu
a  DB 5          ; 0200h
   EVEN          ; 0201h: dolgu
w  DW 1234h      ; 0202h (çift)
  • 8086'nın veri yolu 16 bittir: çift adresten başlayan bir sözcük tek yol döngüsünde okunur.
  • Tek adresteki sözcük için iki yol döngüsü gerekir; 8086 bunu kendiliğinden yapar, yalnızca daha yavaştır (sözcük erişimi başına 4 saat turu).
  • MASM ve TASM'daki EVEN direktifi konum sayacını çift sayıya yuvarlar; gerekirse araya bir dolgu baytı koyar. Tanımlar yer değiştirmez, yalnızca kayar.
  • 8 bitlik veri yolu olan 8088'de her sözcük zaten iki döngüdür; hizalama orada fark yaratmaz.
Örnek: MOV AX, w 8086'da 10 saat turudur; w tek adresteyse 14 olur. Bir döngüde 1000 kez okunan sözcük için fark 4000 tur, 5 MHz'de 0,8 ms eder. Bayt değişkenler için hizalama gerekmez.

Bellek Yerleşimi

Değişkenler Nereye Yazılır?

YerÖrnekDikkat edilecek nokta
Kodun sonundaRET · x DB 5Yürütme RET'te biter, veriye hiç ulaşmaz. .COM'da en sık kullanılan düzen.
Kodun başındaJMP basla · x DB 5 · basla:JMP veriyi atlar; unutulursa veri baytları komut olarak yürütülür.
Ayrı veri kesimi (.EXE).DATA · x DB 5Program başında MOV AX, @data · MOV DS, AX şarttır.
DS yüklenmezse.EXE programı başladığında DS, PSP'yi gösterir. MOV AL, x doğru bağıl konumu kullanır ama yanlış kesimden okur: hata vermeden yanlış değer gelir.
Kesimin önemi.COM'da CS = DS olduğu için kod ile verinin aynı kesimde durması sorun değildir. .EXE'de kod CS'de, veri DS'de durur; değişken adresi DS'ye göre hesaplanır.

Diziler

Diziler

  • Diziler değişken zincirleri olarak düşünülebilir: ardışık bellek konumlarında saklanan veri gruplarıdır.
  • Tırnak içindeki metin otomatik olarak bayt dizisine (ASCII kodları) dönüştürülür.
  • Dizi elemanlarına bellek adresi üzerinden erişilir: ilk eleman dizinin adresinde, sonrakiler ardından.
a DB 48h, 65h, 6Ch, 6Ch, 6Fh, 00h
b DB 'Hello', 0
…a[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00b[0]48b[1]65b[2]6C…

a ve b bellekte aynı baytları tutar: 48h 'H', 65h 'e', 6Ch 'l', 6Ch 'l', 6Fh 'o', 00h (dizgi sonu).

Diziler · Kodu adım adım çalıştır

Kod İzleme: Dizi Elemanlarına Erişim

AX006CAHALBX0000BHBLSI0000a dizisia[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00

a[3], a + 3 bayt demektir: AL = 6Ch ('l').

AX006CAHALBX0000BHBLSI0000a dizisia[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00

İndis yazmacı SI = 0.

AX006CAHALBX0048BHBLSI0000a dizisia[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00

a[SI] = [a + SI]: BL = 48h ('H').

AX006CAHALBX0048BHBLSI0001a dizisia[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00

SI = 1: bir sonraki bayt.

AX006CAHALBX6548BHBLSI0001a dizisia[0]48a[1]65a[2]6Ca[3]6Ca[4]6Fa[5]00

BH = a[1] = 65h ('e'). BX = 6548h.

AX006CAHALBX6548BHBLSI0001a dizisia[0]48a[1]45a[2]6Ca[3]6Ca[4]6Fa[5]00

Dizi bayt türünde olduğu için boyut belli: a[1] ← 45h ('E'). Dizi artık “HEllo”.

AX006CAHALBX6548BHBLSI0001a dizisia[0]48a[1]45a[2]6Ca[3]6Ca[4]6Fa[5]00

RET. Dizi tanımı kodun sonunda, yürütülmeyen bölgede.

MOV AL, a[3]   ; a + 3
MOV SI, 0
MOV BL, a[SI]  ; a + 0
INC SI
MOV BH, a[SI]  ; a + 1
MOV a[SI], 'E' ; a[1] ← 45h
RET
a DB 48h,65h,6Ch,6Ch,6Fh,0

Diziler

Erişim Yolları ve DUP

Elemana erişim
  • Köşeli parantezle sabit indis: MOV AL, a[3]
  • Bellek indis yazmaçları (BX, SI, DI, BP) ile: MOV SI, 3 · MOV AL, a[SI]
  • Eşdeğer yazımlar: a[SI] = [a + SI] = [SI + a]
  • İndis bayt cinsindendir, eleman sayısı değil.
DUP işleci Büyük dizi için: sayı DUP(değer(ler))
  • c DB 5 DUP(9) = c DB 9, 9, 9, 9, 9
  • d DB 5 DUP(1, 2) = d DB 1, 2, 1, 2, 1, 2, 1, 2, 1, 2
  • tampon DB 100 DUP(?): 100 baytlık ilk değersiz alan
  • tablo DW 10 DUP(0): 10 sözcük = 20 bayt
c DB 5 DUP(9)0909090909d DB 5 DUP(1, 2)010201020102010201025 bayt10 bayt
DW ile sayı dizileri tanımlanabilir (w DW 1000h, 2000h); kullanılamadığı şey metin dizgileridir (DW 'Hello' geçersiz). Değerler 255'ten büyük ya da −128'den küçükse DW gerekir.

Diziler · Kodu adım adım çalıştır

Kod İzleme: DW Dizisinde İndis

AX1111AHALBX0000BHBLCX0000CHCLDX0000DHDLSI0000w dizisi (bayt bayt)w+011w+111w+222w+322w+433w+533

w[0]: ilk sözcük → AX = 1111h.

AX1111AHALBX2222BHBLCX0000CHCLDX0000DHDLSI0000w dizisi (bayt bayt)w+011w+111w+222w+322w+433w+533

İkinci eleman w[2]'dedir (her eleman 2 bayt): BX = 2222h.

AX1111AHALBX2222BHBLCX0000CHCLDX0000DHDLSI0004w dizisi (bayt bayt)w+011w+111w+222w+322w+433w+533

i. elemanın indisi = 2 × i: üçüncü eleman için SI = 4.

AX1111AHALBX2222BHBLCX3333CHCLDX0000DHDLSI0004w dizisi (bayt bayt)w+011w+111w+222w+322w+433w+533

CX = w[SI] = 3333h.

AX1111AHALBX2222BHBLCX3333CHCLDX2211DHDLSI0004w dizisi (bayt bayt)w+011w+111w+222w+322w+433w+533

w[1] elemanın ortasından okur: baytlar 11h, 22h → DX = 2211h. Sık yapılan hata!

MOV AX, w[0]   ; 1. eleman
MOV BX, w[2]   ; 2. eleman
MOV SI, 4
MOV CX, w[SI]  ; 3. eleman
MOV DX, w[1]   ; dikkat!
RET
w DW 1111h, 2222h, 3333h

Diziler

Tanımdan Bayta

Yazılan DB / DW / DD satırı baytlara açılır. Sayılar (onluk, h, b, o), 'metin' (yalnız DB), ? ve n DUP(…) desteklenir. Hücre üstü: değişkenin başından bayt uzaklığı.

Diziler

Dizgiler ve Sonlandırıcılar

s1 DB 'Merhaba', 0             ; sıfırla biten dizgi
s2 DB 'Merhaba$'               ; '$' ile biten (INT 21h / AH = 09h)
s3 DB 13, 10, 'Satır', 13, 10, '$' ; CR LF: satır başı + yeni satır
s4 DB 7, 'Merhaba'             ; uzunluk önekli: ilk bayt = 7
s5 DB "Ali'nin", 0             ; çift tırnak içinde tek tırnak
BiçimSonu nasıl anlaşılır?Nerede kullanılır?
0 ile bitenokunan bayt 0 oluncaemu8086.inc PRINT_STRING, C dili
'$' ile bitenokunan bayt 24h oluncaDOS dizgi yazdırma hizmeti
uzunluk önekliilk bayttaki sayı kadarDOS satır girişi tamponu (AH = 0Ah)
  • Dizginin bellekte kapladığı yer = karakter sayısı + sonlandırıcı: s1 için 8 bayt. Sonlandırıcı unutulursa yazdırma, dizginin ardındaki baytları da karakter sanıp devam eder.
  • '$' ile biten bir dizgi '$' karakterini yazdıramaz. Türkçe harflerin (ç, ğ, ş…) kodu kullanılan kod sayfasına bağlıdır; ASCII'nin 0–127 aralığında değildir.

Diziler

Karakter Sabitleri ve ASCII Aritmetiği

KarakterlerASCII kodları
'0' … '9'30h … 39h
'A' … 'Z'41h … 5Ah
'a' … 'z'61h … 7Ah
boşluk · '$'20h · 24h
CR · LF0Dh · 0Ah
  • Tırnak içindeki karakter assembler için yalnızca bir sayıdır: MOV AL, 'A' = MOV AL, 41h.
  • Rakam karakterinden sayıya: SUB AL, '0' ('7' = 37h → 7). Ters yön: ADD AL, '0'.
  • Büyük ve küçük harf arasındaki fark 20h, yani yalnızca bit 5'tir: SUB AL, 20h ya da AND AL, 0DFh büyütür, OR AL, 20h küçültür.
AND AL, 0DFh yalnızca harflerde doğru çalışır. '1' (31h) üzerinde uygulanırsa sonuç 11h olur ve rakam bozulur; bu yüzden harf olup olmadığı önce denetlenir ('a' ≤ AL ≤ 'z').

Diziler · Kodu adım adım çalıştır

Kod İzleme: Dizgiyi Büyük Harfe Çevirme

ORG 100h
LEA SI, s
don:
MOV AL, [SI]
CMP AL, 0          ; sonlandırıcı?
JE bitti
CMP AL, 'a'
JB sonraki
CMP AL, 'z'
JA sonraki
SUB AL, 20h        ; 'a' - 'A'
MOV [SI], AL
sonraki:
INC SI
JMP don
bitti:
RET
s DB 'Ab1c', 0
s41'A'62'b'31'1'63'c'0000SI = 0119hAL00h

LEA SI, s: SI = 0119h, dizginin ilk baytı. Dizgi 'Ab1c' ve sonlandırıcı 0.

s41'A'62'b'31'1'63'c'0000SI = 011AhAL41h

'A' (41h): 0 değil; CMP AL, 'a' → 41h < 61h, JB atlar. Büyük harf olduğu için yazılmadı; SI ilerledi.

s41'A'42'B'31'1'63'c'0000SI = 011BhAL42h

'b' (62h): 'a' ≤ 62h ≤ 'z' → SUB AL, 20h = 42h ('B'), MOV [SI], AL belleğe geri yazar.

s41'A'42'B'31'1'63'c'0000SI = 011ChAL31h

'1' (31h): 'a'dan küçük, atlanır. Harf denetimi olmasaydı 31h − 20h = 11h ile rakam bozulurdu.

s41'A'42'B'31'1'43'C'0000SI = 011DhAL43h

'c' (63h) → 43h ('C'). Dizgi artık 'AB1C'.

s41'A'42'B'31'1'43'C'0000AL00hsonlandırıcı: ZF = 1

Okunan bayt 0: CMP AL, 0 → ZF = 1, JE bitti. Döngü dizginin uzunluğunu bilmeden, sonlandırıcıda durdu.

Dizgi yerinde değiştirildi: her bayt okunur, harfse 20h çıkarılıp aynı adrese yazılır. Uzunluk yerine sonlandırıcı (0) kullanıldı.

Diziler

İki Boyutlu Diziler (Tablolar)

[0][0][0][1][0][2][0][3][1][0][1][1][1][2][1][3][2][0][2][1][2][2][2][3]mantıksal görünümbellekte satır öncelikli düzen01234567891011uzaklık = satır × 4 + sütun[2][1] → 2 × 4 + 1 = 9
mat DB 3 DUP(4 DUP(0)) ; 3 × 4
tab DW 3 DUP(4 DUP(0)) ; 24 bayt
  • Bellek tek boyutludur; tablo satır öncelikli düzende yerleşir: önce 0. satırın tüm sütunları, sonra 1. satır…
  • Bağıl uzaklık = (satır × sütun sayısı + sütun) × eleman boyu.
  • Sözcük tablosunda [1][2]: (1 × 4 + 2) × 2 = 12 bayt.
  • İç içe DUP satır ve sütunu birlikte ayırır: 3 kez (4 kez 0).
Sütun sayısı 2'nin kuvvetiyse çarpma yerine kaydırma yeterlidir: satır × 4 için iki kez SHL. Satır sayısı dizinin yerleşimine girmez; yalnızca satır indisinin sınırını belirler.

Diziler · Kodu adım adım çalıştır

Kod İzleme: mat[2][1] Elemanını Okuma

SUTSAY EQU 4
ORG 100h
MOV AL, satir      ; AL = 2
MOV BL, SUTSAY     ; BL = 4
MUL BL             ; AX = 2 × 4
ADD AL, sutun      ; + 1
MOV SI, AX         ; SI = 9
MOV DL, mat[SI]    ; mat[2][1]
RET
mat DB 11h, 12h, 13h, 14h
    DB 21h, 22h, 23h, 24h
    DB 31h, 32h, 33h, 34h
satir DB 2
sutun DB 1
AX0002hBL00hSI0000hDL00h11012113214321422523624731832933103411

AL ← satir = 2. Hedef eleman: mat[2][1]. Tablo 0112h adresinde, 3 satır × 4 sütun bayt.

AX0002hBL04hSI0000hDL00h11012113214321422523624731832933103411

SUTSAY EQU 4 komuta gömülür: BL = 04h (sütun sayısı).

AX0008hBL04hSI0000hDL00h11012113214321422523624731832933103411

MUL BL: AX = AL × BL = 2 × 4 = 0008h. 2. satırın başı, tablonun 8. baytı.

AX0009hBL04hSI0000hDL00h11012113214321422523624731832933103411

ADD AL, sutun: 8 + 1 = 9. AH zaten 0 olduğu için AX = 0009h.

AX0009hBL04hSI0009hDL00h11012113214321422523624731832933103411

Uzaklık indis yazmacına alınır: SI = 0009h. AL indis olarak kullanılamaz; adreslemede yalnız BX, SI, DI, BP.

AX0009hBL04hSI0009hDL32h11012113214321422523624731832933103411mat[2][1]

mat[SI] = [0112h + 9]: DL = 32h. 2. satır 1. sütun.

AX0009hBL04hSI0009hDL32h11012113214321422523624731832933103411

RET. Sabit adı SUTSAY seçildi: SUTUN EQU 4 yazılsaydı assembler büyük-küçük harfe duyarsız olduğundan sutun DB 1 ile aynı ad olur ve “iki kez tanımlı” hatası verirdi.

Satır ve sütun çalışma anında değişkenlerden okundu; aynı kod her eleman için çalışır. Sözcük tablosunda sonuç ayrıca 2 ile çarpılırdı.

Adresler

Değişkenin Adresini Alma

LEA (Load Effective Address)Değişkenin adresini (bağıl konum) yazmaca yükler: LEA BX, VAR1. İndisli değişkenlerin adresini almak için de kullanılabilir: LEA BX, a[SI].
OFFSETAssembler işlecidir; değişkenin bağıl konum değerini derleme anında sağlar: MOV BX, OFFSET VAR1.
VAR1 · 010Dh22hLEA BX, VAR1010DhadresMOV AL, VAR122hdeğer
Değişkenin adresi, bir prosedüre parametre geçirmek için çok kullanışlıdır: prosedüre büyük bir dizinin kendisi değil, yalnızca 16 bitlik adresi verilir.
KomutBX'e ne yüklenir?
MOV BX, VAR1 (VAR1 DW)VAR1'in değeri (içerik)
LEA BX, VAR1 · MOV BX, OFFSET VAR1VAR1'in adresi (bağıl konum)

Adresler · Kodu adım adım çalıştır

Kod İzleme: LEA ile Değişken Güncelleme

AX0000AHALBX0000BHBLDS:010C … (VAR1 = 010Dh)010CC3010D22010E00

Kod 0100h'den başlar; derleyici VAR1'i 010Dh'ye yerleştirdi (12 bayt kod + RET).

AX0022AHALBX0000BHBLDS:010C … (VAR1 = 010Dh)010CC3010D22010E00

AL = VAR1'in değeri = 22h.

AX0022AHALBX010DBHBLDS:010C … (VAR1 = 010Dh)010CC3010D22010E00

BX = VAR1'in adresi = 010Dh. BX artık VAR1'i gösteren bir işaretçidir.

AX0022AHALBX010DBHBLDS:010C … (VAR1 = 010Dh)010CC3010D44010E00

[BX] üzerinden VAR1 güncellenir: [010Dh] = 44h.

AX0044AHALBX010DBHBLDS:010C … (VAR1 = 010Dh)010CC3010D44010E00

VAR1 tekrar okunur: AL = 44h. Değişkene adı ile de işaretçi ile de erişilebilir.

AX0044AHALBX010DBHBLDS:010C … (VAR1 = 010Dh)010CC3010D44010E00

RET. END kaynak dosyanın sonunu bildiren direktiftir.

ORG 100h
MOV AL, VAR1          ; değer
LEA BX, VAR1          ; adres
MOV BYTE PTR [BX], 44h
MOV AL, VAR1          ; yeni değer
RET
VAR1 DB 22h
END

Adresler

LEA ve OFFSET Aynı mı?

OFFSET ile aynı program

ORG 100h
MOV AL, VAR1
MOV BX, OFFSET VAR1
MOV BYTE PTR [BX], 44h
MOV AL, VAR1
RET
VAR1 DB 22h
END
  • emu8086'da LEA BX, VAR1 ve MOV BX, OFFSET VAR1 aynı makine koduna derlenir: BB 0D 01 (3 bayt, MOV BX, 010Dh). İki programda da VAR1 = 010Dh'dir.
  • Gerçek 8086 assembler'ı MASM ise LEA'yı ayrı bir komut olarak kodlar: 8D 1E 0D 01 (4 bayt).
  • Fark: LEA BX, a[SI] adresi çalışma anında hesaplar (a + SI); OFFSET yalnızca sabit adres verir.
  • Köşeli parantez içinde yalnızca BX, SI, DI, BP kullanılabilir.

Adresler · Kodu adım adım çalıştır

Kod İzleme: LEA a[BX] ile OFFSET a

ORG 100h
MOV BX, 2
LEA SI, a[BX]      ; SI = a + BX
MOV DI, OFFSET a   ; sabit adres
ADD DI, BX         ; elle ekle
MOV AL, [SI]
INC BX
LEA SI, a[BX]      ; yeni adres
MOV AH, [SI]
RET
a DB 'ABCD'
a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119BX0002hSI0000hDI0000hAX0000h

BX = 2: indis. a dizisi 0116h'de başlıyor: 'A' 'B' 'C' 'D'.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIBX0002hSI0118hDI0000hAX0000h

LEA SI, a[BX]: adres çalışma anında hesaplanır: 0116h + 2 = 0118h. Bellek okunmaz.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0002hSI0118hDI0116hAX0000h

OFFSET a derleme anında bilinen sabittir: DI = 0116h. BX'i katamaz.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0002hSI0118hDI0118hAX0000h

Aynı adres için OFFSET ile ayrıca ADD gerekir: DI = 0118h = SI.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0002hSI0118hDI0118hAX0043h

AL = [SI] = 43h ('C').

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0003hSI0118hDI0118hAX0043h

BX = 3.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0003hSI0119hDI0118hAX0043h

LEA güncel BX ile yeniden hesaplar: SI = 0119h.

a'A' 41h0116'B' 42h0117'C' 43h0118'D' 44h0119SIDIBX0003hSI0119hDI0118hAX4443h

AH = [SI] = 44h ('D'). AX = 4443h.

LEA adresi yazmaçlarla çalışma anında hesaplar; OFFSET yalnızca derleme anında bilinen sabit adresi verir.

Adresler

İşaretçi Değişkenleri

ORG 100h
MOV BX, p          ; 010Bh
LEA SI, p          ; 010Fh
MOV DI, OFFSET dizi
RET
dizi DB 'KAYA'     ; 010Bh
p    DW dizi       ; 010Fh, içi 010Bh
uzak DD dizi       ; bağıl konum + kesim
  • DW'nin değeri bir değişken adı olursa o değişkenin adresi saklanır: p bir işaretçi değişkendir.
  • İşaretçi bellekte durduğu için değiştirilebilir: ADD p, 2 onu dizinin ilerisine kaydırır.
  • Kullanmak için önce bir adres yazmacına alınır: MOV BX, p · MOV AL, [BX].
  • DD ile tanımlanan uzak işaretçi bağıl konum ve kesimi birlikte tutar; LDS SI, uzak ya da LES DI, uzak ile tek komutta yüklenir.
KomutYazmaca ne yüklenir?Değer
MOV BX, pp'nin içindeki adres (dizinin adresi)010Bh
LEA SI, pp'nin kendi adresi010Fh
MOV DI, OFFSET dizidizinin adresi, derleme anında sabit010Bh

Adresler · Kodu adım adım çalıştır

Kod İzleme: Bellekteki İşaretçi

ORG 100h
MOV BX, p          ; p'nin içi
MOV AL, [BX]       ; dizi[0]
ADD p, 2           ; ilerlet
MOV BX, p
MOV AH, [BX]       ; dizi[2]
RET
dizi DB 'KAYA'
p    DW dizi       ; adres
dizi4B0112410113590114410115p (0116)0112hBX0112hAX0000h

MOV BX, p: p'nin içeriği okunur. p = DW dizi olduğundan BX = 0112h, dizinin adresi.

dizi4B0112410113590114410115p (0116)0112hBX0112hAX004Bh

MOV AL, [BX]: işaretçinin gösterdiği bayt: AL = 4Bh ('K').

dizi4B0112410113590114410115p (0116)0114hBX0112hAX004Bhişaretçi kaydı

ADD p, 2: bellekteki işaretçi artık 0114h'yi gösterir. BX değişmedi; eski adresi tutuyor.

dizi4B0112410113590114410115p (0116)0114hBX0114hAX004Bh

İşaretçi yeniden yüklenir: BX = 0114h.

dizi4B0112410113590114410115p (0116)0114hBX0114hAX594Bh

MOV AH, [BX]: AH = 59h ('Y'). AX = 594Bh.

dizi4B0112410113590114410115p (0116)0114hBX0114hAX594Bh

RET. Dizinin adresi kodda hiç yazılmadı; hangi elemanın okunacağına bellekteki işaretçi karar verdi.

İşaretçi değişkeni bir adresi bellekte saklar; yazmaçlar azken pek çok dizinin konumunu tutmanın yoludur. Her kullanımda önce BX, SI ya da DI'ye alınır.

Sabitler

Sabitler (EQU)

  • Değişkenlere benzer, ancak yalnızca derleme sırasında var olurlar; bellekte yer kaplamazlar.
  • Bir sabitin değeri tanımlandıktan sonra değiştirilemez.
  • Programın farklı bölümlerinde aynı değerin kullanılmasını sağlar; değer tek yerden güncellenir.
  • Tanım: ad EQU <herhangi bir ifade>
  • Assembler her kullanımda adı değeriyle değiştirir: MOV AX, k → MOV AX, 5 (B8 05 00).
k      EQU 5
SATIR  EQU 80

MOV AX, k        ; AX = 5
MOV BX, SATIR*2  ; BX = 160
MOV CL, k+1      ; CL = 6
k EQU 5k DB 5
Bellekkullanmaz1 bayt
MOV AL, kAL ← 5 (anlık)AL ← [k] (bellekten)
Değiştirilebilir mi?hayırevet: MOV k, 7

Sabitler · Kodu adım adım çalıştır

Kod İzleme: EQU Komuta Gömülür

k     EQU 5
SATIR EQU 80
ORG 100h
MOV AX, k        ; MOV AX, 5
MOV BX, SATIR*2  ; MOV BX, 160
MOV CL, k+1      ; MOV CL, 6
MOV DL, v        ; bellekten
RET
v DB 5           ; 1 bayt yer
semboller (derleme)k5bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0000hBX0000hCL00hDL00h

k EQU 5: assembler sembol tablosuna k = 5 yazar. Bellekte yer ayrılmaz, makine kodu üretilmez.

semboller (derleme)k5SATIR80bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0000hBX0000hCL00hDL00h

SATIR = 80 da yalnız derleme anında vardır. Program 0100h'den başlar; ilk bayt MOV AX, k'nın kodudur.

semboller (derleme)k5SATIR80v010Dh (adres)bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0005hBX0000hCL00hDL00h

MOV AX, k → MOV AX, 5 (B8 05 00): 5 komutun içinde, anlık değer. AX = 0005h.

semboller (derleme)k5SATIR80v010Dh (adres)bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0005hBX00A0hCL00hDL00h

SATIR*2 derleme anında hesaplandı: 160 = 00A0h → BX = 00A0h.

semboller (derleme)k5SATIR80v010Dh (adres)bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0005hBX00A0hCL06hDL00h

k+1 = 6 → CL = 06h. Çalışma anında toplama yapılmadı.

semboller (derleme)k5SATIR80v010Dh (adres)bellek (kesim 0700h)0100B8 05 00MOV AX, 50103BB A0 00MOV BX, 1600106B1 06MOV CL, 601088A 16 0D 01MOV DL, [010Dh]010CC3RET010D05vAX0005hBX00A0hCL06hDL05h

v bir değişken: komut adresini (010Dh) taşır, değer bellekten okunur: DL = 05h. v 1 bayt yer kaplar, k hiç kaplamaz.

Makine kodları MASM/emu8086 kodlamasıdır: B8 iw (MOV AX, sabit), BB iw (MOV BX, sabit), B1 ib (MOV CL, sabit), 8A 16 adres (MOV DL, [adres]).

Sabitler

Konum Sayacı ($) ve Boyut İşleçleri

  • Assembler bir sonraki baytın yerleşeceği bağıl konumu bir sayaçta tutar: konum sayacı. Kaynakta $ ile okunur.
  • Bir dizinin hemen arkasında $ − dizi, dizinin bayt sayısıdır. Dizi büyüyüp küçülse de sabit kendiliğinden doğru kalır.
  • EQU satırı dizinin hemen ardından gelmelidir; araya başka bir tanım girerse onun baytları da sayılır.
  • MASM'daki TYPE, LENGTHOF ve SIZEOF işleçleri aynı bilgiyi değişkenin tanımından okur.
s DB 'Merhaba', 0
n EQU $ - s        ; 8
w DW 10 DUP(0)
İfadeDeğerAnlamı
n8s'nin bayt sayısı
TYPE s1eleman boyu (DB)
LENGTHOF s8eleman sayısı
TYPE w2eleman boyu (DW)
LENGTHOF w10eleman sayısı
SIZEOF w20LENGTHOF × TYPE
Hepsi derleme anı sabitidir: MOV CX, LENGTHOF w komuta 10 gömer, bellekte yer kaplamaz. Sözcük dizisinde döngü sayacı LENGTHOF, bayt uzunluğu SIZEOF ile alınır.

Sabitler · Kodu adım adım çalıştır

Kod İzleme: $ ile Boyut, Döngüyle En Büyük Eleman

ORG 100h
JMP basla
dizi DB 12, 47, 5, 31
n EQU $ - dizi     ; 4
enb DB ?
basla:
MOV CX, n          ; CX = 4
MOV SI, 0
MOV AL, dizi[SI]   ; ilk aday
bak:
CMP AL, dizi[SI]
JAE gec            ; AL >= eleman
MOV AL, dizi[SI]   ; yeni aday
gec:
INC SI
LOOP bak
MOV enb, AL
RET
dizi12010247010350104310105enb00hCX0004hSI0000hAL0ChAL = 12

JMP basla veriyi atlar. n EQU $ − dizi = 4 derleme anında hesaplandı: CX = 0004h. İlk eleman aday: AL = 12.

dizi12010247010350104310105enb00hCX0003hSI0001hAL0ChAL = 12

1. tur: 12 ile 12 karşılaştırılır; JAE atlar (eşit). SI = 1, LOOP: CX = 3.

dizi12010247010350104310105enb00hCX0002hSI0002hAL2FhAL = 47

2. tur: 12 < 47 → CF = 1, JAE atlamaz; AL = 47 (2Fh). SI = 2, CX = 2.

dizi12010247010350104310105enb00hCX0001hSI0003hAL2FhAL = 47

3. tur: 47 ≥ 5 → atlanır, AL değişmez. SI = 3, CX = 1.

dizi12010247010350104310105enb00hCX0000hSI0004hAL2FhAL = 47

4. tur: 47 ≥ 31 → atlanır. LOOP: CX = 0, döngü biter.

dizi12010247010350104310105enb2FhCX0000hSI0004hAL2FhAL = 47enb = 47

MOV enb, AL: en büyük eleman 2Fh = 47 belleğe yazıldı; RET.

Döngü sayısı elle yazılmadı; diziye eleman eklenirse n kendiliğinden değişir. JAE işaretsiz karşılaştırır; işaretli dizilerde JGE kullanılır.

Örnek Programlar · Kodu adım adım çalıştır

Kod İzleme: Değişkenler Arasında Veri Taşıma

AX0000AHALdeğişkenler (DS)value10Avalue1+100value200value2+100

jmp start CPU'yu verilerin üzerinden atlatır; aksi hâlde veri baytları komut gibi yürütülürdü.

AX000AAHALdeğişkenler (DS)value10Avalue1+100value200value2+100

value1 → AX = 000Ah. Bellekten belleğe doğrudan MOV olmadığı için ara yazmaç gerekir.

AX000AAHALdeğişkenler (DS)value10Avalue1+100value20Avalue2+100

AX → value2: bellekte 0A 00. Artık value1 = value2 = 10.

AX000AAHALdeğişkenler (DS)value10Avalue1+100value20Avalue2+100

end start: kaynağın sonu; start programın giriş noktasıdır.

jmp start
value1 DW 10    ; 2 baytlık değişken
value2 DW 0     ; ikinci değişken
start:
MOV AX, value1  ; AX ← value1
MOV value2, AX  ; value2 ← AX
end start

Örnek Programlar · Kodu adım adım çalıştır

Kod İzleme: Değişkenleri Toplama

AX0000AHALBayraklarCF=0ZF=0SF=0OF=0PF=0AF=0değişkenler (DS)value105value1+101value203value2+101result00result+100

Başlangıç: result ? ile tanımlı; emu8086 belleğe 00 00 koyar, ama değerine güvenilmez.

AX0105AHALBayraklarCF=0ZF=0SF=0OF=0PF=0AF=0değişkenler (DS)value105value1+101value203value2+101result00result+100

AX = value1 = 0105h.

AX0208AHALBayraklarCF=0ZF=0SF=0OF=0PF=0AF=0değişkenler (DS)value105value1+101value203value2+101result00result+100

ADD bellek işlenenini doğrudan kullanabilir: 0105h + 0103h = 0208h. Bayraklar: CF = 0, ZF = 0, PF = 0 (08h'de bir adet 1).

AX0208AHALBayraklarCF=0ZF=0SF=0OF=0PF=0AF=0değişkenler (DS)value105value1+101value203value2+101result08result+102

result ← AX: bellekte 08 02 (little-endian).

AX0208AHALBayraklarCF=0ZF=0SF=0OF=0PF=0AF=0değişkenler (DS)value105value1+101value203value2+101result08result+102

Sonuç: result = 0208h = 520 (261 + 259).

jmp start
value1 DW 105h  ; ilk değer 105h
value2 DW 103h  ; ilk değer 103h
result DW ?     ; belirsiz
start:
MOV AX, value1  ; AX ← value1
ADD AX, value2  ; AX ← AX + value2
MOV result, AX  ; result ← AX
end start

Örnek Programlar · Kodu adım adım çalıştır

Kod İzleme: Büyük Olanı Bul (10, 5)

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value00max_value+100

AX = value1 = 000Ah.

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value00max_value+100

CMP çıkarma yapar ama sonucu saklamaz, yalnız bayrakları ayarlar: 10 − 5.

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value00max_value+100

JGE (işaretli ≥): SF = OF olduğundan atlanır → greater_or_equal.

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value00max_value+100

AX = value1 (zaten öyleydi; bu satır gereksiz ama zararsız).

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value0Amax_value+100

max_value ← AX = 000Ah.

AX000AAHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value10Avalue1+100value205value2+100max_value0Amax_value+100

RET: DOS'a dönüş. RET olmasaydı CPU value1'in baytlarını komut sanıp yürütürdü.

ORG 100h
MOV AX, value1     ; AX ← value1
CMP AX, value2     ; AX − value2
JGE greater_or_equal
MOV AX, value2     ; küçükse value2
JMP store_max
greater_or_equal:
MOV AX, value1
store_max:
MOV max_value, AX  ; sonucu sakla
RET
value1 DW 10
value2 DW 5
max_value DW ?

Örnek Programlar · Kodu adım adım çalıştır

Kod İzleme: Büyük Olanı Bul (3, 7)

AX0003AHALBayraklarCF=0ZF=0SF=0OF=0değişkenler (DS)value103value1+100value207value2+100max_value00max_value+100

AX = value1 = 0003h.

AX0003AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value00max_value+100

CMP çıkarma yapar ama sonucu saklamaz, yalnız bayrakları ayarlar: 3 − 7.

AX0003AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value00max_value+100

SF ≠ OF → koşul sağlanmaz, atlanmaz; sıradaki komuta geçilir.

AX0007AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value00max_value+100

AX = value2 = 0007h (büyük olan).

AX0007AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value00max_value+100

JMP koşulsuz atlar → store_max.

AX0007AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value07max_value+100

max_value ← AX = 0007h.

AX0007AHALBayraklarCF=1ZF=0SF=1OF=0değişkenler (DS)value103value1+100value207value2+100max_value07max_value+100

RET: DOS'a dönüş. RET olmasaydı CPU value1'in baytlarını komut sanıp yürütürdü.

ORG 100h
MOV AX, value1     ; AX ← value1
CMP AX, value2     ; AX − value2
JGE greater_or_equal
MOV AX, value2     ; küçükse value2
JMP store_max
greater_or_equal:
MOV AX, value1
store_max:
MOV max_value, AX  ; sonucu sakla
RET
value1 DW 3
value2 DW 7
max_value DW ?

Örnek Programlar

Karşılaştırma Notları

CMPCMP a, b = a − b hesaplanır, sonuç atılır; yalnız bayraklar (CF, ZF, SF, OF, PF, AF) güncellenir.
İşaretli / işaretsizJGE, JG, JL: işaretli (SF, OF). JAE, JA, JB: işaretsiz (CF). value1 = −1 (FFFFh), value2 = 5 için JGE atlamaz, JAE atlar.
Neden RET?Veri tanımları kodun hemen ardından gelir; RET olmasaydı CPU 0A 00 05 00… baytlarını komut olarak yürütürdü. Çözüm: RET (ya da başta jmp start).
İyileştirmegreater_or_equal altındaki MOV AX, value1 gereksizdir; AX zaten value1'dir. Etiket doğrudan store_max'e atlayabilir.
JAE (işaretsiz)0565535 (FFFFh)JGE (işaretli)0−15−3276832767FFFFh ≥ 0005h ? işaretsiz evet, işaretli hayır

Örnek Programlar

Çift Sözcük Değişken

jmp start
mydouble dd 12345678h  ; double word
mywords  dw 5678h      ; 2 ayrı word
         dw 1234h
mybytes  db 78h        ; 4 ayrı byte
         db 56h
         db 34h
         db 12h
data dd 00010010001101000101011001111000b
start:  ; data'yı DX:AX'e yükle
mov ax, word ptr data
mov dx, word ptr [data+2]

Dört tanımın da bellekteki karşılığı aynıdır:

+078+156+234+312düşük sözcük → AXyüksek → DX
  • DD 32 bit = 4 bayt; en düşük bayt en düşük adreste.
  • 8086'nın 32 bitlik yazmacı yoktur: değer DX:AX çiftinde tutulur (DX yüksek, AX düşük sözcük).

Örnek Programlar · Kodu adım adım çalıştır

Kod İzleme: DX:AX'e 32 Bitlik Yükleme

DX0000DHDLAX5678AHALdata (4 bayt)data+078data+156data+234data+312

data'nın ilk iki baytı (78 56) → AX = 5678h. word ptr: data DD olduğu için boyut açıkça belirtilir.

DX1234DHDLAX5678AHALdata (4 bayt)data+078data+156data+234data+312

data+2'deki iki bayt (34 12) → DX = 1234h. DX:AX = 1234:5678h = 12345678h.

mov ax, word ptr data      ; data+0
mov dx, word ptr [data+2]  ; data+2
ret
data dd 12345678h

Örnek Programlar

Değişkenlerle İlgili Sık Hatalar

Değer ile adresi karıştırmakMOV SI, dizi ilk sözcüğü yükler; adres için LEA SI, dizi.
Bellekten belleğe taşımakMOV v1, v2 yoktur; değer bir yazmaçtan geçer.
Sözcük dizisinde indis3. eleman w[4]'tedir: indis bayt cinsindendir.
? değerine güvenmektoplam DW ? sıfır olmayabilir; önce MOV toplam, 0.
Soneki unutmakDW 10 onluk 10'dur (000Ah); onaltılık için 10h.
Ad çakışmasıSUTUN EQU 4 ile sutun DB 1 aynı addır: “iki kez tanımlı”.
Veriyi kodun yoluna koymakRET ya da JMP yoksa veri baytları komut sanılır.
Sonlandırıcıyı unutmak0 ya da '$' yoksa yazdırma arkadaki baytlarla sürer.

Örnek Programlar

Veri Tanımlama Özeti

YazımAnlamıBellek
x DB 7bir bayt07
y DW 1234hbir sözcük34 12
z DD 12345678hçift sözcük78 56 34 12
s DB 'Hi', 0dizgi + sonlandırıcı48 69 00
t DB 3 DUP(0)tekrar00 00 00
u DW ?ilk değersiz?? ?? (emu8086: 00 00)
k EQU 10sabityer kaplamaz

Adres: LEA BX, x / MOV BX, OFFSET x. Değer: MOV AL, x. Boyut değiştirme: word ptr, byte ptr.

Özet

Özet

DeğişkenBir bellek konumuna verilen ad; derleyici adı bağıl konumla değiştirir.
DB / DW / DD1, 2, 4 bayt; little-endian; ? ilk değersiz.
ORG 100h.COM kodu 0100h'den başlar; ilk 256 bayt PSP. Veriler RET'ten sonra ya da jmp ile atlanarak.
DizilerArdışık baytlar; a[i] bayt uzaklığıdır; DUP ile tekrar; DW dizisinde indis 2 × i.
LEA / OFFSETAdres almak için; LEA çalışma anında indisli adres de hesaplar.
EQUDerleme anı sabiti; bellekte yer kaplamaz, değiştirilemez.

Özet

Alıştırmalar

  1. x DB 5, 6 · y DW 0ABCDh · z DB 'OK' tanımları 0200h'den başlıyorsa her baytın adresi ve değeri?
  2. tablo DW 10 DUP(?) kaç bayt kaplar? 7. elemanın (indis 6) bağıl uzaklığı nedir?
  3. Önceki sorudaki y için MOV AL, BYTE PTR y ve MOV AL, BYTE PTR y+1 sonrası AL?
  4. LEA SI, a[BX] ile MOV SI, OFFSET a arasındaki fark nedir?
  5. İki DW değişkenin toplamını üçüncüsüne yazan, toplamda taşma olursa (CF = 1) tasma DB 1 yapan kodu yazın.
  6. dd 0FFFFFFFFh değerine 1 eklemek için DX:AX'te hangi komut çifti gerekir?
Cevaplar
  1. 0200: 05, 0201: 06, 0202: CD, 0203: AB, 0204: 4F ('O'), 0205: 4B ('K').
  2. 20 bayt; uzaklık 6 × 2 = 12 = 0Ch.
  3. CDh ve ABh.
  4. LEA, a + BX'i çalışma anında hesaplar; OFFSET yalnızca a'nın sabit adresidir.
  5. MOV AX,v1 · ADD AX,v2 · MOV v3,AX · JNC son · MOV tasma,1 · son:
  6. ADD AX,1 · ADC DX,0 (eldeyi yüksek sözcüğe taşır).

Özet

Kaynaklar

  • emu8086 belgeleri, 8086 assembler tutorial for beginners, bölüm 3: variables (DB, DW, DUP, LEA, OFFSET, EQU).
  • Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson.
  • Kip R. Irvine, Assembly Language for x86 Processors, Pearson (veri tanımlama direktifleri).
  • Microsoft MASM 6.1 Programmer's Guide: DB/DW/DD, DUP, EQU, OFFSET.

Son

Bölüm 4.2: Değişkenler
Sonraki bölüm: Bölüm 5.1: Kesmeler · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.