Bölüm 6: Aritmetik, Mantık ve Kaydırma Komutları

Mikroişlemciler
Bayrak yazmacıCF · ZF · SF · OF · PF · AFKomut gruplarıADD · SUB · CMPAND · OR · XOR · TESTMUL · IMUL · DIV · IDIVINC · DEC · NOT · NEGSHL · SHR · SAR · ROL · RCRDizi toplamaBCD: AAA · AASSıcaklık dönüşümü
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Bayraklar

Bir işlemin sonucuna göre CF, ZF, SF, OF, PF ve AF bayraklarının değerini hesaplamak; CF ile OF farkını açıklamak.

Komutlar

Toplama, çıkarma, karşılaştırma, mantıksal, çarpma, bölme, tek işlenenli, kaydırma ve döndürme komutlarını doğru işlenenlerle kullanmak; kaydırmanın CF'ye etkisini izlemek.

Çarpma / bölme

MUL, IMUL, DIV, IDIV'in örtük yazmaçlarını (AL, AX, DX:AX) ve bölme hatasını bilmek.

Uygulama

Dizi toplama, BCD düzeltme ve sıcaklık dönüşümü programlarını adım adım izlemek.

Bayrak Yazmacı

Aritmetik ve Mantık Komutları

  • Aritmetik ve mantık komutlarının sonuçları, işlemcinin durum bayraklarını etkiler.
  • Bayraklar, 16 bitlik FLAGS yazmacında tutulur; her bit 0 ya da 1 olan bir bayraktır.
  • 8086'da bu 16 bitin 9'u kullanılır: 6 durum bayrağı (sonucu anlatır) ve 3 kontrol bayrağı (işlemcinin davranışını yönetir).
  • Koşullu atlamalar (JZ, JC, JO …) bu bayraklara bakarak karar verir.
1514131211OF10DF9IF8TF7SF6ZF54AF32PF10CFkontrol bayrakları: DF, IF, TFdurum bayrakları: OF, SF, ZF, AF, PF, CF

Kesik çizgili bitler 8086'da kullanılmaz.

Bayrak Yazmacı

Bayraklar Tablosu

BitBayrakTür1 olur, eğer…Örnek / not
0CF · Carrydurumişaretsiz taşma: toplamada elde, çıkarmada ödünç255 + 1 → AL = 00h, CF = 1; 7 − 9 → CF = 1; STC, CLC, CMC
2PF · Paritydurumsonucun düşük baytında çift sayıda 1 biti var96h = 1001 0110b → PF = 1; sözcük sonuçta da yalnız düşük bayt
4AF · Auxiliarydurumbit 3'ten bit 4'e elde/ödünç08h + 08h → AF = 1; yalnız AAA, AAS, DAA, DAS kullanır
6ZF · Zerodurumsonuç sıfırSUB AL, AL → ZF = 1; CMP AX, BX sonrası ZF = 1 ise AX = BX
7SF · Signdurumsonucun en anlamlı biti (MSB) 1MSB'nin kopyası: 96h → SF = 1
8TF · Trapkontrolher komuttan sonra INT 1tek adım hata ayıklama
9IF · InterruptkontrolINTR kesmeleri kabul edilirSTI → 1, CLI → 0; NMI'yi etkilemez
10DF · Directionkontroldizgi komutları geriye doğru0: SI/DI artar, 1: azalır; CLD / STD
11OF · Overflowdurumişaretli taşma: sonuç işaretli aralığa sığmadı100 + 50 → AL = 96h (−106), OF = 1

Bayrak Yazmacı

CF mi, OF mi?

İşlemci toplamayı yalnızca bitler üzerinde yapar; yorum programcınındır. CF işaretsiz, OF işaretli yorumda sonucun doğru olup olmadığını söyler.

AL + işlenenişaretsiz yorumişaretli yorumALCFOF
FFh + 01h255 + 1 = 256-1 + 1 = 000h10
64h + 32h100 + 50 = 150100 + 50 = 15096h01
C8h + 64h200 + 100 = 300-56 + 100 = 442Ch10
80h + 80h128 + 128 = 256-128 + -128 = -25600h11
05h + 0Ah5 + 10 = 155 + 10 = 150Fh00
OF kuralı: aynı işaretli iki sayının toplamı farklı işaretli çıkarsa OF = 1. Farklı işaretli iki sayı toplanınca OF hiçbir zaman 1 olmaz.

Bayrak Yazmacı · Kodu adım adım çalıştır

Kod İzleme: CF, OF ve Diğer Bayraklar

AL17060514131201009Chişaretsiz: 156işaretli: -100CF0OF0SF0ZF0AF0PF0

AL = 9Ch: işaretsiz 156, işaretli −100. Bayraklar başlangıçta 0; MOV onları değiştirmez.

AL07060504131201000Chişaretsiz: 12işaretli: 12CF1OF0SF0ZF0AF0PF1

156 + 112 = 268 > 255 → AL = 0Ch, CF = 1. İşaretli −100 + 112 = 12 doğru → OF = 0. 0Ch'de iki tane 1 → PF = 1.

AL071605140302010050hişaretsiz: 80işaretli: 80CF1OF0SF0ZF0AF0PF1

AL = 50h (80). Bayraklar önceki ADD'den kalır.

AL1706150403020100A0hişaretsiz: 160işaretli: -96CF0OF1SF1ZF0AF0PF1

80 + 80 = 160 işaretsizde doğru (CF = 0), ama iki pozitifin toplamı negatif çıktı (A0h = −96) → OF = 1, SF = 1.

AL071605040302010040hişaretsiz: 64işaretli: 64CF1OF1SF0ZF0AF0PF0

A0h + A0h: işaretsiz 320 (CF = 1), işaretli −96 + (−96) = −192 (OF = 1). AL = 40h: iki yorum da yanlış.

AL1716151413121110FFhişaretsiz: 255işaretli: -1CF1OF1SF0ZF0AF0PF0

AL = FFh. CF = 1 hâlâ duruyor.

AL070605040302010000hişaretsiz: 0işaretli: 0CF1OF0SF0ZF1AF1PF1

INC AL: FFh + 1 = 00h → ZF = 1, AF = 1; ama INC CF'ye dokunmaz: CF = 1 önceki toplamadan kaldı.

AL070605040302010000hişaretsiz: 0işaretli: 0CF0OF0SF0ZF1AF1PF1

CMC CF'yi tersler: CF = 0. Diğer bayraklar değişmez.

MOV  AL, 9Ch     ; 156 ya da -100
ADD  AL, 70h     ; + 112
MOV  AL, 50h     ; 80
ADD  AL, 50h     ; + 80
ADD  AL, AL      ; A0h + A0h
MOV  AL, 0FFh
INC  AL          ; CF'ye dokunmaz
CMC              ; CF tersine
RET

Bayrak Yazmacı

ADD ile Bayraklar Adım Adım

A = 64h0716150403120100B = 32h00110010

MOV AL, 64h (100) ve ADD AL, 32h (50). Bitler sağdan sola toplanır.

A = 64h0716150403120100B = 32h00110010AL = 96h10010110

Sonuç 96h = 1001 0110b. İşaretsiz yorumla 150 (doğru), işaretli yorumla −106 (yanlış!).

A = 64h0716150403120100B = 32h00110010AL = 96h10010110bit 7'den dışarı elde: 0→ CF = 0

CF: en soldaki bitten dışarı elde çıktı mı? Hayır → CF = 0 (150 ≤ 255).

A = 64h0716150403120100B = 32h00110010AL = 96h10010110bit 7'ye giren elde 1, çıkan 0→ OF = 1

