Bölüm 7: Akış Kontrolü

Mikroişlemciler
IP ve sıralı yürütmeKoşulsuz atlama (JMP)Tek bayrağı test eden atlamalar CMP ile karşılaştırmaİşaretli / işaretsiz atlamalarLOOP ailesi İç içe döngülerÖrnek programlar
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Atlama mekanizması

JMP ve etiketlerle programın akışını yönlendirmek; IP'nin nasıl değiştiğini ve bağıl konumun (offset) nasıl hesaplandığını açıklamak.

Koşullu atlamalar

Her koşullu atlamanın hangi bayrağa (ZF, CF, SF, OF, PF) baktığını söylemek ve zıt komutunu bulmak.

Doğru karşılaştırma

CMP sonrasında işaretsiz sayılar için JA/JB, işaretli sayılar için JG/JL ailesini doğru seçmek.

Döngüler

LOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ ve JCXZ ile sayaçlı döngüler yazmak; örnek programları adım adım izlemek.

Giriş

Program Akış Kontrolü

  • İşlemci normalde komutları bellekteki sırasıyla yürütür: her komuttan sonra IP (Instruction Pointer) komutun uzunluğu kadar artar.
  • Akış kontrol komutları IP'ye yeni bir değer yükleyerek yürütmeyi başka bir noktaya taşır.
  • Böylece karar yapıları (if/else) ve döngüler (for/while) makine düzeyinde gerçekleştirilir.
Sıralı (IP += uzunluk)Atlama (IP ← hedef)mov ax, 5mov ax, 5mov bx, 2mov bx, 2jmp calcjmp calcback: jmp stopback: jmp stopcalc: add ax, bxcalc: add ax, bxjmp backjmp backstop: retstop: ret
Koşulsuz atlamaJMP etiket: her zaman atlar.
Koşullu atlamalarTek bayrağı test edenler, işaretli ve işaretsiz sayılar için olanlar.
DöngülerLOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ, JCXZ.

Koşulsuz Atlama

JMP: Koşulsuz Atlama

  • JMP etiket kontrolü programın başka bir noktasına her koşulda aktarır; bayrakları değiştirmez.
  • Hem ileri hem geri atlayabilir.
  • Yakın (near) atlama, mevcut kod kesimi içinde (64 KB = 65.536 bayt, offset 0000h–FFFFh) her yere ulaşır; yalnızca IP değişir.
  • Uzak (far) atlama CS ve IP'yi birlikte değiştirerek başka bir kesime geçer.
  • Assembler, hedef yakınsa otomatik olarak 2 baytlık kısa (short) biçimi seçebilir.
BiçimKodBaytMenzil
JMP SHORTEB rel82−128…+127
JMP NEARE9 rel163kesim içi
JMP FAREA ofs seg5CS:IP
JMP reg/memFF /42–4dolaylı
rel8 / rel16: hedefin, atlama komutundan sonraki komutun adresine göre işaretli uzaklığı.

Koşulsuz Atlama

Etiketler

  • Etiket tanımlamak için adı yazılır ve sonuna : eklenir: dongu:
  • Harf, rakam ve _ gibi karakterlerden oluşabilir, ancak rakamla başlayamaz.
  • Ayrı bir satırda ya da bir komutun önünde tanımlanabilir: back: jmp stop
  • Etiket bellekte yer kaplamaz; assembler onu bir adrese (offset) dönüştürür.
  • Komut adları ve yazmaç adları (mov, ax …) etiket olarak kullanılamaz; her etiket bir kez tanımlanır.

Geçerli

  • dongu:
  • next_char:
  • k1:  calc:

Geçersiz

  • 1basla: rakamla başlıyor
  • mov: komut adı
  • iki kelime: boşluk içeriyor

Koşulsuz Atlama · Kodu adım adım çalıştır

Kod İzleme: JMP ile İleri ve Geri

Program 0100h adresinden başlar (org 100h, .COM programı). IP = 0100h.

mov ax, 5 (3 bayt) yürütüldü: AX = 0005h, IP = 0103h.

mov bx, 2: BX = 0002h. Sıradaki komut 0106h adresindeki jmp calc.

jmp calc: IP ← calc = 010Ah. Arada kalan back: satırı atlanır.

add ax, bx: AX = 5 + 2 = 0007h.

jmp back: geriye atlama, IP ← 0108h.

back: jmp stop: tekrar ileri atlanır, IP ← 010Eh.

ret: program sonlanır. Sonuç AX = 0007h. Akış: 1 → 2 → 3 → calc → back → stop.

org    100h
mov    ax, 5          ; ax = 5
mov    bx, 2          ; bx = 2
jmp    calc           ; 'calc' etiketine git
back:  jmp stop       ; 'stop' etiketine git
calc:
add    ax, bx         ; ax = ax + bx
jmp    back           ; 'back' etiketine dön
stop:
ret                   ; işletim sistemine dön

Koşulsuz Atlama

Bağıl Konum Hesabı

adresmakine kodukomut0100hB8 05 00mov ax, 50103hBB 02 00mov bx, 20106hEB 02jmp calc0108hEB 04back: jmp stop010Ah01 D8calc: add ax, bx010ChEB FAjmp back010EhC3stop: retjmp calc @ 0106h (2 bayt)sonraki IP = 0108hhedef calc = 010Ahrel8 = 010A − 0108 = +2kod: EB 02

İleri atlama: uzaklık, atlama komutundan sonraki adrese göre hesaplanır → +2.

adresmakine kodukomut0100hB8 05 00mov ax, 50103hBB 02 00mov bx, 20106hEB 02jmp calc0108hEB 04back: jmp stop010Ah01 D8calc: add ax, bx010ChEB FAjmp back010EhC3stop: retjmp stop @ 0108hsonraki IP = 010Ahhedef stop = 010Ehrel8 = 010E − 010A = +4kod: EB 04

