Bölüm 11: Komut Kodlama ve Dizgi Komutları

Mikroişlemciler
Komut sınıflarıMakine koduModR/MMOV biçimleriXLATLEA · LDS · LESDizgi komutlarıREP önekleriJMP kodlamasıİşlemci kontrolüBayrak etkileri
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Komut sınıfları

8086'nın yaklaşık 100 komutunu altı işlevsel sınıfa ayırmak ve her sınıfın tipik kullanımını açıklamak.

Makine kodu

İşlem kodu, D/W bitleri ve ModR/M baytından bir komutun makine kodunu çıkarmak.

Dizgi komutları

MOVS, CMPS, SCAS, LODS ve STOS komutlarını REP önekleriyle kullanmak; DF, SI, DI ve CX değişimini izlemek.

Başvuru

XLAT, LEA, LDS, LES ve işlemci kontrolü komutlarını tanımak; bayrak etkileri tablosundan bir komutun hangi bayrağı değiştirdiğini okumak.

Giriş

8086 Komut Kümesine Genel Bakış

1. Veri taşımaYazmaç, bellek, yığın ve G/Ç arasında veri kopyalama.
MOV PUSH POP XCHG IN OUT XLAT LEA LDS LES LAHF SAHF PUSHF POPF
2. AritmetikDört işlem, BCD düzeltme, işaret genişletme.
ADD ADC INC AAA DAA SUB SBB DEC NEG CMP AAS DAS MUL IMUL AAM DIV IDIV AAD CBW CWD
3. Mantık, kaydırma, döndürmeBit düzeyinde işlemler.
NOT AND OR XOR TEST SHL SAL SHR SAR ROL ROR RCL RCR
4. Dizgi işlemeBellek bloklarını SI/DI ile tarama ve kopyalama.
MOVSB/W CMPSB/W SCASB/W LODSB/W STOSB/W REP REPE REPZ REPNE REPNZ
5. Kontrol aktarmaDallanma, döngü, prosedür ve kesme.
JMP Jcc (JE JNE JA JB JG JL …) LOOP LOOPE LOOPNE JCXZ CALL RET RETF INT INTO IRET
6. İşlemci kontrolüBayrakları kurma/temizleme ve işlemci durumu.
CLC STC CMC CLD STD CLI STI HLT WAIT ESC LOCK NOP

Komut Kodlama

Makine Kodu Biçimi

opcode6 bitDWMOD2REG3R/M3disp düşükdisp yüksekveri düşükveri yüksek1. bayt2. bayt (ModR/M)0 / 1 / 2 bayt yer değiştirme0 / 1 / 2 bayt anlık veriKomut uzunluğu 1–6 bayt; önekler (segment, REP, LOCK) en başa eklenebilir.
D (direction)1: REG alanı hedef; 0: REG alanı kaynak.
W (word)0: bayt (8 bit) işlem; 1: sözcük (16 bit) işlem.
ModR/MMOD işlenenin yazmaç mı bellek mi olduğunu, R/M adres biçimini, REG diğer yazmacı seçer.
Sık kullanılan komutların daha kısa özel biçimleri vardır: inc ax = 40h (1 bayt), mov ax, imm16 = B8h + 2 bayt, add al, imm8 = 04h + 1 bayt.

Komut Kodlama

REG ve MOD Alanları

REGW = 0W = 1SREG
000ALAXES (00)
001CLCXCS (01)
010DLDXSS (10)
011BLBXDS (11)
100AHSP
101CHBP
110DHSI
111BHDI
MODAnlamı
00Bellek, yer değiştirme yok (R/M = 110 ise doğrudan 16 bit adres)
01Bellek + 8 bit yer değiştirme (işaret genişletilir)
10Bellek + 16 bit yer değiştirme
11Yazmaç: R/M alanı da bir REG kodudur
Örnek: mov ax, bx → 8B C3: 100010 1 1 | 11 000 011 (D = 1, hedef REG = AX, R/M = BX). Aynı komut 89 D8 olarak da kodlanabilir (D = 0).

Komut Kodlama

R/M Alanı: Etkin Adres (EA)