OF: iki pozitif sayının toplamı negatif çıktı (bit 7'ye giren ve çıkan elde farklı) → OF = 1.

A = 64h0716150403120100B = 32h00110010AL = 96h10010110MSB = 1 → SF = 1sonuç ≠ 0 → ZF = 0

SF = sonucun bit 7'si = 1. Sonuç sıfır değil: ZF = 0.

A = 64h0716150403120100B = 32h00110010AL = 96h10010110dört tane 1 (çift) → PF = 14 + 2 nibble: elde yok → AF = 0

PF: 1001 0110b'de dört tane 1 → çift → PF = 1. AF: düşük nibble'lar 4 + 2 = 6, elde yok → AF = 0.

Sonuç: AL = 96h; CF = 0, ZF = 0, SF = 1, OF = 1, PF = 1, AF = 0.

Bayrak Yazmacı

Demo: Bayrak Hesaplayıcı

İki değer ve bir komut seçilince sonuç ve bayraklar hesaplanır. Değerler onluk (-5), onaltılık (3Fh) veya ikili (1010b) yazılabilir.

Komut Grupları

Komutlar Üç Gruba Ayrılır

1. grup · iki işlenenli

ADD, SUB, CMP, AND, TEST, OR, XOR

hedef, kaynak

2. grup · çarpma ve bölme

MUL, IMUL, DIV, IDIV

tek işlenen + örtük AL / AX / DX

3. grup · tek işlenenli

INC, DEC, NOT, NEG

işlenen hem kaynak hem hedef

Artırma (INC) ve azaltma (DEC) üçüncü gruptadır. Gruplar, işlenen biçimine göre ayrılır.
hedef ← hedef ∘ kaynakADD AX, BXAX ← AL × işlenenMUL BLişlenen ← f(işlenen)INC CX

Komut Grupları

Komutların Anlamı

1. grupNe yapar?
ADDiki değeri toplar, sonucu hedefe yazar
SUBkaynağı hedeften çıkarır, sonucu hedefe yazar
CMPçıkarır ama sonucu saklamaz; yalnız bayraklar
ANDbit düzeyinde VE
TESTbit düzeyinde VE; sonucu saklamaz
ORbit düzeyinde VEYA
XORbit düzeyinde dışlayan VEYA
2. grupNe yapar?
MULişaretsiz çarpma
IMULişaretli çarpma
DIVişaretsiz bölme (bölüm + kalan)
IDIVişaretli bölme
3. grupNe yapar?
INC1 artırır
DEC1 azaltır
NOTtüm bitleri tersler
NEGişaretini değiştirir (ikiye tümleyen)

Grup 1: İki İşlenenli

ADD, SUB, CMP, AND, TEST, OR, XOR: İşlenenler

BiçimÖrnek
REG, memoryADD AX, [BX]
memory, REGSUB var1, CL
REG, REGXOR AX, AX
memory, immediateAND byte ptr [SI], 0Fh
REG, immediateCMP AL, 'A'
  • REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
  • memory: [BX], [BX+SI+7], değişken …
  • immediate: 5, -24, 3Fh, 10001101b …
Geçersiz: ADD [BX], [SI] (iki bellek), ADD AL, BX (boyut farkı), ADD 5, AL (hedef sabit), ADD DS, AX (kesim yazmacı).

Grup 1: İki İşlenenli

Kurallar ve Etkilenen Bayraklar

  • İki işlenenli işlemlerden sonra sonuç her zaman ilk işlenende (hedef) saklanır.
  • CMP ve TEST yalnızca bayrakları etkiler, sonuç saklamaz.
  • ADD/SUB: ikinci işleneni birinciye ekler / birinciden çıkarır.
  • CMP: ikinci işleneni birinciden çıkarır, sonucu saklamaz.
  • AND/OR/XOR: iki işlenenin karşılıklı bitleri arasında işlem yapar; TEST, AND gibidir ama yalnız bayrakları etkiler.
KomutCFZFSFOFPFAF
ADD, SUB, CMP✓✓✓✓✓✓
AND, OR, XOR, TEST0✓✓0✓?

✓: sonuca göre ayarlanır · 0: her zaman temizlenir · ?: tanımsız. Mantıksal komutlar CF ve OF'yi daima 0 yapar.

Grup 1: İki İşlenenli · Kodu adım adım çalıştır

Kod İzleme: ADD, SUB, CMP

AL = F0h. MOV bayrakları değiştirmez (başlangıçta hepsi 0).

F0h + 20h = 110h; 8 bite 10h sığar, dışarı taşan 1 → CF = 1. İşaretli: −16 + 32 = 16 doğru → OF = 0.

BL = 7. Bayraklar önceki ADD'den kalır.

7 − 9 = −2 = FEh. Ödünç alındı → CF = 1; MSB = 1 → SF = 1. 7 − 9'da düşük nibble ödünç → AF = 1.

CMP AL, 10h: 10h − 10h = 0 → ZF = 1. AL değişmedi: eşitlik böyle sınanır.

FEh − 0: ZF = 0, SF = 1, CF = 0. İşaretsiz FEh > 0, işaretli −2 < 0.

FEh + 2 = 100h → BL = 00h, CF = 1, ZF = 1. İşaretli: −2 + 2 = 0 doğru → OF = 0.

mov al, 0F0h     ; 240
add al, 20h      ; 240 + 32 = 272
mov bl, 7
sub bl, 9        ; 7 - 9
cmp al, 10h      ; AL - 10h
cmp bl, 0
add bl, 2        ; FEh + 2

Grup 1: İki İşlenenli · Kodu adım adım çalıştır

ADC ile 32 Bitlik Toplama

32 bitlik ilk sayı DX:AX'e yüklenir: düşük sözcük FFFFh…

…yüksek sözcük 0001h → DX:AX = 0001FFFFh (131071).

İkinci sayı CX:BX = 00020001h (131073).

FFFFh + 0001h = 10000h → AX = 0000h, CF = 1: yüksek sözcüğe taşınacak elde.

ADC = ADD + CF: 0001h + 0002h + 1 = 0004h. Sonuç DX:AX = 00040000h (262144) ✓

; DX:AX = 0001FFFFh, CX:BX = 00020001h
mov ax, 0FFFFh
mov dx, 0001h
mov bx, 0001h
mov cx, 0002h
add ax, bx      ; düşük sözcükler
adc dx, cx      ; yüksek + CF

SBB (subtract with borrow) aynı fikirle çok sözcüklü çıkarma yapar: önce SUB, sonra SBB.

Grup 1: İki İşlenenli · Kodu adım adım çalıştır

SBB ile 32 Bitlik Çıkarma

Birinci sayı DX:AX = 00040000h (262144): yüksek sözcük DX, düşük sözcük AX.

Çıkarılan CX:BX = 00010001h (65537).

0000h − 0001h: düşük sözcük yetmez, ödünç alınır → AX = FFFFh, CF = 1.

SBB = SUB − CF: 0004h − 0001h − 1 = 0002h. Sonuç DX:AX = 0002FFFFh (196607) ✓

; DX:AX = 00040000h, CX:BX = 00010001h
mov ax, 0000h
mov dx, 0004h
mov bx, 0001h
mov cx, 0001h
sub ax, bx      ; düşük sözcükler
sbb dx, cx      ; yüksek - CF

Kural: en düşük sözcükte SUB, sonraki her sözcükte SBB. Aradaki komutlar CF'yi bozmamalıdır (MOV, INC, LOOP CF'yi korur).

Mantıksal İşlemler

Mantıksal İşlem Kuralları

AND (VE)
ABA AND B
111
100
010
000

İkisi de 1 ise 1.

OR (VEYA)
ABA OR B
111
101
011
000

En az biri 1 ise 1.

XOR (dışlayan)
ABA XOR B
110
101
011
000

Farklı ise 1.

NOT (değil)
ANOT A
10
01

Tersler. Tek işlenenli.

Bu kurallar 8 ya da 16 bitin her birine ayrı ayrı uygulanır: AND AL, BL aslında 8 tane bağımsız VE işlemidir.

Mantıksal İşlemler

Maskeleme: AND, OR, XOR, TEST

AL='a' 61h0716150403020110maske DFh11011111ANDAL='A' 41h01000001

AND ile bit temizleme: maskede 0 olan bit 5 sıfırlanır, diğerleri korunur → küçük harf büyük olur.

AL='A' 41h0716050403020110maske 20h00100000ORAL='a' 61h01100001

OR ile bit kurma: maskede 1 olan bit 5 kesin 1 olur → büyük harf küçük olur.

AL='a' 61h0716150403020110maske 20h00100000XORAL='A' 41h01000001

XOR ile bit tersleme: maskede 1 olan bit değişir → harfin büyük/küçük hâli yer değiştirir.

BL='7' 37h0706151403121110maske 01h00000001TEST(saklanmaz)00000001

TEST ile bit sınama: sonuç 01h ≠ 0 → ZF = 0, yani bit 0 = 1, sayı tek. BL değişmez.

Mantıksal İşlemler

Sık Kullanılan Kalıplar