İşlemci yürütürken IP ← sonraki IP + rel8 = 010Ah + 4 = 010Eh.

adresmakine kodukomut0100hB8 05 00mov ax, 50103hBB 02 00mov bx, 20106hEB 02jmp calc0108hEB 04back: jmp stop010Ah01 D8calc: add ax, bx010ChEB FAjmp back010EhC3stop: retjmp back @ 010Chsonraki IP = 010Ehhedef back = 0108hrel8 = 0108 − 010E = −6−6 = FAh (ikiye tümleyen)kod: EB FA

Geri atlama: uzaklık negatiftir ve ikiye tümleyenle saklanır: −6 → FAh. 010Eh + FFFAh = 0108h (taşan bit atılır).

Koşullu Atlamalar

Koşullu Atlama Fikri

  • Jcc etiket: koşul (cc) doğruysa IP ← etiket, değilse bir sonraki komut yürütülür.
  • Koşul, önceki bir komutun (çoğunlukla CMP, SUB, ADD, TEST, DEC) ayarladığı bayraklara bakılarak değerlendirilir.
  • Atlama komutlarının kendisi bayrakları değiştirmez.
ZFsonuç sıfır
CFelde / ödünç
SFsonuç negatif
OFişaretli taşma
PF1 sayısı çift
AFatlamada kullanılmaz
cmp / sub / …bayraklarkoşulu sağlıyor mu?evetetiket:hayırsonraki komut

Koşullu Atlamalar

Tek Bir Bayrağı Test Eden Atlamalar

KomutAnlamıKoşulZıt komut
JZ, JEJump if Zero (Equal): sıfırsa / eşitseZF = 1JNZ, JNE
JC, JB, JNAEJump if Carry (Below, Not Above or Equal): elde varsaCF = 1JNC, JNB, JAE
JSJump if Sign: sonuç negatifseSF = 1JNS
JOJump if Overflow: işaretli taşma varsaOF = 1JNO
JPE, JPJump if Parity Even: eşlik çiftsePF = 1JPO, JNP
JNZ, JNEJump if Not Zero (Not Equal)ZF = 0JZ, JE
JNC, JNB, JAEJump if Not Carry (Not Below, Above or Equal)CF = 0JC, JB, JNAE
JNSJump if Not Sign: negatif değilseSF = 0JS
JNOJump if Not OverflowOF = 0JO
JPO, JNPJump if Parity Odd (No Parity)PF = 0JPE, JP

JC/JB adındaki "C" elde (carry) bayrağıdır; "taşma" (overflow) ise OF ile ilgilidir: ikisi farklı kavramlardır.

Koşullu Atlamalar

Kodlama ve Eş Anlamlılar

  • 8086'da koşullu atlamalar sabit uzunluktadır: 2 bayt = işlem kodu + 1 baytlık bağıl konum (rel8).
  • rel8 her zaman işaretli sayıdır: sonraki komuta göre −128 bayt geriye veya +127 bayt ileriye atlanabilir.
  • Aynı koşulun farklı adları (eş anlamlılar) aynı makine koduna derlenir: JE = JZ, JNE = JNZ, JC = JB = JNAE, JNC = JNB = JAE.
  • Not: 16 bitlik uzaklıklı koşullu atlamalar (0F 8x) ancak 80386 ile gelmiştir; 8086'da yoktur.
74JE / JZ
75JNE / JNZ
72JB / JC / JNAE
73JAE / JNB / JNC
78JS
79JNS
70JO
71JNO
7AJP / JPE
7BJNP / JPO
77JA / JNBE
76JBE / JNA
7FJG / JNLE
7DJGE / JNL
7CJL / JNGE
7EJLE / JNG
E2LOOP
E1LOOPE / LOOPZ
E0LOOPNE / LOOPNZ
E3JCXZ

Hepsi 2 bayttır: işlem kodu + rel8. Kısa JMP'nin kodu EBh'dir.

Koşullu Atlamalar · Kodu adım adım çalıştır

Kod İzleme: JNC = JNB = JAE

Üç komut da aynı koşulu (CF = 0) sınar ve aynı işlem kodunu (73h) üretir; yalnızca rel8 farklıdır, çünkü her biri farklı adreste.

CF = 0 olduğundan jnc a atlar: IP ← 0102h + 07h = 0109h. Aradaki jnb, jae ve mov ax, 4 yürütülmez.

a: mov ax, 5 → AX = 0005h.

ret. CF = 1 olsaydı üç atlama da gerçekleşmez, AX önce 4 sonra 5 olurdu.

org 100h
jnc a          ; 0100h: 73 07
jnb a          ; 0102h: 73 05
jae a          ; 0104h: 73 03
mov ax, 4      ; 0106h: B8 04 00
a: mov ax, 5   ; 0109h: B8 05 00
ret            ; 010Ch: C3

Koşullu Atlamalar

Atlama Kodu Hesaplayıcı

Atlama komutunun adresini ve hedef adresi (onaltılık) girin: rel8 / rel16 değeri ve makine kodu hesaplanır.

Kural: uzaklık = hedef − (adres + komut uzunluğu). Kısa biçimde sonuç −128…+127 aralığında olmalıdır; değilse assembler "relative jump out of range" hatası verir.

Karşılaştırma

CMP Komutu

  • Sayısal değerleri karşılaştırmak için CMP hedef, kaynak kullanılır.
  • CMP, SUB (çıkarma) işlemini yapar: hedef − kaynak. Ancak sonucu hiçbir yere yazmaz; yalnızca bayrakları (CF, ZF, SF, OF, PF, AF) ayarlar.
  • Ardından gelen koşullu atlama bu bayraklara bakarak karar verir.
  • İşlenenler: yazmaç–yazmaç, yazmaç–bellek, bellek–yazmaç, yazmaç/bellek–sabit. İki bellek işleneni olamaz.