R/MMOD = 00MOD = 01MOD = 10Varsayılan kesim
000[BX+SI][BX+SI+d8][BX+SI+d16]DS
001[BX+DI][BX+DI+d8][BX+DI+d16]DS
010[BP+SI][BP+SI+d8][BP+SI+d16]SS
011[BP+DI][BP+DI+d8][BP+DI+d16]SS
100[SI][SI+d8][SI+d16]DS
101[DI][DI+d8][DI+d16]DS
110[d16] doğrudan[BP+d8][BP+d16]DS / SS
111[BX][BX+d8][BX+d16]DS
  • Yalnızca BX, BP, SI, DI adres yazmacı olabilir; [ax], [cx], [si+di] geçersizdir.
  • [bp] yazılınca assembler onu [bp+0] (MOD = 01, d8 = 0) olarak kodlar; çünkü MOD = 00, R/M = 110 doğrudan adrese ayrılmıştır.
  • Kesim öneki varsayılanı değiştirir: mov al, es:[bx] → önek 26h.

Komut Kodlama

Kodlama Adım Adım: MOV CL, [BX+SI+12h]

OPCODEDWMODREGR/Mdisp81. bayt2. baytMOV CL, [BX+SI+12h]

Komut: bellekteki bir baytı CL'ye taşı. Biçim: MOV reg, r/m (işlem kodu + ModR/M + yer değiştirme).

100010OPCODEDWMODREGR/Mdisp81. bayt2. baytMOV CL, [BX+SI+12h]

MOV r/m ↔ reg ailesinin işlem kodu 100010.

100010OPCODE1D0WMODREGR/Mdisp81. bayt2. bayt8AhMOV CL, [BX+SI+12h]

D = 1: REG alanı hedeftir. W = 0: bayt işlem. 1. bayt = 1000 1010b = 8Ah.

100010OPCODE1D0W01MOD001REG000R/Mdisp81. bayt2. bayt8Ah48hMOV CL, [BX+SI+12h]

MOD = 01: bellek + 8 bit yer değiştirme. REG = 001 (CL). R/M = 000 ([BX+SI]). 2. bayt = 01 001 000b = 48h.

100010OPCODE1D0W01MOD001REG000R/M12hdisp81. bayt2. bayt8Ah48h12hMakine kodu: 8A 48 12 (3 bayt)MOV CL, [BX+SI+12h]

12h, 8 bitlik yer değiştirme olarak eklenir. Sonuç: 8A 48 12. Yer değiştirme 16 bit olsaydı MOD = 10 ve 4 bayt olurdu.

Komut Kodlama

Örnek Komutlar ve Uzunlukları

KomutMakine koduBaytNot
nop901aslında xchg ax, ax
inc ax / push bx40 / 531yazmaç kodu işlem kodunun içinde (40h+r, 50h+r)
mov al, 5B0 052B0h+r, anlık bayt
int 21hCD 212kesme numarası komutta
mov ax, 1234hB8 34 123düşük bayt önce (little-endian)
mov cl, [bx+si+12h]8A 48 123ModR/M + d8
mov es:[bx], al26 88 07326h = ES öneki
add [bx+di+1000h], dx01 91 00 104MOD = 10, d16
mov word ptr [1234h], 5678hC7 06 34 12 78 566en uzun biçim: d16 + imm16
rep movsbF3 A42F3h = REP öneki

Önekler: 26h ES, 2Eh CS, 36h SS, 3Eh DS (segment); F3h REP/REPE, F2h REPNE; F0h LOCK. emu8086'da makine kodunu görmek için derledikten sonra listing (.lst) dosyasına bakılabilir.

Komut Kodlama

MOV'un Kodlama Biçimleri

Biçimİşlem kodu (8 / 16 bit)ArdındanÖrnekKod
yazmaç → r/m88 / 89ModR/M (+ disp)mov [bx], al88 07
r/m → yazmaç8A / 8BModR/M (+ disp)mov cx, [si]8B 0C
anlık → r/mC6 / C7ModR/M (REG = 000) + disp + immmov byte ptr [bx], 5C6 07 05
anlık → yazmaçB0+r / B8+rimm8 / imm16mov si, 1000hBE 00 10
bellek → AL / AXA0 / A116 bit adresmov ax, [2000h]A1 00 20
AL / AX → bellekA2 / A316 bit adresmov [1000h], alA2 00 10
kesim yazmacı → r/m168CModR/M (REG = sreg)mov ax, es8C C0
r/m16 → kesim yazmacı8EModR/M (REG = sreg)mov ds, ax8E D8