KodEtkiNeden?
XOR AX, AXAX = 0, ZF = 1, CF = 0MOV AX, 0'dan kısa (2 bayt); bayrakları da temizler
AND AL, 0Fh'7' (37h) → 7ASCII rakamı sayıya çevirir (yüksek nibble silinir)
OR AL, 30h7 → '7' (37h)sayıyı ASCII rakama çevirir
AND AL, 0DFh'a' → 'A'bit 5'i temizler: büyük harf
OR AL, 20h'A' → 'a'bit 5'i kurar: küçük harf
TEST AL, 1ZF = 0 ise tekAL değişmeden bit 0 sınanır
TEST AL, 80hZF = 0 ise negatifişaret biti sınanır
OR AX, AXAX değişmezZF/SF ayarlanır: AX sıfır mı, negatif mi?

Mantıksal İşlemler · Kodu adım adım çalıştır

Kod İzleme: AND, OR, XOR, TEST

AL = 'a' = 61h = 0110 0001b.

61h AND DFh = 41h = 'A'. 41h'de iki tane 1 → PF = 1. CF = OF = 0.

41h OR 20h = 61h = 'a'. Üç tane 1 → PF = 0.

61h XOR 20h = 41h = 'A' (bit 5 terslendi).

BL = '7' = 37h (ASCII rakam).

37h AND 0Fh = 07h: artık sayısal 7.

07h AND 01h = 01h ≠ 0 → ZF = 0: sayı tek. BL aynı kaldı.

Kendisiyle XOR → 00h, ZF = 1, PF = 1 (sıfır tane 1, çift).

mov al, 'a'      ; 61h
and al, 0DFh     ; büyük harf
or  al, 20h      ; küçük harf
xor al, 20h      ; tersle
mov bl, '7'      ; 37h
and bl, 0Fh      ; sayı 7
test bl, 1       ; tek mi?
xor bl, bl       ; BL = 0

Grup 2: Çarpma ve Bölme

MUL ve IMUL

bayt işlenen (8 bit)AL×işlenenAX (16 bit)MUL / IMULsözcük işlenen (16 bit)AX×işlenenDXAX32 bitlik sonuç DX:AX (DX yüksek)
Komutİşlenen bayt iseİşlenen sözcük ise
MUL (işaretsiz)AX = AL × işlenen(DX AX) = AX × işlenen
IMUL (işaretli)AX = AL × işlenen(DX AX) = AX × işlenen

İşlenen: REG veya memory (MUL BL, IMUL word ptr [SI]). 8086'da sabit işlenen yoktur: MUL 5 geçersizdir.

Grup 2: Çarpma ve Bölme

DIV ve IDIV

Komutİşlenen bayt iseİşlenen sözcük ise
DIV (işaretsiz)AL = AX / işlenen
AH = kalan (modulus)
AX = (DX AX) / işlenen
DX = kalan (modulus)
IDIV (işaretli)AL = AX / işlenen
AH = kalan
AX = (DX AX) / işlenen
DX = kalan
DXAXbölünen (32 bit)÷işlenenbölen (16 bit)AXbölümDXkalanbayt bölmede:AX ÷ işlenen → AL, AH
Bayraklar

MUL / IMUL yalnızca CF ve OF'yi anlamlı ayarlar: sonuç işlenen boyutunu aşarsa (üst yarı gerekliyse) CF = OF = 1. Diğerleri tanımsız.

DIV / IDIV sonrası tüm bayraklar tanımsızdır.

Bölme hatası

Bölen 0 ise ya da bölüm hedefe (AL / AX) sığmıyorsa işlemci INT 0 üretir (bölme hatası).

IDIV bölümü sıfıra doğru keser; kalan bölünenle aynı işaretlidir.

Grup 2: Çarpma ve Bölme

Çarpma ve Bölme Adım Adım

ALC8hBL03h

MOV AL, 200, MOV BL, 3. 200 = C8h, işaretli yorumda −56.

AX0258hCF1OF1

MUL BL: 200 × 3 = 600 = 0258h → AX. Sonuç AL'ye sığmadı (AH ≠ 0) → CF = OF = 1.

AXFF58hCF1OF1

Aynı bitlerle IMUL BL: −56 × 3 = −168 = FF58h. Farklı sonuç! −168 bayta sığmaz → CF = OF = 1.

AXFFF6hCF0OF0

AL = FEh (−2), BL = 5: IMUL BL → −10 = FFF6h. AH yalnızca AL'nin işaret uzantısı → CF = OF = 0: sonuç AL'ye sığdı.

AX0017hBL05hAL04hAH03h

DIV BL: AX = 23, BL = 5 → bölüm AL = 4, kalan AH = 3. Yeni AX = 0304h.

AXFFE9hBL05hALFChAHFDh

IDIV BL: −23 / 5 → bölüm AL = FCh (−4), kalan AH = FDh (−3). Kontrol: −4 × 5 + (−3) = −23.

AX1000hBL02hAL?

AX = 1000h (4096), DIV BL (2): bölüm 2048 AL'ye sığmaz → bölme hatası, INT 0. Sözcük bölme (DX:AX / BX) gerekirdi.

DXFFFFhAXFFFFhBX0001hAX?

DX:AX = FFFFFFFFh, DIV BX (BX = 1): bölen sıfır değil, ama bölüm FFFFFFFFh AX'e sığmaz → yine INT 0. Kural: sözcük bölmede DX ≥ bölen ise bölüm sığmaz (bayt bölmede AH ≥ bölen).

Grup 2: Çarpma ve Bölme

Bölmeye Hazırlık: CBW, CWD

  • Bölme, işlenenin iki katı genişlikte bir bölünen ister: bayt bölmede AX, sözcük bölmede DX:AX.
  • İşaretsiz bölmeden önce üst yarı sıfırlanır: MOV AH, 0 veya XOR DX, DX.
  • İşaretli bölmeden önce işaret genişletilir: CBW (AL → AX), CWD (AX → DX:AX).
  • DX'i unutmak klasik hatadır: DX'te kalan eski değer bölüneni büyütür ve bölme hatasına yol açabilir.
AL11111001F9h = -7CBW: bit 7 AH'ye kopyalanırAX1111111111111001FFF9h = -7
; işaretsiz: 1000 / 7
mov ax, 1000
xor dx, dx      ; DX:AX = 1000
mov bx, 7
div bx          ; AX = 142, DX = 6

; işaretli: -1000 / 7
mov ax, -1000
cwd             ; DX = FFFFh
idiv bx         ; AX = -142, DX = -6

Grup 2: Çarpma ve Bölme · Kodu adım adım çalıştır

Kod İzleme: DIV, CWD ve IDIV

DX0000hAX07D0hBX0000hDX:AX = 000007D0hişaretsiz 2000 · işaretli 2000

AX = 2000 = 07D0h. Sözcük bölmede bölünen DX:AX'tir; DX'te ne olduğu da önemlidir.

DX0000hAX07D0hBX0000hDX:AX = 000007D0hişaretsiz 2000 · işaretli 2000

XOR DX, DX: işaretsiz bölme için üst yarı sıfır → DX:AX = 2000.

DX0000hAX07D0hBX0009hDX:AX = 000007D0hişaretsiz 2000 · işaretli 2000

Bölen BX = 9.

DX0002hAX00DEhBX0009hDX:AX = 000200DEhişaretsiz 131294 · işaretli 131294bölüm AX = 222, kalan DX = 2

DIV BX: 2000 / 9 → AX = 222 (00DEh), DX = 2. Bayraklar tanımsız.

DX0002hAXF830hBX0009hDX:AX = 0002F830hişaretsiz 194608 · işaretli 194608

AX = −2000 = F830h. DX'te önceki kalan (2) duruyor: DX:AX şimdi yanlış bir bölünen.

DXFFFFhAXF830hBX0009hDX:AX = FFFFF830hişaretsiz 4294965296 · işaretli -2000

CWD: AX'in işaret biti 1 → DX = FFFFh. DX:AX = FFFFF830h, 32 bitte −2000.

DXFFFEhAXFF22hBX0009hDX:AX = FFFEFF22hişaretsiz 4294901538 · işaretli -65758bölüm AX = -222, kalan DX = -2

IDIV BX: −2000 / 9 → AX = FF22h (−222), DX = FFFEh (−2). Kalan bölünenle aynı işaretli.

DXFFFEhAX07D0hBX0009hDX:AX = FFFE07D0hişaretsiz 4294838224 · işaretli -129072