CMP 05h, 02h5 − 2 = 3 → 03hZF = 0, CF = 0, SF = 0, OF = 0
CMP 07h, 07h7 − 7 = 0 → 00hZF = 1, CF = 0, SF = 0, OF = 0
Örnek 1: 5 − 2 = 3 → sonuç sıfır değil, ZF = 0. Örnek 2: 7 − 7 = 0 → sonuç sıfır, ZF = 1 ve JE/JZ atlar.

Karşılaştırma

CMP AL, BL Bayrakları Nasıl Ayarlar?

AL0000 010105hişaretsiz 5 · işaretli 5BL0000 001002hişaretsiz 2 · işaretli 2AL−BL0000 001103hsonuç saklanmaz, yalnız bayraklarCF=0ZF=0SF=0OF=0PF=1AF=0işaretsiz: AL > BLişaretli: AL > BLCF=0, ZF=0 → JA atlarSF=0, OF=0, ZF=0 → JG atlar

Pozitif fark: hiçbir bayrak kalkmaz (PF = 1 çünkü 03h = 0000 0011 iki adet 1 içerir).

AL0000 011107hişaretsiz 7 · işaretli 7BL0000 011107hişaretsiz 7 · işaretli 7AL−BL0000 000000hsonuç saklanmaz, yalnız bayraklarCF=0ZF=1SF=0OF=0PF=1AF=0işaretsiz: AL = BLişaretli: AL = BLCF=0, ZF=1 → JE atlarSF=0, OF=0, ZF=1 → JE atlar

Eşit sayılar: sonuç 0 → ZF = 1. Hem işaretli hem işaretsiz bakışta eşitlik.

AL0000 010105hişaretsiz 5 · işaretli 5BL0000 011107hişaretsiz 7 · işaretli 7AL−BL1111 1110FEhsonuç saklanmaz, yalnız bayraklarCF=1ZF=0SF=1OF=0PF=0AF=1işaretsiz: AL < BLişaretli: AL < BLCF=1, ZF=0 → JB atlarSF=1, OF=0, ZF=0 → JL atlar

Küçükten büyük çıkarılınca ödünç alınır → CF = 1; sonuç FEh = −2 → SF = 1, taşma yok.

AL0111 11117Fhişaretsiz 127 · işaretli 127BL1000 000080hişaretsiz 128 · işaretli -128AL−BL1111 1111FFhsonuç saklanmaz, yalnız bayraklarCF=1ZF=0SF=1OF=1PF=1AF=0işaretsiz: AL < BLişaretli: AL > BLCF=1, ZF=0 → JB atlarSF=1, OF=1, ZF=0 → JG atlar

127 − (−128) = 255 işaretli 8 bite sığmaz → OF = 1. İşaretsiz bakışta 127 < 128 (CF = 1), işaretli bakışta 127 > −128 (SF = OF).

AL1111 1011FBhişaretsiz 251 · işaretli -5BL0000 001103hişaretsiz 3 · işaretli 3AL−BL1111 1000F8hsonuç saklanmaz, yalnız bayraklarCF=0ZF=0SF=1OF=0PF=0AF=0işaretsiz: AL > BLişaretli: AL < BLCF=0, ZF=0 → JA atlarSF=1, OF=0, ZF=0 → JL atlar

FBh işaretsiz 251, işaretli −5. İşaretsiz: 251 > 3 (CF = 0); işaretli: −5 < 3 (SF ≠ OF). Aynı bitler, farklı karar!

Karşılaştırma

Karşılaştırma Hesaplayıcı

İki baytı girin (ondalık −128…255 ya da 7Fh gibi onaltılık). CMP A, B sonucu, bayraklar ve hangi atlamaların gerçekleşeceği gösterilir.

Yeşil: atlar · soluk: atlamaz

Karşılaştırma

İşaretli Sayılar İçin Atlamalar

KomutAnlamıKoşulZıt komut
JE, JZJump if Equal (=) · Jump if ZeroZF = 1JNE, JNZ
JNE, JNZJump if Not Equal (<>) · Jump if Not ZeroZF = 0JE, JZ
JG, JNLEJump if Greater (>) · Not Less or EqualZF = 0 ve SF = OFJNG, JLE
JL, JNGEJump if Less (<) · Not Greater or EqualSF ≠ OFJNL, JGE
JGE, JNLJump if Greater or Equal (>=) · Not LessSF = OFJNGE, JL
JLE, JNGJump if Less or Equal (<=) · Not GreaterZF = 1 veya SF ≠ OFJNLE, JG
<> işareti "eşit değil" anlamına gelir. Greater / Less sözcükleri, sayıların ikiye tümleyen gösterimde işaretli olduğu varsayımıyla kullanılır.

Karşılaştırma

Neden SF = OF?

  • CMP A, B → A − B hesaplanır. Taşma yoksa sonucun işareti doğrudur: SF = 1 ⇔ A < B.
  • Taşma varsa (OF = 1) sonuç 8/16 bite sığmamış, işaret biti ters çıkmıştır.
  • Bu yüzden gerçek işaret = SF XOR OF: SF ≠ OF ⇔ A < B, SF = OF ⇔ A ≥ B.
ABA − B (8 bit)SFOFSonuç
57FEh (−2)10SF ≠ OF → 5 < 7
127 (7Fh)−128 (80h)FFh (−1) ✗ gerçek: +25511SF = OF → 127 > −128
−128 (80h)17Fh (+127) ✗ gerçek: −12901SF ≠ OF → −128 < 1
−5 (FBh)3F8h (−8)10SF ≠ OF → −5 < 3