Aynı komutun birden çok kodu olabilir: mov al, [1000h] = A0 00 10 (3 bayt) ya da 8A 06 00 10 (4 bayt). Assembler kısa biçimi seçer.

Komut Kodlama

MOV'un Kodlama Biçimleri (devam)

Kesim yazmacı kodları (sreg)ES = 00, CS = 01, SS = 10, DS = 11; ModR/M'nin REG alanına 0 + sreg olarak yazılır. mov ds, ax: 11 011 000 = D8h.
Olmayan biçimlerAnlık → kesim yazmacı yok (mov ds, 1234h geçersiz), bellek → bellek yok. mov cs, … kullanılmaz; CS yalnız JMP/CALL/RET/INT ile değişir.
mov ds, ax → 8E D811011000MOD = 11REG = 011 → DSR/M = 000 → AXES 00 · CS 01 · SS 10 · DS 11 (REG alanına 0 + sreg)

Komut Kodlama

MOD = 00, R/M = 110: [BP] Değil, [d16]

mov [1000h], bl → 88 1E 00 10

88h10001000d = 0, w = 0
1Eh00011110REG = BL
MOD = 00 ve R/M = 110 → ardından 2 bayt adres gelir: 00 10 = 1000h. Komut 4 bayttır. [BP] için assembler MOD = 01, d8 = 0 kullanır.
KomutKodNot
mov [1000h], alA2 00 10AL için kısa biçim, 3 bayt
mov [1000h], al88 06 00 10genel biçim, 4 bayt (aynı iş): ModR/M 06h = 00 000 110
mov [1000h], bl88 1E 00 10BL için kısa biçim yok
mov [bp], bl88 5E 005Eh = 01 011 110: [BP+d8], d8 = 0; kesim SS
Bir çözücü 1Eh'yi yanlışlıkla [BP] sayarsa 88 1E'yi 2 baytlık mov [bp], bl sanar; adres baytları yeni bir komut olur: 00 10 = add [bx+si], dl. Sonraki tüm sınırlar kayar ve bellek bozulur.

Komut Kodlama

Aynı Baytlar, Farklı Komutlar: Yanlış Bağıl Konumdan Çözme

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21

Bellekte 11 bayt. Bunlar kod mu, veri mi? İşlemci bunu bilmez: CS:IP nereyi gösteriyorsa oradaki baytı işlem kodu sayar.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02h

Bağıl konum 0: B4h = MOV AH, imm8 (B0h + 4) → 1 anlık bayt alır: mov ah, 02h.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41h

B2h = MOV DL, imm8 → mov dl, 41h (41h = 'A').

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21h

CDh = INT imm8 → int 21h: AH = 02h, DOS DL'deki 'A'yı ekrana yazar.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21hMOV AX, 4C00h

B8h = MOV AX, imm16 → 2 bayt, little-endian: mov ax, 4C00h.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21hMOV AX, 4C00hINT 21h

int 21h, AH = 4Ch: program sonlanır. Bağıl konum 0'dan çözüm, programcının yazdığı koddur.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21hMOV AX, 4C00hINT 21hADD DH, [BP+SI+CD41h]

IP bir bayt kaysın (bağıl konum 1). 02h = ADD r8, r/m8; ModR/M B2h = 10 110 010 → MOD = 10 (d16), REG = DH, R/M = [BP+SI]; d16 = CD41h → 4 bayt: 'A' ve INT'in işlem kodu yutuldu.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21hMOV AX, 4C00hINT 21hADD DH, [BP+SI+CD41h]AND [BX+SI+4C00h], DI

21h = AND r/m16, r16; ModR/M B8h = 10 111 000 → [BX+SI+d16], REG = DI; d16 = 4C00h. Bu komut belleğe yazar.

konum 0'dankonum 1'den0000B40001020002B20003410004CD0005210006B800070000084C0009CD000A21MOV AH, 02hMOV DL, 41hINT 21hMOV AX, 4C00hINT 21hADD DH, [BP+SI+CD41h]AND [BX+SI+4C00h], DIINT 21h

Son CD 21 iki çözümde de aynı yere düştü: çözme yeniden eşlendi. Ama AH = 02h hiç yüklenmedi, INT 21h, AH'de o an ne varsa onunla çağrılır. Anlamı baytlar değil, IP'nin başladığı yer belirler.