AX = 2000, ama DX = FFFEh temizlenmedi: DX:AX = FFFE07D0h, yaklaşık 4,29 milyar.

DXFFFEhAX07D0hBX0009hDX:AX = FFFE07D0hişaretsiz 4294838224 · işaretli -129072bölüm AX'e sığmıyor → INT 0

DIV BX: bölüm 16 bite sığmaz (DX ≥ bölen) → işlemci INT 0 üretir, program durur. Çözüm: bölmeden önce XOR DX, DX.

MOV  AX, 2000
XOR  DX, DX      ; DX:AX = 2000
MOV  BX, 9
DIV  BX          ; işaretsiz bölme
MOV  AX, -2000
CWD              ; işaret genişlet
IDIV BX          ; işaretli bölme
MOV  AX, 2000    ; DX temizlenmedi!
DIV  BX
RET

İşaretli Sayılar · Kodu adım adım çalıştır

İşaretli Taşma: JO ve CBW

AL = BL = A4h: −92 (256 − 92 = 164 = A4h).

A4h + A4h = 148h → AL = 48h = +72. İki negatifin toplamı pozitif çıktı → OF = 1 (CF = 1 de oldu ama işaretli yorumda önemsiz).

JO OF = 1 olduğu için genislet etiketine atlar. Doğru sonuç −184, −128 … 127 aralığında değil.

AL = A4h, CBW: MSB = 1 → AH = FFh, AX = FFA4h (16 bitte −92).

Birinci sayı DX'e saklanır; ikinci sayı (BL) da AL'ye alınıp genişletilir: AX = FFA4h.

FFA4h + FFA4h = 1FF48h → AX = FF48h = −184 ✓. Sonuç 16 bite sığdı: OF = 0.

mov al, -92      ; A4h
mov bl, -92
add al, bl       ; 8 bit toplama
jo  genislet     ; OF = 1 ise
jmp bitti
genislet:
mov al, -92      ; birinci sayı
cbw              ; AL -> AX
mov dx, ax
mov al, bl       ; ikinci sayı
cbw
add ax, dx       ; 16 bit toplama
bitti:
ret

JO (jump if overflow) OF = 1 ise, JNO OF = 0 ise atlar. İşaretli bayt toplamı taşabiliyorsa işlenenler önce CBW ile sözcüğe genişletilir.

İşaretli Sayılar · Kodu adım adım çalıştır

CBW ile İşaretli Bayt Toplamı

SI dizinin başını gösterir, CX = 4 eleman, BX = 0 (toplam sıfırlandı).

AL = 64h (+100). MSB = 0 → CBW AH = 00h, AX = 0064h.

BX = BX + AX = 0064h (100).

AL = E2h (−30). MSB = 1 → CBW AH = FFh, AX = FFE2h.

BX = BX + AX = 0046h (70).

AL = 5Ah (+90). MSB = 0 → CBW AH = 00h, AX = 005Ah.

BX = 00A0h (160). Bayt toplasaydık 70 + 90 = 160 > 127 → AL = A0h (−96), OF = 1 olurdu.

AL = F9h (−7). MSB = 1 → CBW AH = FFh, AX = FFF9h.

BX = BX + AX = 0099h (153).

Döngü bitti, toplam = 0099h = 153 ✓ belleğe yazılır. CBW yerine MOV AH, 0 kullanılsaydı −30 = E2h, 226 olarak eklenirdi.

org 100h
jmp basla
dizi db 100, -30, 90, -7
toplam dw 0
basla:
lea si, dizi
mov cx, 4
xor bx, bx      ; BX = 16 bit toplam
dongu:
mov al, [si]
cbw             ; AL -> AX (işaretle)
add bx, ax
inc si
loop dongu
mov toplam, bx  ; 153 = 0099h
ret

İşaretli Sayılar · Kodu adım adım çalıştır

CWD ve ADC ile 32 Bitlik Toplam

SI = dizi, CX = 3 sözcük. Toplam (32 bit) bellekte 0000:0000.

AX = 7530h (30000). Pozitif → CWD DX = 0000h.

Düşük sözcük: 0000h + 7530h = 7530h, CF = 0.

Yüksek sözcük: 0000h + 0000h + CF(0) = 0000h. Toplam 00007530h.

AX = 61A8h (25000), DX = 0000h.

7530h + 61A8h = D6D8h (55000). 16 bit işaretli yorumda negatif (OF = 1) ama toplam 32 bit tutulduğu için sorun yok.

Yüksek sözcük 0000h kalır: toplam 0000D6D8h = 55000.

AX = F060h (−4000). MSB = 1 → CWD DX = FFFFh: DX:AX = FFFFF060h (32 bitte −4000).

D6D8h + F060h = 1C738h → düşük sözcük C738h, CF = 1.

FFFFh + 0000h + CF(1) = 10000h → yüksek sözcük 0000h. Toplam 0000C738h = 51000 ✓

org 100h
jmp basla
dizi dw 30000, 25000, -4000
toplam dw 0, 0       ; 32 bit toplam
basla:
lea si, dizi
mov cx, 3
dongu:
mov ax, [si]
cwd                  ; AX -> DX:AX
add [toplam], ax     ; düşük sözcük
adc [toplam+2], dx   ; yüksek + CF
add si, 2
loop dongu
ret

İşaretli sözcük dizisi: her eleman CWD ile 32 bite genişletilir, düşük sözcük ADD, yüksek sözcük ADC ile toplanır.

Grup 2: Çarpma ve Bölme

Demo: Çarpma / Bölme Hesaplayıcı

Komut, boyut ve değerler seçilince sonucun hangi yazmaçlara yazıldığı gösterilir. Bölmede bölünen, bayt için AX; sözcük için DX:AX'tir.

Grup 2: Çarpma ve Bölme · Adım adım

32 × 32 Bit Çarpma: Kısmi Çarpımlar

8086 en çok 16 × 16 bit çarpar. 32 bitlik sayılar sözcüklere bölünür: A × B = A1·B1·232 + (A1·B0 + A0·B1)·216 + A0·B0. Dört MUL, sonuçlar sözcük konumuna göre ADD/ADC ile toplanır; sonuç 64 bittir.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)

A = 9ABCDEF0h ve B = EDCBFEDCh, 16 bitlik yarılara ayrılır: A = A1:A0, B = B1:B0.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)A0 × B01. MULDDF1B640

A0 × B0 kaydırılmaz: sonucun en düşük iki sözcüğüne (z1:z0) düşer.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)A0 × B01. MULDDF1B640A1 × B02. MUL · 16 bit kayık9A0B8190A0 × B13. MUL · 16 bit kayıkCF14F850

A1 × B0 ve A0 × B1 ikisi de 216 ile çarpılmıştır: z2:z1 sütunlarına yazılır.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)A0 × B01. MULDDF1B640A1 × B02. MUL · 16 bit kayık9A0B8190A0 × B13. MUL · 16 bit kayıkCF14F850A1 × B14. MUL · 32 bit kayık8FBABF14

A1 × B1 232 ile çarpılmıştır: z3:z2 sütunlarına yazılır.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)A0 × B01. MULDDF1B640A1 × B02. MUL · 16 bit kayık9A0B8190A0 × B13. MUL · 16 bit kayıkCF14F850A1 × B14. MUL · 32 bit kayık8FBABF14+2 elde+2 eldesütun eldeleri

Sütun toplamları: z1 = 257D1h → yaz 57D1h, 2 elde; z2 = 22835h → yaz 2835h, 2 elde. Her ADD en çok 1 elde verir: kodda ADC zinciri bu yüzden var.

z3 · bit 48–63z2 · bit 32–47z1 · bit 16–31z0 · bit 0–15A =9ABC (A1)DEF0 (A0)× B =EDCB (B1)FEDC (B0)A0 × B01. MULDDF1B640A1 × B02. MUL · 16 bit kayık9A0B8190A0 × B13. MUL · 16 bit kayıkCF14F850A1 × B14. MUL · 32 bit kayık8FBABF14+2 elde+2 eldesütun eldeleriA × B =8FBC283557D1B640

Sonuç: 8FBC 2835 57D1 B640h. Kontrol (onluk): 2596069104 × 3989569244 = 10357197452617037376 ✓

Grup 2: Çarpma ve Bölme · Kodu adım adım çalıştır

32 × 32 Bit Çarpma: Kod İzleme