Taşmalı satırlarda SF tek başına yanlış cevap verirdi; OF ile birlikte değerlendirilince karar doğru olur.

Karşılaştırma

İşaretsiz Sayılar İçin Atlamalar

KomutAnlamıKoşulZıt komut
JE, JZJump if Equal (=) · Jump if ZeroZF = 1JNE, JNZ
JNE, JNZJump if Not Equal (<>) · Jump if Not ZeroZF = 0JE, JZ
JA, JNBEJump if Above (>) · Not Below or EqualCF = 0 ve ZF = 0JNA, JBE
JB, JNAE, JCJump if Below (<) · Not Above or Equal · CarryCF = 1JNB, JAE, JNC
JAE, JNB, JNCJump if Above or Equal (>=) · Not Below · Not CarryCF = 0JNAE, JB, JC
JBE, JNAJump if Below or Equal (<=) · Not AboveCF = 1 veya ZF = 1JNBE, JA
İşaretsiz çıkarmada A < B ise ödünç alınır ve CF = 1 olur. Bu nedenle "aşağıda" (below) testi doğrudan elde bayrağıdır: JB ≡ JC.

Karşılaştırma

Above/Below mı, Greater/Less mi?

Karşılaştırmaİşaretsiz (A/B)İşaretli (G/L)
A = BJE / JZJE / JZ
A ≠ BJNE / JNZJNE / JNZ
A > BJA / JNBEJG / JNLE
A ≥ BJAE / JNBJGE / JNL
A < BJB / JNAEJL / JNGE
A ≤ BJBE / JNAJLE / JNG
HatırlatıcıAbove / Below → işaretsiz (adresler, sayaçlar, ASCII kodları). Greater / Less → işaretli (sıcaklık, fark, negatif olabilen değerler).
Tipik hataAL = FBh, BL = 03h için JA atlar (251 > 3) ama JG atlamaz (−5 < 3). Verinin türüne göre doğru aile seçilmelidir.

Karşılaştırma · Kodu adım adım çalıştır

Kod İzleme: CMP + JE

AX = 0005h.

BX = 0005h.

cmp ax, bx: 5 − 5 = 0 → ZF = 1. AX değişmez.

ZF = 1 olduğundan je atlar.

equal_message: eşitlik durumundaki işlemler burada yapılır.

jmp end_program: not_equal_message bloğu atlanır. Bu JMP olmasaydı her iki blok da yürütülürdü.

Program sonu. Eşit olmasaydı: je atlamaz, 5. satırdaki jmp ile 8. satıra gidilirdi.

mov ax, 5
mov bx, 5
cmp ax, bx
je  equal_message
jmp not_equal_message
equal_message:        ; eşitse
jmp end_program
not_equal_message:    ; eşit değilse
end_program:

Karşılaştırma · Kodu adım adım çalıştır

Kod İzleme: CMP + JA

AX = 0005h.

BX = 0007h.

cmp ax, bx: 5 − 7 = FFFEh (−2). Ödünç alındı → CF = 1, ZF = 0.

ja için CF = 0 ve ZF = 0 gerekir. CF = 1 → atlamaz.

jmp not_jump_above ile "küçük veya eşit" bloğuna gidilir.

not_jump_above: AX ≤ BX durumundaki işlemler.

Program sonu. Aynı kodda ja yerine jg kullanılsaydı da (SF ≠ OF) atlanmazdı; değerler pozitif olduğu için iki aile aynı sonucu verir.

mov ax, 5
mov bx, 7
cmp ax, bx
ja  jump_above
jmp not_jump_above
jump_above:       ; ax büyükse yapılacaklar
jmp end_program
not_jump_above:   ; ax küçük veya eşitse
end_program:

Karşılaştırma · Kodu adım adım çalıştır

Kod İzleme: Karşılaştır ve Yaz