8086'da kod ile veri arasında donanım ayrımı yoktur: veriye atlayan bir JMP ya da yanlış hesaplanmış bir IP, baytları komut olarak yürütür. Disassembler da başlangıç noktasını bilmek zorundadır.

Veri Taşıma

Veri Taşıma Komutları

KomutİşlemÖrnek
MOV h, kh ← k (kopyalama)mov bx, [si]
PUSH k / POP hSP ← SP−2, [SS:SP] ← k / h ← [SS:SP], SP ← SP+2push ax
XCHG a, ba ↔ b (biri yazmaç olmalı)xchg al, [bx]
IN / OUTAL/AX ↔ G/Ç portuin al, 60h
XLATAL ← [DS:BX + AL]tablo çevirisi
LEA r, mr ← m'nin adresi (EA)lea si, metin
LDS / LES r, mr ← [m], DS/ES ← [m+2] (uzak işaretçi)les di, uzak
LAHF / SAHFAH ← FLAGS düşük bayt / tersi
PUSHF / POPFFLAGS'ı yığına at / yığından al
Veri taşıma komutları bayrakları etkilemez; istisnalar SAHF ve POPF'tur (bayrakları doğrudan yazarlar).

Veri Taşıma · Kodu adım adım çalıştır

Kod İzleme: XLAT ile Baytı Onaltılık Yazdırma

BX, çeviri tablosunun başlangıç bağıl konumunu (offset) alır: BX = 011Dh.

Yazdırılacak bayt: AL = 3Ch (0011 1100b).

8086'da 1'den büyük kaydırma sayısı CL ile verilir.

shr al, cl: 0011 1100 → 0000 0011. AL = 03h (yüksek nibble).

xlat: AL ← [DS:BX + AL] = tablo[3] = '3' (33h).

Karakter DL'ye kopyalanır (INT 21h/02h parametresi).

AH = 02h: DOS karakter yaz hizmeti.

DOS ekrana '3' yazar (AL de DL'nin değerini alır).

Aynı bayt yeniden alınır: AL = 3Ch.

and al, 0Fh: yüksek nibble maskelenir → AL = 0Ch.

tablo[12] = 'C' (43h).

DL = 43h. AH hâlâ 02h olduğundan yeniden yüklemeye gerek yok.

Ekrana 'C' yazılır → çıktı 3C.

Program biter. XLAT, en fazla 256 baytlık tablolarla tek komutta çeviri yapar.

org 100h
mov bx, offset tablo
mov al, sayi       ; AL = 3Ch
mov cl, 4
shr al, cl         ; üst dörtlü
xlat               ; AL = [BX+AL]
mov dl, al
mov ah, 2
int 21h            ; DL'yi yaz
mov al, sayi
and al, 0Fh        ; alt dörtlü
xlat
mov dl, al
int 21h
ret
sayi  db 3Ch
tablo db '0123456789ABCDEF'

Veri Taşıma

Adres Yükleme: LEA, LDS, LES

  • lea si, metin ≡ mov si, offset metin; fark: LEA çalışma anında hesaplanan adresleri de verir: lea si, [bx+di+4].
  • LEA belleğe erişmez ve bayrakları etkilemez; bu yüzden toplama için de kullanılabilir: lea ax, [bx+si] → AX = BX + SI.
  • lds si, ptr: SI ← [ptr], DS ← [ptr+2]. les di, ptr aynı işi ES ile yapar.
  • Uzak işaretçi (far pointer) bellekte bağıl konum önce, kesim sonra saklanır.
mov bx, 0010h
mov di, 0004h
lea ax, [bx+di+2]  ; AX = 0016h
mov ax, [bx+di+2]  ; AX = [0016h]

; ekran belleği: B800:0000
ekran dw 0000h, 0B800h
les di, ekran      ; DI=0000h ES=B800h
mov al, 'A'
stosb             ; köşeye 'A'
LEA adresi, MOV içeriği verir: lea ax, [bx+di+2] ile mov ax, [bx+di+2] arasındaki fark sınavlarda sık sorulur.

Veri Taşıma · Kodu adım adım çalıştır

Adres mi, İçerik mi? LEA, MOV ve LES

org 100h
lea bx, veri        ; BX ← adres
mov di, 2
lea ax, [bx+di+2]   ; AX ← EA
mov ax, [bx+di+2]   ; AX ← [EA]
les di, ekran       ; uzak işaretçi
mov al, 'A'
stosb               ; ES:[DI] ← AL
ret
veri  dw 1111h, 2222h, 3333h
ekran dw 0000h, 0B800h
BX0115hDI0000hAX0000hES0700hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesim

LEA, veri değişkeninin adresini verir: BX = 0115h. Bellek okunmaz.

BX0115hDI0002hAX0000hES0700hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesim

DI = 2.

BX0115hDI0002hAX0119hES0700hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesimEA = BX + DI + 2 = 0119h (adres)

LEA AX, [BX+DI+2]: yalnız etkin adres hesaplanır → AX = 0115h + 2 + 2 = 0119h. Belleğe dokunulmaz, bayrak değişmez.

BX0115hDI0002hAX3333hES0700hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesim[EA] = 3333h (içerik)

MOV AX, [BX+DI+2]: aynı EA'daki içerik okunur → AX = 3333h (veri'nin 3. sözcüğü).