AX = A0 = DEF0h, MUL [y]: A0 × B0 = DEF0h × FEDCh = DDF1:B640h (DX:AX). DX ≠ 0 olduğundan MUL CF = 1 yapar.

İlk kısmi çarpım z0 (bit 0–15) ve z1 (bit 16–31) sözcüklerine yazılır.

A1 × B0 = 9ABCh × FEDCh = 9A0B:8190h. 16 bit sola kaymış: z1 ve z2'ye eklenecek.

z1 + AX = DDF1h + 8190h → z1 = 5F81h, CF = 1.

z2 = 0 + DX + CF = 9A0Ch. z2 önceden 0 olduğu için burada yeni elde oluşmaz.

A0 × B1 = DEF0h × EDCBh = CF14:F850h. Bu da z1–z2 konumuna eklenir.

z1 = 5F81h + F850h → 57D1h, CF = 1.

z2 = 9A0Ch + CF14h + CF → 6921h, CF = 1: elde z3'e gitmeli!

ADC [z+6], 0: yalnızca eldeyi taşır → z3 = 0001h.

A1 × B1 = 9ABCh × EDCBh = 8FBA:BF14h, 32 bit sola kaymış: z2–z3.

z2 = 6921h + BF14h → 2835h, CF = 1.

z3 = 0001h + 8FBAh + CF = 8FBCh. Sonuç z3:z2:z1:z0 = 8FBC 2835 57D1 B640h ✓

org 100h
mov ax, [x]       ; A0
mul [y]           ; A0*B0
mov [z], ax
mov [z+2], dx
mov ax, [x+2]     ; A1
mul [y]           ; A1*B0
add [z+2], ax
adc [z+4], dx
mov ax, [x]       ; A0
mul [y+2]         ; A0*B1
add [z+2], ax
adc [z+4], dx
adc [z+6], 0
mov ax, [x+2]     ; A1
mul [y+2]         ; A1*B1
add [z+4], ax
adc [z+6], dx
ret
x dw 0DEF0h, 9ABCh  ; A = 9ABCDEF0h
y dw 0FEDCh, 0EDCBh ; B = EDCBFEDCh
z dw 4 dup(0)       ; 64 bit sonuç

Grup 3: Tek İşlenenli

INC, DEC, NOT, NEG

  • İşlenenler: REG (AX, BX, … SP) veya memory ([BX], [BX+SI+7], değişken). Sabit olamaz.
  • INC ve DEC yalnızca ZF, SF, OF, PF, AF'yi etkiler; CF'ye dokunmaz.
  • NOT hiçbir bayrağı etkilemez! İşlenenin her bitini ters çevirir (birler tümleyeni).
  • NEG CF, ZF, SF, OF, PF, AF'yi etkiler. İşleneni negatif yapar (ikiye tümleyen): her biti tersler, ardından 1 ekler. Ör. 5 → −5, −2 → 2.
KomutCFZFSFOFPFAF
INC, DEC—✓✓✓✓✓
NOT——————
NEG✓ (işlenen ≠ 0 ise 1)✓✓✓✓✓

—: değişmez. INC/DEC'in CF'yi korması, döngü içinde ADC ile çok baytlı toplama yaparken sayaç artırmayı mümkün kılar.

Grup 3: Tek İşlenenli

NEG: İkiye Tümleyen Adım Adım

x = 05h0706050403120110

x = 5 = 0000 0101b.

x = 05h0706050403120110NOT x11111010FAh

NOT: her bit terslenir → 1111 1010b = FAh (−6). Birler tümleyeni.

x = 05h0706050403120110NOT x11111010FAh+ 1 → NEG11111011FBh

+1: FBh = 1111 1011b = −5. NEG bu iki adımı tek komutta yapar; CF = 1 (x ≠ 0).

x = FEh1716151413121100NOT x0000000101h+ 1 → NEG0000001002h

x = FEh (−2): NOT → 01h, +1 → 02h. Negatifin negatifi pozitiftir.

x = 80h1706050403020100NOT x011111117Fh+ 1 → NEG1000000080h

Özel durum: x = 80h (−128). NOT → 7Fh, +1 → 80h: +128 bayta sığmaz → OF = 1.

x = 00h0706050403020100NOT x11111111FFh+ 1 → NEG0000000000h