emu8086.inc kütüphanesi putc makrosunu sağlar (AL'deki karakteri ekrana yazar).

AL = 25 = 19h.

BL = 10 = 0Ah.

cmp al, bl: 25 − 10 = 15 (0Fh) → ZF = 0.

ZF = 0 → je atlamaz.

putc 'n': ekrana n yazılır.

jmp stop: 'y' yazan blok atlanır.

Programın sonunda ret bulunmalıdır; kaynaktaki örnekte eksikti, yoksa işlemci stop'tan sonraki rastgele baytları komut sanıp yürütürdü.

include "emu8086.inc"
org    100h
mov    al, 25     ; al = 25
mov    bl, 10     ; bl = 10
cmp    al, bl     ; al - bl karşılaştır
je     equal      ; al = bl ise (zf = 1) atla
putc   'n'        ; buraya gelindiyse al <> bl:
jmp    stop       ; 'n' yaz ve stop'a atla
equal:            ; buraya gelindiyse
putc   'y'        ; al = bl, 'y' yaz
stop:
ret               ; (eklendi) DOS'a dön

Karşılaştırma

if / else Kalıbı

Yüksek düzey

if (ax == bx) {
    ; A bloğu
} else {
    ; B bloğu
}
while (cx > 0) {     ; işaretsiz
    ; gövde
}

Assembly

    cmp ax, bx
    jne degil      ; koşulun TERSİ
    ; A bloğu
    jmp son
degil:
    ; B bloğu
son:
bas: cmp cx, 0
    jbe bitti      ; cx <= 0 → çık
    ; gövde
    jmp bas
bitti:
Koşulun tersiyle blok atlanırsa kod, yüksek düzeydeki sırayı korur. A bloğunun sonundaki jmp son unutulursa B bloğu da çalışır.

Karşılaştırma

Menzil Dışı Koşullu Atlama

  • 8086'da koşullu atlama yalnızca −128…+127 bayt uzağa gidebilir.
  • Hedef daha uzaktaysa assembler hata verir. Çözüm: koşulu ters çevirip kısa atlama ile hemen sonraki komutu atlamak, uzak hedefe ise JMP (near, ±32 KB) ile gitmek.

Hatalı (hedef çok uzak)

cmp al, 0
je  cok_uzak    ; out of range!
; ... 200 baytlık kod ...
cok_uzak:

Doğru

cmp al, 0
jne devam       ; ters koşul, kısa
jmp cok_uzak    ; near JMP (E9)
devam:
; ... 200 baytlık kod ...
cok_uzak:

Döngüler

Döngü Komutları

Komutİşlem ve atlama koşulu
LOOPCX'i 1 azalt; CX ≠ 0 ise etikete atla.
LOOPECX'i 1 azalt; CX ≠ 0 ve eşitse (ZF = 1) atla.
LOOPZLOOPE ile aynı: CX ≠ 0 ve ZF = 1 ise atla.
LOOPNECX'i 1 azalt; CX ≠ 0 ve eşit değilse (ZF = 0) atla.
LOOPNZLOOPNE ile aynı: CX ≠ 0 ve ZF = 0 ise atla.
JCXZCX = 0 ise etikete atla (CX azaltılmaz).
SayaçSayaç her zaman CX yazmacıdır.
BayraklarLOOP ailesi CX'i azaltırken bayrakları değiştirmez.
MenzilHepsi 2 bayt, rel8: geriye en fazla 128 bayt.

Döngüler

LOOP Nasıl Çalışır?

  • Döngüler, bir kod bloğunun bir koşula bağlı olarak tekrarlanmasını sağlar.
  • LOOP etiket: önce CX azaltılır, CX sıfır değilse etikete atlanır. DEC CX + JNZ ile aynı etki, ama bayraklar korunur.
  • LOOPE / LOOPZ: CX ≠ 0 ve ZF = 1 olduğu sürece; LOOPNE / LOOPNZ: CX ≠ 0 ve ZF = 0 olduğu sürece atlar.
  • JCXZ: CX sıfır olduğunda etikete atlar.
  • Dikkat: CX = 0 iken döngüye girilirse ilk azaltma CX'i FFFFh yapar → gövde 65.536 kez çalışır.
mov cx, netiket:döngü gövdesiCX ← CX − 1CX ≠ 0 ?evethayır → sonraki komutLOOPE: ve ZF=1LOOPNE: ve ZF=0

Döngüler · Kodu adım adım çalıştır

Kod İzleme: LOOP

CX = 0005h: gövde 5 kez çalışacak.

1. tur: döngü içeriği yürütülür.

loop: CX = 0004h ≠ 0 → dongu'ya geri atla.

2. tur: döngü içeriği yürütülür.

loop: CX = 0003h ≠ 0 → dongu'ya geri atla.

3. tur: döngü içeriği yürütülür.

loop: CX = 0002h ≠ 0 → dongu'ya geri atla.

4. tur: döngü içeriği yürütülür.

loop: CX = 0001h ≠ 0 → dongu'ya geri atla.

5. tur: döngü içeriği yürütülür.

loop: CX = 0000h → atlama yok, döngüden çıkılır.

jmp dur: dur zaten sonraki satır olduğundan bu atlama gereksizdir ama zararsızdır.

ret: gövde toplam 5 kez çalıştı.

include "emu8086.inc"
org 100h
mov cx, 5         ; CX = tekrar sayısı (5)
dongu:
; döngü içeriği
loop dongu        ; CX ≠ 0 ise dongu'ye atla
jmp dur           ; döngü bitince dur'a atla
dur:
ret

Döngüler · Kodu adım adım çalıştır

Kod İzleme: İç İçe LOOP

BX toplam adım sayacı: 0. .COM programında SP = FFFEh.

Dış döngü 5 kez dönecek: CX = 0005h.

Dış tur 1: BX = 1.

AL = '1' (31h), AH = 0Eh → INT 10h teletype ile 1 yazılır. (0Eh işlevi BH'yi sayfa no. olarak kullanır; BX < 256 olduğundan BH = 0.)

push cx: iç döngü de CX kullanacağı için dış sayaç (5) yığına saklanır; SP = FFFCh.

İç döngü sayacı: CX = 5.

İç tur 1: BX = 2, 2 yazılır.

loop k2: CX = 4 → k2'ye dön.

4 iç tur daha: toplam 5 adet 2 yazıldı, BX = 6, CX = 0 → iç döngü biter.

pop cx: dış sayaç geri gelir: CX = 5, SP = FFFEh.

loop k1: CX = 4 → k1'e dön (dış tur 2).

Dış tur 2 bitti: BX = 12, CX = 3.

Dış tur 3 bitti: BX = 18, CX = 2.

Dış tur 4 bitti: BX = 24, CX = 1.

Dış tur 5 bitti: CX = 0 → dış döngüden çıkılır. BX = 30 = 001Eh (5 + 5×5 adım).

ret. Ekranda 5 kez "122222" vardır. push/pop dengesi sayesinde ret doğru adrese (0000h) döner.

org 100h
mov bx, 0      ; toplam adım
mov cx, 5      ; dış döngü sayacı
k1:
 add bx, 1
 mov al, '1'
 mov ah, 0eh
 int 10h       ; '1' yaz
 push cx       ; dış sayacı sakla
 mov cx, 5     ; iç döngü sayacı
k2:
  add bx, 1
  mov al, '2'
  mov ah, 0eh
  int 10h      ; '2' yaz
  loop k2      ; iç döngü
 pop cx        ; dış sayacı geri al
loop k1        ; dış döngü
ret

Döngüler · Kodu adım adım çalıştır

Kod İzleme: LOOPNE ile Dizide Arama

7[0]1[1]3[2]9[3]4[4]

En fazla 5 eleman incelenecek.

7[0]1[1]3[2]9[3]4[4]

SI = −1 (FFFFh); döngüdeki ilk inc onu 0 yapar.

7[0]1[1]3[2]9[3]4[4]SI

SI = 0.

7[0]1[1]3[2]9[3]4[4]SI

dizi[0] = 7; 7 − 3 → ZF = 0.

7[0]1[1]3[2]9[3]4[4]SI

loopne: CX = 4 ≠ 0 ve ZF = 0 → aramaya devam.

7[0]1[1]3[2]9[3]4[4]SI

SI = 1.

7[0]1[1]3[2]9[3]4[4]SI

dizi[1] = 1; 1 − 3 → ZF = 0.

7[0]1[1]3[2]9[3]4[4]SI

loopne: CX = 3 ≠ 0 ve ZF = 0 → aramaya devam.

7[0]1[1]3[2]9[3]4[4]SI

SI = 2.

7[0]1[1]3[2]9[3]4[4]SI

dizi[2] = 3; 3 − 3 → ZF = 1.

7[0]1[1]3[2]9[3]4[4]SI

loopne: CX = 2 ama ZF = 1 → döngüden çıkılır. LOOPNE bayrakları değiştirmediği için ZF = 1 korunur.

7[0]1[1]3[2]9[3]4[4]SI

ZF = 1 → jne yok atlamaz: değer bulundu.

7[0]1[1]3[2]9[3]4[4]SI

AL = 1 (bulundu), SI = 2 konumu gösterir. Döngü 5 yerine 3 turda bitti.

org 100h
mov cx, 5          ; eleman sayısı
mov si, -1         ; ilk inc ile 0 olur
ara:
inc si             ; sonraki eleman
cmp dizi[si], 3    ; aranan değer 3 mü?
loopne ara         ; CX≠0 ve ZF=0 ise sürdür
jne yok            ; ZF=0 → bulunamadı
mov al, 1          ; bulundu, konum SI'da
ret
yok:
mov al, 0          ; bulunamadı
ret
dizi db 7, 1, 3, 9, 4

Döngüler

JCXZ ve LOOP / DEC–JNZ

Sıfır turlu döngüye karşı koruma

mov cx, n        ; n çalışma anında
jcxz atla        ; CX = 0 ise girme
tekrar:
    ; gövde
    loop tekrar
atla:

JCXZ olmadan CX = 0 iken LOOP önce CX'i FFFFh yapar ve gövde 65.536 kez çalışır.

LOOP mu, DEC + JNZ mi?

LOOPDEC CX + JNZ
Boyut2 bayt1 + 2 = 3 bayt
BayraklardeğişmezZF, SF, OF, PF, AF değişir (CF korunur)
Sayaçyalnız CXherhangi bir yazmaç
Ek koşulLOOPE / LOOPNEfarklı Jcc seçilebilir

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

Kod İzleme: Dizi Elemanları Toplamı

5[0]4[1]5[2]2[3]1[4]BX

CX = 5 eleman, toplam AL = 0, indis BX = 0.

5[0]4[1]5[2]2[3]1[4]BX

add al, vector[0]: AL = 0 + 5 = 5 (05h).

5[0]4[1]5[2]2[3]1[4]BX

BX = 1, CX = 4 → next'e dön.

5[0]4[1]5[2]2[3]1[4]BX

add al, vector[1]: AL = 5 + 4 = 9 (09h).

5[0]4[1]5[2]2[3]1[4]BX

BX = 2, CX = 3 → next'e dön.

5[0]4[1]5[2]2[3]1[4]BX

add al, vector[2]: AL = 9 + 5 = 14 (0Eh).

5[0]4[1]5[2]2[3]1[4]BX

BX = 3, CX = 2 → next'e dön.

5[0]4[1]5[2]2[3]1[4]BX

add al, vector[3]: AL = 14 + 2 = 16 (10h).

5[0]4[1]5[2]2[3]1[4]BX

BX = 4, CX = 1 → next'e dön.

5[0]4[1]5[2]2[3]1[4]BX

add al, vector[4]: AL = 16 + 1 = 17 (11h).

5[0]4[1]5[2]2[3]1[4]

BX = 5, CX = 0 → döngü biter.

5[0]4[1]5[2]2[3]1[4]

mov m, al: m = 11h = 17 = 5 + 4 + 5 + 2 + 1.

5[0]4[1]5[2]2[3]1[4]

ret. Veriler ret'ten sonra tanımlandığı için komut olarak yürütülmez.

org 100h
mov cx, 5           ; eleman sayısı
mov al, 0           ; toplam (AL) = 0
mov bx, 0           ; BX = indis
next:
add al, vector[bx]  ; elemanı topla
inc bx              ; sonraki eleman
loop next           ; CX = 0 olana kadar dön
mov m, al           ; sonucu m'ye yaz
ret
vector db 5, 4, 5, 2, 1
m db 0

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

Kod İzleme: Ekrana Hello Yazdırma

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000h

jmp start: veri (msg) kodun arasında olduğu için üzerinden atlanır; yoksa 'H' (48h) gibi baytlar komut sanılırdı.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

SI = 0: ilk karakter.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

AL = msg[0] = 'H' = 48h.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

48h − 0 ≠ 0 → ZF = 0, je atlamaz.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

AH = 0Eh, INT 10h → H yazılır.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

SI = 1, jmp next_char ile başa dönülür.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

Aynı tur: AL = 'e' (65h), ZF = 0 → e yazılır, SI = 2.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

Aynı tur: AL = 'l' (6Ch), ZF = 0 → l yazılır, SI = 3.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

Aynı tur: AL = 'l' (6Ch), ZF = 0 → l yazılır, SI = 4.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

Aynı tur: AL = 'o' (6Fh), ZF = 0 → o yazılır, SI = 5.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

AL = msg[5] = 0: dizgenin sonu (null sonlandırıcı).

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000hSI

0 − 0 = 0 → ZF = 1, je stop atlar.

'H'48h'e'65h'l'6Ch'l'6Ch'o'6Fh000h

ret: ekranda Hello. (Kaynakta eksik olan org 100h ve ret eklendi.)

org     100h
jmp     start
msg db 'Hello', 0
start:
mov     si, 0          ; kaynak indisi = 0
next_char:
mov     al, msg[si]    ; karakteri al
cmp     al, 0          ; 0 ile karşılaştır
je      stop           ; 0 ise yazmayı durdur
mov     ah, 0eh        ; teletype işlevi
int     10h            ; AL'deki karakteri yaz
inc     si             ; sonraki karakter
jmp     next_char      ; başa dön
stop:
ret

Örnek Programlar

LED Ekran Aygıtı

  • emu8086, sanal aygıtlarla G/Ç (giriş/çıkış) denemeyi sağlar. #start=led_display.exe# yönergesi program çalışınca LED ekran penceresini açar.
  • #make_bin#: DOS'a bağlı olmayan düz ikili (.bin) dosya üretilir.
  • LED ekran 199 numaralı porta bağlıdır ve 2 bayt (bir word) okur. Değeri işaretli ondalık olarak 5 basamakla gösterir.
  • OUT port, AX: AX'teki 16 bitlik değeri porta yazar. Port numarası 0–255 ise doğrudan yazılabilir; daha büyükse DX ile verilir (OUT DX, AX).
123404D2h
−5678E9D2h (ikiye tümleyen)
0, 1, 2, …sayaç

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

Kod İzleme: LED Ekran Testi

888888 00000port 199 (2 bayt)

AX = 1234 = 04D2h.

888888 01234port 199 (2 bayt)

out 199, ax: LED ekranda 01234.

888888 01234port 199 (2 bayt)

AX = −5678 = E9D2h (65536 − 5678 = 59858).

888888-05678port 199 (2 bayt)

Ekran değeri işaretli yorumlar: −05678.

888888-05678port 199 (2 bayt)

Sayaç: AX = 0.

888888 00000port 199 (2 bayt)

Ekranda 00000.

888888 00000port 199 (2 bayt)

inc ax → 0001h, jmp x1 ile başa.

888888 00001port 199 (2 bayt)

Ekranda 00001.

888888 00001port 199 (2 bayt)

inc ax → 0002h, jmp x1 ile başa.

888888 00002port 199 (2 bayt)

Ekranda 00002.

888888 00002port 199 (2 bayt)

inc ax → 0003h, jmp x1 ile başa.

888888 00003port 199 (2 bayt)

Döngü koşulsuz olduğundan sonsuza dek sayar (32767'den sonra −32768'e geçer). hlt satırına hiç ulaşılmaz.

#start=led_display.exe#
#make_bin#
mov ax, 1234
out 199, ax     ; LED'e 1234 gönder
mov ax, -5678
out 199, ax     ; LED'e -5678 gönder
mov ax, 0
x1:
out 199, ax     ; sayacı göster
inc ax
jmp x1          ; sonsuz döngü
hlt             ; buraya hiç ulaşılmaz

Örnek Programlar

Palindrom Kontrolü: Fikir

  • Palindrom: baştan ve sondan okunuşu aynı olan dizi (123321, kayak).
  • DI dizinin başını, SI sonunu gösterir; karakterler karşılaştırılır, DI ileri, SI geri gider.
  • Uzunluğun yarısı kadar karşılaştırma yeterlidir (shr cx, 1 → CX / 2). Tek uzunlukta ortadaki karakter karşılaştırılmaz.
  • str_size = $ - msg: $ o anki adrestir; msg ile str aynı adreste olduğundan sonuç dizinin uzunluğu olan 6 sabitidir (bellekte yer kaplamaz).
  • INT 21h / AH = 09h: DS:DX adresindeki dizgeyi '$' karakterine kadar yazar; 0Dh, 0Ah satır başı ve yeni satırdır.
'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

Adresler org 100h ve 2 baytlık kısa jmp start (0100h) varsayımıyla verilmiştir: str 0102h'den başlar.

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

Kod İzleme: Palindrom (1/2) Hazırlık

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

jmp start: veri bölümünün üzerinden atlanır.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

AH = 09h: DOS dizge yazdırma işlevi.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

DX = offset str = 0102h.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

INT 21h: 123321 ve satır sonu yazılır ('$' yazılmaz).

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDIstr_size = 6

lea di, str: DI = 0102h (ilk karakter).

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

SI = DI = 0102h.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

SI = 0102h + 6 = 0108h: dizinin bir sonrası (0Dh).

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

dec si: SI = 0107h, son karakter '1'.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

CX = str_size = 6.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

6 − 1 ≠ 0 → ZF = 0, je atlamaz.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

shr cx, 1: 0110b → 0011b, CX = 3. Dışarı kayan bit 0 → CF = 0.

org 100h
jmp start
msg:
str db '123321'
str_size = $ - msg     ; = 6
db 0Dh,0Ah,'$'
start:
mov ah, 9              ; '$'e kadar yaz
mov dx, offset str
int 21h
lea di, str            ; DI = str adresi
mov si, di
add si, str_size       ; SI = son + 1
dec si                 ; SI = son karakter
mov cx, str_size
cmp cx, 1              ; tek karakter mi?
je is_palindrome       ; tek karakter palindromdur
shr cx, 1              ; CX = uzunluk / 2

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

Kod İzleme: Palindrom (2/2) Karşılaştırma

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

Döngü başı: DI = 0102h, SI = 0107h, CX = 3.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

AL = [DI] = '1', BL = [SI] = '1'.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

Eşit → ZF = 1, jne atlamaz.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

DI = 0103h, SI = 0106h, CX = 2 → next_char.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

AL = [DI] = '2', BL = [SI] = '2'.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

Eşit → ZF = 1, jne atlamaz.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

DI = 0104h, SI = 0105h, CX = 1 → next_char.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

AL = [DI] = '3', BL = [SI] = '3'.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

Eşit → ZF = 1, jne atlamaz.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010AhDISIstr_size = 6

CX = 0 → döngü biter: tüm çiftler eşleşti.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

AH = 09h, DX = offset msg1.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

INT 21h: palindrome! yazılır. (DOS bu işlevden AL = 24h, yani '$' ile döner.)

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

jmp stop: "not palindrome!" bloğu atlanır.

'1'0102h'2'0103h'3'0104h'3'0105h'2'0106h'1'0107h0Dh0108h0Ah0109h'$'010Ahstr_size = 6

ret. Kaynakta stop: doğrudan verilerin önündeydi; ret olmadan işlemci "palindrome!$" baytlarını komut sanıp yürütürdü.

next_char:
mov al, [di]          ; baştaki karakter
mov bl, [si]          ; sondaki karakter
cmp al, bl
jne not_palindrome    ; farklıysa değil
inc di                ; baştan bir ileri
dec si                ; sondan bir geri
loop next_char
is_palindrome:
mov ah, 9             ; "palindrome!" yaz
mov dx, offset msg1
int 21h
jmp stop
not_palindrome:
mov ah, 9             ; "not palindrome!" yaz
mov dx, offset msg2
int 21h
stop:
ret                   ; (eklendi)
msg1 db "palindrome!$"
msg2 db "not palindrome!$"

Örnek Programlar

Palindrom: Farklı Girişler

strUzunlukCX (shr sonrası)KarşılaştırmalarÇıktı
'123321'631=1, 2=2, 3=3palindrome!
'123421'631=1, 2=2, 3≠4 → jnenot palindrome!
'12321'521=1, 2=2 (ortadaki 3 atlanır)palindrome!
'7'1—cmp cx,1 → je is_palindromepalindrome!
'ab'21a≠b → jnenot palindrome!
Neden cmp cx, 1? Uzunluk 1 iken shr cx, 1 CX'i 0 yapar; LOOP'lu döngüye CX = 0 ile girilirse karşılaştırma 65.536 kez çalışırdı. Uzunluk 0 da aynı tehlikeyi taşır: jcxz ile korunabilir.

Özet

Özet

JMPKoşulsuz; IP ← hedef. Kısa (EB, ±128), yakın (E9, kesim içi), uzak (EA, CS:IP).
Bağıl konumhedef − sonraki komutun adresi; negatifse ikiye tümleyenle saklanır.
JccBayraklara bakar, bayrakları değiştirmez; 8086'da yalnız kısa (2 bayt).
CMPSonucu saklamayan SUB; ardından gelen Jcc kararı verir.
İşaretsizJA, JAE, JB, JBE → CF ve ZF.
İşaretliJG, JGE, JL, JLE → ZF, SF ve OF.
LOOP ailesiCX azalır, bayraklar korunur; LOOPE/LOOPNE ZF'ye de bakar.
TuzaklarCX = 0 ile LOOP, iç içe döngüde CX'i saklamamak, veriyi kod gibi yürütmek.

Özet

Alıştırmalar

  1. 0120h adresindeki JNE komutu 0100h adresine atlamak istiyor. Makine kodu nedir?
  2. mov al, 80h / cmp al, 1 sonrasında JA ve JG atlar mı?
  3. mov cx, 0 / d: loop d kaç kez döner? Nasıl önlenir?
  4. AX'teki işaretsiz sayı 100'den büyükse BX = 1, değilse BX = 0 yapan kodu yazın.
  5. Dizi toplamı örneğinde dizinin elemanları 200, 100 olsaydı AL ve CF ne olurdu? Çözüm önerin.
  6. Hello örneğinde jmp start satırı silinirse ne olur?
İpuçları / cevaplar
  1. Sonraki IP = 0122h; 0100h − 0122h = −22h = DEh → 75 DE.
  2. 80h − 01h = 7Fh: CF = 0, ZF = 0 → JA atlar (128 > 1). SF = 0, OF = 1 → SF ≠ OF → JG atlamaz (−128 < 1).
  3. 65.536 kez; öncesine jcxz konmalı.
  4. mov bx, 0 / cmp ax, 100 / jbe son / mov bx, 1 / son:
  5. 200 + 100 = 300 = 12Ch → AL = 2Ch, CF = 1 (taşma). Toplamı AX'te tutup adc ah, 0 ya da 16 bit toplama kullanılmalı.
  6. 'H','e','l','l','o',0 baytları (48h 65h 6Ch …) komut olarak yürütülür; program öngörülemez davranır.

Özet

Kaynaklar

  • emu8086 belgeleri: 8086 Assembler Tutorial for Beginners (Part 7: Program Flow Control).
  • Intel, The 8086 Family User's Manual, 1979: komut kümesi ve kodlama tabloları.
  • Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009: Bölüm 6 "Program Control Instructions".
  • Kip R. Irvine, Assembly Language for x86 Processors, 7. baskı, Pearson, 2014: koşullu işlem ve döngüler.

Son

Bölüm 7: Akış Kontrolü
Sonraki bölüm: Bölüm 7: Prosedürler
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.