BX0115hDI0000hAX3333hESB800hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesimES:DI → B8000h:00

LES DI, ekran: bellekteki uzak işaretçi (bağıl konum önce, kesim sonra) → DI = 0000h, ES = B800h.

BX0115hDI0000hAX3341hESB800hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesimES:DI → B8000h:00

AL = 41h ('A').

BX0115hDI0001hAX3341hESB800hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesimES:DI → B8000h:'A'

STOSB: ES:[DI] = B800h × 10h + 0000h = B8000h ← 41h; DF = 0 olduğundan DI = 1. Ekranın sol üst köşesinde 'A'.

BX0115hDI0001hAX3341hESB800hveri (DS:0115h)1111h0115h2222h0117h3333h0119hekran (uzak işaretçi)0000hbağıl konumB800hkesimES:DI → B8000h:'A'

RET: program biter.

Aritmetik ve Mantık

Aritmetik, Mantık ve Kaydırma Komutları: Özet

GrupKomutlarAçıklama
ToplamaADD ADC INCADC eldeyi (CF) de ekler; INC CF'yi değiştirmez
ÇıkarmaSUB SBB DEC NEG CMPSBB ödüncü (CF) de çıkarır; NEG = 0 − h; CMP sonucu yazmaz
ÇarpmaMUL IMULişaretsiz / işaretli; örtük AL veya AX
BölmeDIV IDIVişaretsiz / işaretli; bölüm + kalan
BCD düzeltmeDAA DAS AAA AAS AAM AADikili sonucu onluğa düzeltir
İşaret genişletmeCBW CWDAL → AX, AX → DX:AX
MantıkAND OR XOR NOT TESTbit temizleme, kurma, tersleme; TEST sonucu yazmaz
Kaydırma / döndürmeSHL SAL SHR SAR ROL ROR RCL RCRkaydırma sayısı 1 ya da CL; çıkan bit CF'ye
İşlemci toplamayı ve çıkarmayı tek bir devreyle yapar; sayının işaretli mi işaretsiz mi olduğunu bilmez. Bu yüzden her iki yorum için bayrak üretir: CF işaretsiz taşmayı, OF işaretli taşmayı gösterir.

Dizgi İşleme

Dizgi (String) Komutları

KomutİşlemGüncellenenBayrak
MOVSB / MOVSW[ES:DI] ← [DS:SI]SI, DI–
CMPSB / CMPSW[DS:SI] − [ES:DI]SI, DICMP gibi
SCASB / SCASWAL/AX − [ES:DI]DICMP gibi
LODSB / LODSWAL/AX ← [DS:SI]SI–
STOSB / STOSW[ES:DI] ← AL/AXDI–
Kaynak / hedefKaynak DS:SI (segment öneki ile değişebilir), hedef her zaman ES:DI.
Yön bayrağıcld → DF = 0, adresler artar; std → DF = 1, azalır.
AdımB (bayt) sürümünde ±1, W (sözcük) sürümünde ±2.

EXE programlarında ES ayrıca ayarlanmalıdır (mov ax, @data / mov es, ax); COM programlarında DS = ES = CS'dir.

Dizgi İşleme

Yineleme Önekleri: REP, REPE, REPNE