x = 0: sonuç 0, CF = 0 (NEG'de CF = 1 olmayan tek durum), ZF = 1.

Grup 3: Tek İşlenenli · Kodu adım adım çalıştır

Kod İzleme: INC, DEC, NOT, NEG

AL = FFh (255 / −1).

FFh + 1 = 00h, ZF = 1. ADD olsaydı CF = 1 olurdu; INC CF'yi değiştirmez → CF = 0 kaldı.

00h − 1 = FFh, SF = 1. Ödünç olsa da CF yine değişmedi.

BL = 7Fh = +127, en büyük pozitif bayt.

7Fh + 1 = 80h = −128: işaretli taşma → OF = 1, SF = 1.

NOT: 80h → 7Fh. Bayraklar hiç değişmedi (SF hâlâ 1 görünüyor).

NEG: −127 = 81h. CF = 1 (işlenen ≠ 0), SF = 1, OF = 0.

mov al, 0FFh
inc al          ; FFh + 1
dec al          ; 00h - 1
mov bl, 7Fh     ; +127
inc bl          ; +128 ?
not bl
neg bl

Kaydırma ve Döndürme

Kaydırma: SHL/SAL, SHR, SAR

b7b6b5b4b3b2b1b0CF0
SHL/SAL: sola kaydır, sağdan 0 girer, çıkan bit CF'ye. Her adım × 2.
b7b6b5b4b3b2b1b0CF0
SHR: mantıksal sağa kaydır, soldan 0 girer. İşaretsiz ÷ 2.
b7b6b5b4b3b2b1b0CFişaret biti korunur
SAR: aritmetik sağa kaydır, işaret biti korunur. İşaretli ÷ 2 (−∞'a yuvarlar).
Kaydırma sayısı8086'da yalnızca 1 ya da CL: shl ax, 1, shr al, cl. shl al, 4 gibi anlık sayı 80186 ve sonrasında geçerlidir. OF yalnızca sayı 1 iken tanımlıdır.
SAR ile IDIV farklı yuvarlar: −7 (F9h) sar 1 → FCh = −4; idiv 2 → −3.

Kaydırma ve Döndürme

Döndürme: ROL, ROR, RCL, RCR

b7b6b5b4b3b2b1b0CF
ROL: sola döndür; b7 hem b0'a hem CF'ye gider.
b7b6b5b4b3b2b1b0CF
ROR: sağa döndür; b0 hem b7'ye hem CF'ye gider.
b7b6b5b4b3b2b1b0CF
RCL: CF üzerinden sola döndür (9 bitlik halka).
b7b6b5b4b3b2b1b0CF
RCR: CF üzerinden sağa döndür.
Döndürmede bit kaybolmaz. Yalnızca CF ve (sayı 1 iken) OF değişir; SF, ZF, PF etkilenmez. RCL/RCR çok sözcüklü kaydırmalarda kullanılır: shl ax, 1 + rcl dx, 1 → DX:AX × 2.

Kaydırma ve Döndürme

Kaydırma ve Döndürme Gezgini

Her düğme komutu op al, 1 olarak uygular. SHL art arda seçilince sayı her adımda iki katına çıkar; SAR işaret bitini korur.

Kaydırma ve Döndürme · Kodu adım adım çalıştır

Kod İzleme: Kaydırarak Çarpma (13 × 5)

Çarpılan BL = 13 = 0Dh (0000 1101b).

Çarpan DL = 5 = 0101b: kâğıt üzerindeki çarpmada olduğu gibi bitler tek tek incelenir.

4 bitlik çarpan için 4 tur.

shr dl, 1: çıkan bit 1 → CF = 1.

CF = 1 → atlama yok, toplama yapılacak.

sonuc = 0 + 0Dh = 0Dh (13 × 1).

Çarpılan bir sola: BL = 1Ah (26).

loop: CX = 0003h.

Çıkan bit 0 → CF = 0.

CF = 0 → atla'ya atlar.

BL = 34h (52).

loop: CX = 0002h.

Çıkan bit 1 → CF = 1.

CF = 1 → toplama yapılacak.

sonuc = 0Dh + 34h = 41h = 65 (13 × 4 eklendi).

BL = 68h (104).

loop: CX = 0001h.

Çıkan bit 0 → CF = 0.

CF = 0 → atla.

BL = D0h.

loop: CX = 0000h.

Sonuç: 13 × 5 = 65 = 41h. MUL olmayan işlemcilerde çarpma böyle yapılır.

org 100h
mov bl, carpilan  ; 13
mov dl, carpan    ; 5 = 0101b
mov cx, 4         ; 4 bit
kontrol:
shr dl, 1         ; en sağ bit → CF
jnc atla
add sonuc, bl     ; bit 1 ise ekle
atla:
shl bl, 1         ; çarpılan × 2
loop kontrol
ret
carpilan db 13
carpan   db 5
sonuc    db 0

Kaydırma ve Döndürme

Kaydırmayla Hızlı Çarpma ve Bölme

; AX ← AX × 3 = AX×2 + AX
mov bx, ax     ; sakla
shl ax, 1      ; AX × 2
add ax, bx     ; ×2 + ×1

; işaretsiz ÷ 8 ve kalan
mov dx, ax
and dx, 0007h  ; kalan = alt 3 bit
mov cl, 3
shr ax, cl     ; bölüm

; işaretli ÷ 4
mov cl, 2
sar ax, cl     ; −7 → −2
  • 8086'da mul 70–133, div 80–162 saat turu sürer; bir shl reg, 1 yalnızca 2 tur.
  • 2'nin kuvvetleriyle çarpma/bölme kaydırmaya, diğer sabitler kaydırma + toplamaya dönüştürülebilir.
  • 2n'e bölümden kalan: and ile alt n bit.
  • İşaretli bölmede SAR kullanılır; negatif bölünende SAR −∞'a, IDIV sıfıra doğru yuvarlar: −7 için SAR 2 → −2, IDIV 4 → −1.
Örnek: AX = 25 → BX = 25, AX = 50 → 50 + 25 = 75.

Kaydırma ve Döndürme · Kodu adım adım çalıştır

Kaydırmayla 37 × 10 ve 370 ÷ 16

org 100h
mov ax, 37
shl ax, 1      ; AX × 2
mov bx, ax     ; sakla
shl ax, 1      ; AX × 4
shl ax, 1      ; AX × 8
add ax, bx     ; ×8 + ×2
mov bx, ax
and bx, 000Fh  ; kalan: alt 4 bit
mov cl, 4
shr ax, cl     ; bölüm: ÷ 16
ret
AX = 0025h = 37015000000080701001010BX = 0000h = 00000000000000000

AX = 37 = 0025h = 0000 0000 0010 0101b.

AX = 004Ah = 74015000000080710010100BX = 0000h = 0000000000000000037 → 74

SHL AX, 1: bitler bir sola, sağdan 0 girer → AX = 74 (004Ah). 2 saat turu; MUL 70 turdan fazla sürer.

AX = 004Ah = 74015000000080710010100BX = 004Ah = 740000000001001010

BX = 74: ×2 saklanır.

AX = 0094h = 148015000000081700101000BX = 004Ah = 74000000000100101074 → 148

SHL → AX = 148 (×4).

AX = 0128h = 296015000000180701010000BX = 004Ah = 740000000001001010148 → 296

SHL → AX = 296 (×8).

AX = 0172h = 370015000000180711100100BX = 004Ah = 740000000001001010296 → 370

ADD AX, BX: 296 + 74 = 370 = 0172h = 37 × 10.

AX = 0172h = 370015000000180711100100BX = 0172h = 3700000000101110010

BX = 370: bölme için kopya.

AX = 0172h = 370015000000180711100100BX = 0002h = 20000000000000010

AND BX, 000Fh: alt 4 bit = 370 mod 16 = 2.

AX = 0172h = 370015000000180711100100BX = 0002h = 20000000000000010

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

AX = 0017h = 23015000000080700101110BX = 0002h = 20000000000000010370 → 23

SHR AX, CL: 4 bit sağa = ÷ 16 → AX = 23 (0017h). 23 × 16 + 2 = 370.

AX = 0017h = 23015000000080700101110BX = 0002h = 20000000000000010

RET: program biter.

Örnek: Dizi Toplama

Dizi Elemanları Toplama

org 100h
jmp start
vec1 db 1, 2, 5, 6
vec2 db 3, 5, 6, 1
vec3 db ?, ?, ?, ?
start:
lea si, vec1
lea bx, vec2
lea di, vec3
mov cx, 4
sum:
mov al, [si]
add al, [bx]
mov [di], al
inc si
inc bx
inc di
loop sum
ret
  • vec3[i] = vec1[i] + vec2[i], i = 0…3.
  • JMP start veri tanımlarının üzerinden atlar; aksi hâlde işlemci veri baytlarını komut sanardı.
  • SI, BX, DI üç dizinin işaretçileridir; LEA adresi (bağıl konumu) yükler.
  • [SI]: SI'nin gösterdiği bellek baytı (dolaylı adresleme).
  • LOOP sum: CX'i 1 azaltır, CX ≠ 0 ise sum'a döner → 4 tur.
  • Beklenen sonuç: vec3 = 4, 7, 11, 7.

Örnek: Dizi Toplama · Kodu adım adım çalıştır

Kod İzleme: Dizi Toplama

vec1 (0102h)1256vec2 (0106h)3561vec3 (010Ah)0000

JMP start: veriler (0102h–010Dh) atlanır, 010Eh'ye gidilir.

vec1 (0102h)1256▲SIvec2 (0106h)3561vec3 (010Ah)0000

SI = vec1'in adresi = 0102h.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)0000▲DI

BX = 0106h (vec2), DI = 010Ah (vec3).

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)0000▲DI

CX = 4 tur.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)0000▲DI

Tur 1: AL ← [SI] = [0102h] = 1.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)0000▲DI

AL ← AL + [BX] = 1 + 3 = 4 (04h).

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4000▲DI

[DI] ← AL: vec3[0] = 4.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4000▲DI

Üç işaretçi de bir bayt ilerler (diziler bayt dizisidir; sözcük dizisi olsaydı 2 eklenirdi).

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4000▲DI

LOOP: CX = 3 ≠ 0 → sum'a dön.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4000▲DI

Tur 2: AL ← [SI] = [0103h] = 2.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4000▲DI

AL ← AL + [BX] = 2 + 5 = 7 (07h).

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4700▲DI

[DI] ← AL: vec3[1] = 7.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4700▲DI

Üç işaretçi de bir bayt ilerler (diziler bayt dizisidir; sözcük dizisi olsaydı 2 eklenirdi).

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)4700▲DI

LOOP: CX = 2 ≠ 0 → sum'a dön.

vec1 (0102h)1256▲SIvec2 (0106h)3561▲BXvec3 (010Ah)47110▲DI

Tur 3 (özet): 5 + 6 = 11 → vec3[2]. LOOP: CX = 1 ≠ 0 → sum'a dön.

vec1 (0102h)1256vec2 (0106h)3561▲SIvec3 (010Ah)47117▲BX

Tur 4 (özet): 6 + 1 = 7 → vec3[3]. LOOP: CX = 0 → döngü biter.

vec1 (0102h)1256vec2 (0106h)3561▲SIvec3 (010Ah)47117▲BX

RET: vec3 = 4, 7, 11, 7 (04h 07h 0Bh 07h).

org 100h
jmp start
vec1 db 1, 2, 5, 6
vec2 db 3, 5, 6, 1
vec3 db ?, ?, ?, ?
start:
lea si, vec1
lea bx, vec2
lea di, vec3
mov cx, 4
sum:
mov al, [si]
add al, [bx]
mov [di], al
inc si
inc bx
inc di
loop sum
ret

Örnek: Dizi Toplama

Bellekte Program ve Veri

AdresBaytlarAnlamı
0100EB 0CJMP 010Eh
+0Ch: 0102h + 0Ch
010201 02 05 06vec1
veri
010603 05 06 01vec2
veri
010A04 07 0B 07vec3
çalıştıktan sonra
010EBE 02 01MOV SI, 0102h
LEA → MOV
0111BB 06 01MOV BX, 0106h
0114BF 0A 01MOV DI, 010Ah
AdresBaytlarAnlamı
0117B9 04 00MOV CX, 0004h
little-endian
011A8A 04MOV AL, [SI]
sum:
011C02 07ADD AL, [BX]
011E88 05MOV [DI], AL
012046 / 43 / 47INC SI / BX / DI
1'er bayt
0123E2 F5LOOP 011Ah
F5h = −11
0125C3RET