ÖnekSürdürme koşuluKullanım
REPCX ≠ 0MOVS, STOS
REPE / REPZCX ≠ 0 ve ZF = 1CMPS, SCAS: "eşitken"
REPNE / REPNZCX ≠ 0 ve ZF = 0CMPS, SCAS: "eşit değilken"
1. CX = 0 ise dur (komut hiç çalışmayabilir).
2. Dizgi komutunu bir kez yürüt, SI/DI'yi güncelle.
3. CX ← CX − 1 (bayraklar değişmez).
4. REPE/REPNE ise ZF koşulunu sına; sağlanmıyorsa dur. Değilse 1'e dön.
; 100 baytlık blok kopyalama
cld
lea si, kaynak
lea di, hedef
mov cx, 100
rep movsb

; ekranı boşlukla doldur
mov ax, 0B800h
mov es, ax
xor di, di
mov ax, 0720h   ; ' ' + öznitelik
mov cx, 2000    ; 80×25
rep stosw

Dizgi İşleme · Kodu adım adım çalıştır

Kod İzleme: MOVSB ile Kopyalama

DF = 0: ileri yönde kopyalama.

SI = 0110h: kaynak dizgi.

DI = 0114h: hedef alan ('....').

Kopyalanacak bayt sayısı CX = 4.

movsb: bir bayt kopyalanır; SI = 0111h, DI = 0115h. Bayraklar değişmez.

CX = 0003h.

movsb: bir bayt kopyalanır; SI = 0112h, DI = 0116h. Bayraklar değişmez.

CX = 0002h.

movsb: bir bayt kopyalanır; SI = 0113h, DI = 0117h. Bayraklar değişmez.

CX = 0001h.

movsb: bir bayt kopyalanır; SI = 0114h, DI = 0118h. Bayraklar değişmez.

CX = 0000h.

hedef = 'ABCD'. mov cx, 4 + rep movsb aynı işi tek komutla yapar.

org 100h
cld
lea si, kaynak     ; DS:SI kaynak
lea di, hedef      ; ES:DI hedef
mov cx, 4
kopya:
movsb              ; [DI]←[SI], SI++, DI++
loop kopya         ; = rep movsb
ret
kaynak db 'ABCD'
hedef  db 4 dup('.')

Dizgi İşleme · Kodu adım adım çalıştır

Kod İzleme: LODSB + STOSB ile Büyük Harfe Çevirme

cld: DF = 0 → dizgi komutları SI/DI'yi artırır.

SI kaynağı gösterir: SI = 0111h (metin).

Hedef aynı dizgi: DI = 0111h. COM programında ES = DS olduğundan ES:DI aynı yeri gösterir.

5 karakter işlenecek.

lodsb: AL = [DS:SI] = 6Dh, ardından SI = 0112h.

Bit 5 temizlenir: AL = 4Dh.

stosb: [ES:DI] ← AL, ardından DI = 0112h.

CX = 0004h.

lodsb: AL = [DS:SI] = 69h, ardından SI = 0113h.

Bit 5 temizlenir: AL = 49h.

stosb: [ES:DI] ← AL, ardından DI = 0113h.

CX = 0003h.

lodsb: AL = [DS:SI] = 6Bh, ardından SI = 0114h.

Bit 5 temizlenir: AL = 4Bh.

stosb: [ES:DI] ← AL, ardından DI = 0114h.

CX = 0002h.

lodsb: AL = [DS:SI] = 72h, ardından SI = 0115h.

Bit 5 temizlenir: AL = 52h.

stosb: [ES:DI] ← AL, ardından DI = 0115h.

CX = 0001h.

lodsb: AL = [DS:SI] = 6Fh, ardından SI = 0116h.

Bit 5 temizlenir: AL = 4Fh.

stosb: [ES:DI] ← AL, ardından DI = 0116h.

CX = 0000h.

metin = 'MIKRO'. LODS/STOS çifti diziyi yerinde dönüştürmenin tipik kalıbıdır.

org 100h
cld               ; DF = 0: ileri
lea si, metin
mov di, si        ; aynı yere yaz
mov cx, 5
don:
lodsb             ; AL = [SI], SI++
and al, 0DFh      ; büyük harf
stosb             ; [DI] = AL, DI++
loop don
ret
metin db 'mikro'

Dizgi İşleme · Kodu adım adım çalıştır

Kod İzleme: REPNE SCASB ile Karakter Arama

İleri yönde tarama.

DI = 0114h: taranacak dizgi ES:DI'de olmalı.