emu8086 bellek penceresi (CS = DS = 0700h). Kod ve veri aynı kesimdedir; assembler LEA'yı daha kısa olan MOV reg, sabit olarak kodlamıştır.

BCD Aritmetiği

İkili Kodlu Onluk (BCD)

  • BCD (Binary Coded Decimal): her onluk basamak ayrı bir 4 bitlik grupta (0000–1001) tutulur.
  • Paketsiz (unpacked) BCD: bayt başına bir basamak. Paketli (packed): bayt başına iki basamak.
  • İşlemci toplamayı ikili yapar; sonucun BCD'ye düzeltilmesi için özel komutlar vardır.
Gösterim14 sayısıBayt(lar)
İkili0000 1110b0Eh
Paketsiz BCD0000 0001 · 0000 010001h 04h (AH, AL)
Paketli BCD0001 0100b14h
ASCII'1' '4'31h 34h

BCD Aritmetiği

BCD Düzeltme Komutları

KomutNe zaman?Etki
AAApaketsiz toplamadan sonraAL'yi BCD'ye düzelt, elde AH'ye
AASpaketsiz çıkarmadan sonraAL'yi düzelt, ödünç AH'den
AAMpaketsiz çarpmadan sonraAH = AL / 10, AL = AL mod 10
AADpaketsiz bölmeden önceAL = AH × 10 + AL, AH = 0
DAA / DASpaketli toplama / çıkarmadan sonraAL'deki iki basamağı düzelt
Düzeltme komutları yalnızca AL (ve AH) üzerinde çalışır; bu yüzden BCD toplama/çıkarma bayt bayt yapılır. Örnek: 83h − 38h = 4Bh → DAS → 45h (83 − 38 = 45).

BCD Aritmetiği · Kodu adım adım çalıştır

Kod İzleme: AAA ile 9 + 5

AH = 09h: birinci basamak 9.

AL = 05h: ikinci basamak 5. AX = 0905h.

09h + 05h = 0Eh (14): ikili doğru ama BCD değil (E > 9). Nibble eldesi yok → AF = 0.

AH = 0: onlar basamağı temizlendi. AX = 000Eh.

AAA: AL'nin düşük nibble'ı E > 9 → AL + 6 = 14h, AH + 1, AF = CF = 1; AL'nin üst nibble'ı silinir → AX = 0104h → “14”.

Her basamağa 30h eklenir: AX = 3134h = '1','4'.

BL = '4' saklanır, AL = '1'.

AH = 0Eh (teletype).

'1' yazılır.

AL = '4'.

'4' yazılır. Ekranda 14.

RET.

; first number '9':
mov     ah, 09h
; second number '5':
mov     al, 05h
; al = al + ah = 09h + 05h = 0eh
add     al, ah
; clear tens byte of bcd
xor     ah, ah
; adjust result to bcd form, ah = 1, al = 4 -> '14'
aaa
; --- sonucu yazdır (ek) ---
or      ax, 3030h   ; ASCII'ye çevir
mov     bl, al      ; '4' sakla
mov     al, ah      ; '1'
mov     ah, 0Eh
int     10h
mov     al, bl
int     10h
ret

BCD Aritmetiği · Kodu adım adım çalıştır

Kod İzleme: AAS ile 5 − 8

AL = 05h. emu8086 programı AX = 0000h ile başlatır.

BL = 08h.

5 − 8 = −3 = FDh. Ödünç: CF = 1; düşük nibble'da da ödünç: AF = 1.

AAS: AF = 1 → AL − 6 = F7h, AH − 1 = FFh, CF = AF = 1; üst nibble silinir → AX = FF07h.

AL = 37h = '7'.

AH = 0Eh.

'7' yazılır.

Tuş beklenir.

Sonuç “7, ödünç 1”: 15 − 8 = 7 gibi. Gerçek fark −3'tür; CF = 1 sonucun negatif olduğunu, 7'nin −3'ün 10'a tümleyeni olduğunu söyler.

; make 5 - 8, al = 0fdh (not in bcd form)
mov     al, 05h
mov     bl, 08h
sub     al, bl
; convert to bcd, al = 7
; and 1 is borrowed from ah,
; like calculating 15 - 8:
aas
; --- yazdır ---
or      al, 30h
mov     ah, 0Eh
int     10h
mov     ah, 0
int     16h
ret

BCD Aritmetiği

AAM ve AAD

AAM · çarpmadan sonra
mov al, 7
mov bl, 8
mul bl      ; AX = 0038h (56)
aam         ; AH = 05h, AL = 06h

AL'yi 10'a böler: bölüm AH'ye, kalan AL'ye. 56 → “5”, “6”.

AAD · bölmeden önce
mov ax, 0504h  ; '54' paketsiz
aad            ; AX = 0036h (54)
mov bl, 6
div bl         ; AL = 09h, AH = 00h

AL = AH × 10 + AL, AH = 0: iki basamak ikili sayıya çevrilir, sonra normal DIV.

Paketli BCD için DAA: MOV AL,38h / ADD AL,45h → AL = 7Dh, DAA → AL = 83h (38 + 45 = 83).

BCD Aritmetiği · Kodu adım adım çalıştır

Kod İzleme: AAM, AAD ve DAA

AH00hAL06hBL09hAF0CF0AX = 0006h (ikili 6)AL nibble'ları: 0 | 6

İki tek basamaklı sayı: AL = 6, BL = 9.

AH00hAL36hBL09hAF?CF0AX = 0036h (ikili 54)AL nibble'ları: 3 | 6

MUL BL: AX = 6 × 9 = 54 = 0036h. İkili sonuç; ekrana yazmak için basamaklara ayrılmalı.

AH05hAL04hBL09hAF?CF?AX = 0504h (ikili 1284)AL nibble'ları: 0 | 4

AAM: AL / 10 → AH = 5 (bölüm), AL = 4 (kalan). AX = 0504h: paketsiz “54”.

AH07hAL02hBL09hAF?CF?AX = 0702h (ikili 1794)AL nibble'ları: 0 | 2

AX = 0702h: paketsiz BCD “72” (AH = 7, AL = 2).

AH00hAL48hBL09hAF?CF?AX = 0048h (ikili 72)AL nibble'ları: 4 | 8

AAD: AL = 7 × 10 + 2 = 72 = 48h, AH = 0. Bölmeden önce ikiliye çevrildi.

AH00hAL09hBL08hAF?CF?AX = 0009h (ikili 9)AL nibble'ları: 0 | 9

DIV BL: 72 / 8 → AL = 9, AH = 0 (kalan). AAD olmasaydı 0702h = 1794 bölünürdü.

AH00hAL19hBL08hAF?CF?AX = 0019h (ikili 25)AL nibble'ları: 1 | 9

AL = 19h: paketli BCD “19” (bir baytta iki basamak).

AH00hAL41hBL08hAF1CF0AX = 0041h (ikili 65)AL nibble'ları: 4 | 1

19h + 28h = 41h: ikili toplama. 9 + 8 = 17 alt nibble'dan taştı → AF = 1; 41h BCD olarak yanlış.

AH00hAL47hBL08hAF1CF0AX = 0047h (ikili 71)AL nibble'ları: 4 | 7

DAA: AF = 1 → AL + 06h = 47h. Sonuç “47” = 19 + 28 ✓

MOV  AL, 6
MOV  BL, 9
MUL  BL          ; AX = 6 × 9
AAM              ; basamaklara ayır
MOV  AX, 0702h   ; '72' paketsiz
AAD              ; ikiliye çevir
MOV  BL, 8
DIV  BL
MOV  AL, 19h     ; paketli 19
ADD  AL, 28h     ; + 28
DAA              ; BCD düzelt
RET

Örnek: Sıcaklık Dönüşümü · Kodu adım adım çalıştır

Kod İzleme: °C → °F

CL = 15 (°C) = 0Fh.

AL = 9.

IMUL CL: AX = 9 × 15 = 135 = 0087h. 135 işaretli bayta sığmaz (>127) → CF = OF = 1; ama sonuç AX'te eksiksiz.

CL = 5 (bölen).

IDIV CL: AX / 5 = 135 / 5 → AL = 1Bh (27), AH = 0 (kalan). Bayraklar tanımsız.