En fazla 7 karşılaştırma.

Aranan karakter AL = 'h' (68h).

repne scasb: 'm','e','r','h' ile karşılaştırılır; 4. karşılaştırmada ZF = 1 olur ve durur. Her turda DI++ ve CX−−: DI = 0118h, CX = 0003h.

ZF = 1 (bulundu) → atlama yok.

DI eşleşmeden bir sonrayı gösterir; geri al: DI = 0117h.

Başlangıç çıkarılır: DI = 3 → 'h' 3. indiste (0'dan sayarak).

Bulunamasaydı CX = 0 ve ZF = 0 ile çıkılır, jne yok atlardı.

org 100h
cld
lea di, metin
mov cx, 7          ; uzunluk
mov al, 'h'        ; aranan
repne scasb        ; ara
jne yok
dec di             ; bulunan konum
sub di, offset metin
yok:
ret
metin db 'merhaba'

Kontrol Aktarma

Koşulsuz Atlama: JMP

TürKodErimÖrnek
Kısa (short)EB d8−128 … +127 baytjmp short dongu
Yakın (near)E9 d16aynı kesim, ±32 Kjmp basla
Uzak (far)EA IP CSherhangi bir kesimjmp far ptr hedef
Dolaylı yakınFF /4IP ← yazmaç/bellekjmp bx, jmp tablo[bx]
Dolaylı uzakFF /5CS:IP ← bellek (4 bayt)jmp dword ptr [si]
  • Kısa ve yakın atlamalar görelidir: hedef = sonraki komutun adresi + yer değiştirme. Bu sayede kod bellekte taşınabilir.
  • Dolaylı atlama ile atlama tablosu (switch-case) kurulur: shl bx, 1 / jmp tablo[bx].
  • EB FE kendine atlar (sonsuz döngü): FEh = −2 ve komut 2 bayttır.
0120: EB 1001220132: hedef+10h (sonraki komuttan sayılır)

İşlemci Kontrolü

İşlemci Kontrolü Komutları

KomutEtki
CLC / STCCF ← 0 / CF ← 1
CMCCF ← ¬CF
CLD / STDDF ← 0 / 1 (dizgi yönü)
CLI / STIIF ← 0 / 1 (INTR kesmeleri)
KomutEtki
HLTkesme ya da RESET gelene kadar dur
WAITTEST̅ ucu etkinleşene kadar bekle (8087 eşlemesi)
ESCkomutu yardımcı işlemciye (8087) ilet
LOCKönek: sonraki komut süresince LOCK̅ ucu → yol kilitlenir
NOPhiçbir şey yapma (90h), 3 saat turu
CLC/STCProsedürden başarı/hata döndürmenin yaygın yolu: hata varsa stc, çağıran jc hata.
CLI/STIKritik bölgeyi (ör. SS:SP değiştirme) kesmelerden korur. NMI maskelenemez.
LOCKÇok işlemcili sistemde lock xchg ile atomik semafor kurulur.

Bayrak Etkileri

Bayrak Etkileri Tablosu: Hesaplama Komutları

KomutOFSFZFAFPFCF
ADD ADC SUB SBB CMP NEG******
CMPS SCAS******
INC DEC*****–
MUL IMUL*????*
DIV IDIV??????
DAA DAS?*****
AAA AAS???*?*
AAM AAD?**?*?
AND OR XOR TEST0**?*0
SHL SAL SHR SAR*¹**?**
ROL ROR RCL RCR*¹––––*

* sonuca göre değişir · 0 temizlenir · – değişmez · ? tanımsız (güvenilmez) · ¹ OF yalnızca kaydırma sayısı 1 iken tanımlı. DF, IF, TF bu komutlardan etkilenmez.

Bayrak Etkileri

Bayrak Etkileri Tablosu: Diğer Komutlar

KomutlarEtkilenen bayraklar
MOV XCHG LEA LDS LES XLAT PUSH POP IN OUT LAHF PUSHF CBW CWD NOThiçbiri
MOVS LODS STOS, REPhiçbiri
JMP Jcc LOOP LOOPE LOOPNE JCXZ CALL REThiçbiri (yalnızca okunur)
SAHFSF ZF AF PF CF ← AH
POPF, IRETtümü (yığından)
INT n, INTOIF ← 0, TF ← 0 (eski FLAGS yığında)
CLC STC CMCCF
CLD STDDF
CLI STIIF
Sık yapılan hata: cmp ile jcc arasına bayrak değiştiren bir komut (ör. inc, add) koymak. Araya yalnızca MOV, PUSH, LEA gibi bayrak etkilemeyen komutlar girebilir.

Özet

Özet

KodlamaKomut 1–6 bayt: işlem kodu (D, W) + ModR/M + yer değiştirme + anlık veri; önekler başa eklenir.
ModR/MMOD = 11 yazmaç, 00/01/10 bellek; MOD = 00, R/M = 110 doğrudan adres olduğu için [BP] d8 = 0 ile kodlanır.
Veri taşımaXLAT: AL ← [DS:BX + AL]. LEA adresi, MOV içeriği verir; LDS/LES uzak işaretçiyi yükler. Bayraklar değişmez.
DizgiDS:SI → ES:DI, DF yönü, REP/REPE/REPNE ile CX kadar yineleme; CX = 0 ise komut hiç çalışmaz.
JMPKısa (EB d8) ve yakın (E9 d16) atlama göreli, uzak ve dolaylı atlama mutlak adres kullanır.
Bayrak etkileriTaşıma, dizgi taşıma ve atlama komutları bayrak değiştirmez; CMP ile Jcc arasına bayrak etkileyen komut girmemeli.

Özet

Alıştırmalar

  1. mov dx, [bp+di+8] komutunu kodlayın (opcode 100010, d = 1, w = 1).
  2. DS = 1000h, BX = 0200h, AL = 05h iken xlat hangi fiziksel adresteki baytı AL'ye yükler?
  3. Bellekteki uzak dd değişkeninin baytları 34 12 00 B8. les di, uzak sonrası ES ve DI nedir?
  4. CX = 0 iken rep movsb kaç bayt kopyalar?
  5. CLD, CX = 5, SI = 0100h, DI = 0200h; repe cmpsb 3. baytta fark buluyor. Sonra CX, SI, DI ve ZF nedir?
  6. 0150h adresindeki jmp short komutu 0130h'ye atlıyor. Makine kodu nedir?
  7. Bir dizgideki boşlukları sayan kodu repne scasb ile yazın.
İpuçları / cevaplar
  1. MOD = 01, REG = 010 (DX), R/M = 011 ([BP+DI]) → 8B 53 08; kesim SS.
  2. EA = BX + AL = 0205h → 10000h + 0205h = 10205h.
  3. Önce bağıl konum, sonra kesim: DI = 1234h, ES = B800h.
  4. 0: REP önce CX'i sınar; CX = 0 ise dizgi komutu hiç yürütülmez.
  5. Üç karşılaştırma: CX = 2, SI = 0103h, DI = 0203h, ZF = 0. Farklı bayt SI − 1 = 0102h'dedir.
  6. Sonraki komut 0152h; 0130h − 0152h = −22h = DEh → EB DE.
  7. Her bulunuşta sayaç artırılır; CX ≠ 0 ise repne scasb yinelenir (DI kaldığı yerden devam eder).

Özet

Alıştırmalar (2)

  1. 8A 1E 34 12 baytları hangi komuttur? Aynı baytlar bir bayt kaydırılarak (bağıl konum 1'den) çözülürse ne olur?
  2. mov es, dx ve mov al, [0020h] komutlarını kodlayın.
İpuçları / cevaplar
  1. mov bl, [1234h] (8Ah: d = 1, w = 0; 1Eh = 00 011 110 → MOD = 00, R/M = 110: d16). Bağıl konum 1'den: 1E = push ds, 34 12 = xor al, 12h.
  2. 8E C2 (11 000 010: sreg = ES, R/M = DX); A0 20 00 (AL kısa biçimi, adres little-endian).

Özet

Kaynaklar

  • Intel, The 8086 Family User's Manual, 1979 (Bölüm 2: komut kümesi, Bölüm 4: komut kodlama).
  • Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009.
  • Kip R. Irvine, Assembly Language for x86 Processors, 7. baskı, Pearson, 2014.
  • Ş. Ç. Öztürk, O. Ergin, Intel 8086 ile Mikroişlemci Programlamaya Giriş, 2009.
  • emu8086 yardım belgeleri: 8086 instructions ve 8086 assembler tutorial.

Son

Bölüm 11: Komut Kodlama ve Dizgi Komutları
Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.