27 + 32 = 59 = 3Bh → AX = 003Bh. 15 °C = 59 °F ✓

RET. emu8086'da son durum: AX = 003Bh, CX = 0005h.

org 100h
start:
;celsius to fahrenheit according to f = c * 9 / 5 + 32
mov cl, 15
mov al, 9
imul cl
mov cl, 5
idiv cl
add al, 32
ret

f = c × 9 / 5 + 32. Önce çarpma, sonra bölme: 9/5 tam sayı bölmesinde 1 olurdu ve sonuç yanlış çıkardı.

Örnek: Sıcaklık Dönüşümü · Kodu adım adım çalıştır

Kod İzleme: °F → °C

CL = 59 (°F) = 3Bh.

59 − 32 = 27 = 1Bh.

AL = 5.

AX = 5 × 27 = 135 = 0087h; CF = OF = 1 (AL'ye sığmadı).

CL = 9.

135 / 9 = 15 = 0Fh → AL, kalan AH = 0. 59 °F = 15 °C ✓

RET.

org 100h
start:
;fahrenheit to celsius according to: c = (f - 32) * 5 / 9
mov cl, 59
sub cl, 32
mov al, 5
imul cl
mov cl, 9
idiv cl
ret

Örnek: Sıcaklık Dönüşümü

Neden IMUL / IDIV? Sınırlar

Negatif sıcaklıklar

c = −10: IMUL → AX = FFA6h (−90), IDIV → AL = EEh (−18), +32 → 0Eh = 14 °F ✓

MUL/DIV kullanılsaydı F6h, 246 sanılırdı ve sonuç anlamsız olurdu.

Tam sayı bölmesi

IDIV kesirli kısmı atar (sıfıra doğru): c = 1 → 9/5 = 1 → 33 °F (doğrusu 33,8). Yuvarlama için kalan (AH) incelenebilir.

°C → °F geçerli aralık

Sonuç işaretli bayt AL'de: c ∈ [−71, 53]. c = 54'te AL = 81h (OF = 1, yanlış); c = 72'de bölüm AL'ye sığmaz → bölme hatası.

°F → °C geçerli aralık

f − 32 bayta sığmalı: f ∈ [−96, 127]. Daha geniş aralık için sözcük işlemleri (AX, CWD, IDIV BX) kullanılır.

Laboratuvar · 8086 komutları adım adım

Laboratuvar: Aritmetik ve Mantık

Özet

Özet: Hangi Komut Hangi Bayrağı Etkiler?

KomutCFZFSFOFPFAF
ADD SUB CMP ADC SBB✓✓✓✓✓✓
NEG✓✓✓✓✓✓
INC DEC—✓✓✓✓✓
AND OR XOR TEST0✓✓0✓?
NOT——————
MUL IMUL✓??✓??
DIV IDIV??????
SHL SHR SAR✓✓✓✓¹✓?
ROL ROR RCL RCR✓——✓¹——
AAA AAS✓????✓
MOV LEA LOOP——————

✓: sonuca göre · 0: temizlenir · —: değişmez · ?: tanımsız · ¹: yalnız kaydırma sayısı 1 iken tanımlı.

Özet

Özet

Bayraklar

CF işaretsiz, OF işaretli taşma; ZF sıfır; SF MSB; PF düşük baytta çift sayıda 1; AF nibble eldesi.

1. grup

Sonuç ilk işlenende; CMP/TEST yalnız bayrak. Mantıksal komutlar CF = OF = 0.

2. grup

Örtük AL/AX/DX. Bayt: AX = AL × op, AL = AX / op (AH kalan). Sözcük: DX:AX.

3. grup

INC/DEC CF'yi korur; NOT bayrak değiştirmez; NEG ikiye tümleyen.

Kaydırma ve döndürme

Sayı 1 ya da CL. SHL ×2, SHR işaretsiz ÷2, SAR işaretli ÷2 (−∞'a yuvarlar); döndürmede bit kaybolmaz, RCL/RCR CF ile 9 (17) bitlik halka kurar.

BCD

AAA/AAS toplama/çıkarma sonrası, AAM çarpma sonrası, AAD bölme öncesi.

Tuzaklar

Bölmeden önce AH/DX hazırla; işaretli veride IMUL/IDIV; aralık taşmalarını bayraklarla denetle.

Özet

Alıştırmalar

  1. MOV AL, 0C0h / ADD AL, 0C0h sonrası AL, CF, OF, SF, ZF, PF nedir?
  2. CMP AL, BL sonrası işaretsiz “AL < BL” hangi bayrakla, işaretli “AL < BL” hangi bayraklarla anlaşılır?
  3. AX = 0FFFFh, BX = 0FFFFh iken MUL BX sonrası DX, AX, CF nedir?
  4. AX = 0100h, BL = 0 iken DIV BL ne olur?
  5. Dizi toplama programını sözcük (DW) dizileri için değiştirin.
  6. Bir bayttaki 1 bitlerini sayan programı SHL/TEST ve döngüyle yazın. PF ile karşılaştırın.
İpuçları / cevaplar
  1. C0h + C0h = 180h → AL = 80h; CF = 1, OF = 0 (−64 + −64 = −128 sığar), SF = 1, ZF = 0, PF = 0 (tek 1 biti).
  2. İşaretsiz: CF = 1. İşaretli: SF ≠ OF.
  3. 65535² = FFFE0001h → DX = FFFEh, AX = 0001h, CF = OF = 1.
  4. Sıfıra bölme → bölme hatası (INT 0).
  5. vec1 dw …, mov ax,[si], add ax,[bx], mov [di],ax; işaretçiler add si,2 ile ilerler.
  6. CX = 8 tur; her turda TEST AL,80h ile bit sınanır, 1 ise sayaç INC, sonra SHL AL,1. PF yalnızca sayının çift/tek olduğunu verir.

Özet

Alıştırmalar (2)

  1. DX = 0005h, AX = 0000h, BX = 0005h iken DIV BX ne olur?
  2. MOV AL, 70h / ADD AL, 30h sonrası AL ve OF nedir? Doğru toplamı 16 bitte nasıl elde edersiniz?
  3. 00012345h − 0000ABCDh işlemini SUB/SBB ile yapın. SUB sonrası CF kaçtır?
  4. 32 × 32 bit çarpmada dört kısmi çarpım sonucun hangi sözcüklerine eklenir?
  5. DX = 0000h, AX = 0FFFh, CF = 0 iken SHL AX, 1 ve RCL DX, 1 sonrası DX:AX nedir?
İpuçları / cevaplar
  1. DX ≥ BX: bölüm 50000h = 327680 AX'e sığmaz → bölme hatası (INT 0), bölen sıfır olmasa da.
  2. AL = A0h, OF = 1 (112 + 48 = 160 > 127). İki sayı ayrı ayrı CBW ile genişletilip 16 bitte toplanır: 00A0h = 160.
  3. 2345h − ABCDh = 7778h, CF = 1 (ödünç); 0001h − 0000h − 1 = 0000h → 00007778h (30584).
  4. A0·B0 → z1:z0; A1·B0 ve A0·B1 → z2:z1; A1·B1 → z3:z2. Eldeler ADC ile bir üst sözcüğe taşınır.
  5. AX = 1FFEh, çıkan bit 0 → CF = 0; RCL DX'e 0 sokar → DX = 0000h. DX:AX = 00001FFEh (0FFFh × 2).

Özet

Kaynaklar

  • Intel, The 8086 Family User's Manual, 1979 — Instruction Set bölümü.
  • B. B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009 — Bölüm 5: Aritmetik, mantık, kaydırma ve döndürme komutları.
  • emu8086 yardım belgeleri: “8086 instructions” ve “Arithmetic and logic instructions” sayfaları.
  • K. R. Irvine, Assembly Language for x86 Processors, 7. baskı, Pearson, 2014 — Bölüm 7: Kaydırma ve döndürme komutları.
  • A. S. Tanenbaum, Modern Operating Systems, 3. baskı, Pearson, 2008.
  • M. Bodur, Mikroişlemcilere Giriş: Assembler ile Yazılım ve Arayüz, EMO, 2014.
  • Ş. Ç. Öztürk, O. Ergin, Intel 8086 ile Mikroişlemci Programlamaya Giriş, 2009.

Son

Bölüm 6: Aritmetik, Mantık ve Kaydırma Komutları
Sonraki bölüm: Bölüm 7: Akış Kontrolü · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.