Bölüm 3.2: Assembly
Giriş
Öğrenme Çıktıları
Assembly dilinin makine dili ve yüksek düzeyli dillerle ilişkisini açıklamak.
Etiket, komut, işlenen ve açıklamadan oluşan satırları okumak; komutu direktiften ayırmak.
Yazmaç, anlık değer ve bellek işlenenlerini ve komutların örtük işlenenlerini tanımak.
Yazmaç ve bellek işlenenli komutların süre farkını saat turuyla hesaplamak.
IP'nin nasıl ilerlediğini ve hangi komutların bayrakları değiştirdiğini izlemek.
emu8086 ile basit bir .COM programını yazıp adım adım çalıştırmak.
Assembly Dili
Assembly Dili
- Düşük düzeyli bir programlama dilidir: her komut, işlemcinin tek bir makine komutuna karşılık gelir.
- Makine kodundaki sayılar yerine akılda kalıcı komut kısaltmaları (mnemonic) kullanılır:
MOV,ADD,JMP… - Bilgisayarın yapısını (yazmaçlar, bellek, sistem yolu) bilmeyi gerektirir.
- Bilgisayarın temel yapısını ve bir programın gerçekte nasıl çalıştığını anlamak açısından önemlidir.
- Her işlemci ailesinin kendi assembly dili vardır; bu derste Intel 8086 ve emu8086 kullanılır.
Assembly: MOV AX, 5
Onaltılık makine kodu: B8 05 00
CPU'nun gördüğü:10111000 00000101 00000000
16 bitlik 0005h, bellekte düşük bayt önce (05 00) saklanır.
Assembly Dili
Assembler ve emu8086
Bu derste örnekler emu8086 söz dizimiyle yazılır; çoğu MASM/TASM ile de uyumludur.
Assembly Dili
Neden Assembly?
Assembly dili ile oluşturulmuş bir program:
Artıları
- Daha az yer kaplar (gereksiz kod yok).
- Yalnızca yapması gereken işlemleri yaptığından daha hızlıdır.
- Yüksek düzeyli dillerin yapamadığı işlemleri yapabilir: port G/Ç, kesme işleme, bayraklara doğrudan erişim.
- Önyükleyici, aygıt sürücüsü, gömülü sistem gibi alanlarda vazgeçilmezdir.
Eksileri
- Taşınabilir değildir: 8086 kodu ARM'da çalışmaz.
- Yazması, okuması ve hata ayıklaması zahmetlidir.
- Büyük projelerde verim düşüktür; modern derleyiciler çoğu zaman yeterince hızlı kod üretir.
Assembly Dili
Komut Satırının Yapısı
[etiket:] komut [hedef], [kaynak] [; açıklama]| Satır | Etiket | Komut | İşlenenler | Açıklama |
|---|---|---|---|---|
basla: MOV AX, 5 ; AX ← 5 | basla | MOV | AX, 5 | ; AX ← 5 |
INC AX | — | INC | AX | — |
RET | — | RET | yok | — |
- İki işlenenli komutlarda sıra hedef, kaynaktır:
MOV AX, BX→ AX ← BX. - Assembler büyük-küçük harfe duyarsızdır:
mov ax, bxileMOV AX, BXaynıdır. ;işaretinden satır sonuna kadar her şey açıklamadır ve makine koduna çevrilmez.
Assembly Dili
Komut mu, Direktif mi?
| Satır | Türü | Bellekte ne üretir? |
|---|---|---|
MOV AX, 5 | komut | makine kodu: B8 05 00 |
ORG 100h | direktif | hiçbir şey; konum sayacını 0100h yapar |
sayi DB 0 | direktif (veri tanımı) | 1 bayt veri: 00 |
k EQU 5 | direktif | hiçbir şey; k adı 5 değerini alır |
END | direktif | hiçbir şey; kaynak burada biter |
PUTC 'A' | makro çağrısı | makro gövdesindeki komutların kodu |
Assembly Dili
Etiketler ve Adlar
basla: MOV CX, 3 ; kod etiketi don: INC AX LOOP don ; don = adres RET sayi DB 7 ; veri adı
- Kod etiketi iki nokta üst üste ile biter ve bir komutun adresini (CS içindeki bağıl konumunu) temsil eder; kendisi makine kodu üretmez.
- Değişken adı iki noktasız yazılır; adı, türü (DB, DW…) ve adresi birlikte saklanır.
- Ad harfle ya da alt çizgiyle başlar, rakamla başlayamaz; devamında harf, rakam ve alt çizgi olabilir.
- Komut, yazmaç ve direktif adları (MOV, AX, DB, END…) ad olarak kullanılamaz.
- Büyük-küçük harf ayrılmaz:
donileDONaynı etikettir; ikisini birden tanımlamak “iki kez tanımlı” hatası verir.
| Ad | _sayac | toplam2 | 2toplam | cx | son-deger |
|---|---|---|---|---|---|
| Geçerli mi? | evet | evet | rakamla başlıyor | yazmaç adı | − bir işleçtir |
Yazmaçlarla Çalışma
İşlenen Türleri ve Örtük İşlenenler
MOV AX, BX: değer işlemcinin içinden gelir; en hızlı tür.MOV AX, 5: değer komutun baytlarının içindedir; yalnızca kaynak olabilir.MOV AX, [BX]: değer bellekten bir yol döngüsüyle okunur.| Komut | Yazılan işlenen | Örtük işlenen(ler) |
|---|---|---|
MUL BL | BL | AL (çarpılan), AX (sonuç) |
DIV BL | BL | AX (bölünen), AL (bölüm), AH (kalan) |
LOOP don | don | CX (sayaç) |
CBW | — | AL → AX |
PUSH AX | AX | SS:SP (yığın tepesi) |
XLAT | — | AL (indis ve sonuç), BX (tablo adresi) |
Örtük işlenen komutta yazılmaz ama değişir: MUL BL AH'yi de siler. Bir yazmacın değerini korumak isteyen program, kullandığı komutların örtük işlenenlerini bilmelidir.
Yazmaçlarla Çalışma · Kodu adım adım çalıştır
Kod İzleme: MUL, SHR ve LOOP'un Örtük İşlenenleri
ORG 100h MOV AL, 12 MOV BL, 10 MUL BL ; AX = AL × BL MOV CL, 2 SHR AX, CL ; sayı CL'de MOV CX, 3 ; LOOP sayacı don: ADD AX, 1 LOOP don ; CX azalır RET
AL = 12, BL = 10. AH başlangıçta 0.
MUL BL yalnız BL'yi yazar; çarpılan örtük olarak AL, sonuç örtük olarak AX'tir: AX = 120 = 0078h. Sonuç 8 bite sığdığı için CF = 0.
SHR AX, CL: 1'den büyük kaydırma sayısı yalnızca CL'de verilebilir. 120 ÷ 4 = 30 → AX = 001Eh.
CX = 3: LOOP'un örtük sayacı. CL de CX'in parçası olduğundan önceki 2 değeri silindi.
1. tur: AX + 1 = 31; LOOP CX'i 1 azaltır: CX = 2, sıfır değil → don.
2. tur: AX + 1 = 32; LOOP CX'i 1 azaltır: CX = 1, sıfır değil → don.
3. tur: AX + 1 = 33; LOOP CX'i 1 azaltır: CX = 0, döngü biter.
RET. Programda CX hiç azaltılmadı gibi görünse de LOOP onu üç kez değiştirdi: AX = 0021h = 33.
AX, CL ve CX bu programda komutların “gizli” işlenenleriydi; yazmaçların özel görevleri bu örtük kullanımlardan gelir.
Yazmaçlarla Çalışma
Yazmaç mı, Bellek mi?
- CPU'nun içindedir; erişim için yol döngüsü gerekmez.
- Sayısı çok azdır (8086'da 14 adet 16 bitlik yazmaç).
- Ara sonuçlar ve sayaçlar için idealdir.
- CPU'nun dışındadır; her erişim en az bir yol döngüsü (8086'da 4 saat periyodu) sürer.
- 1 MB'a kadar büyüktür.
- Program kodu, değişkenler, diziler ve yığın buradadır.
CX'te saklamak döngüyü hızlandırır.14 yazmaç: 8 genel amaçlı + 4 kesim + IP + FLAGS.
Yazmaçlarla Çalışma
Komut Süreleri: Yazmaç ve Bellek
| Komut (8086) | Saat turu |
|---|---|
MOV AX, BX | 2 |
MOV AX, 5 | 4 |
MOV AX, sayi | 10 |
MOV CX, [BX] | 8 + 5 = 13 |
ADD AX, BX | 3 |
ADD AX, sayi | 9 + 6 = 15 |
INC CX | 2 |
INC sayac (sözcük) | 15 + 6 = 21 |
- Bellek işlenenli komutlarda süreye etkin adres hesabı (EA) eklenir: doğrudan adres 6,
[BX]5,[BX+SI]7 tur. - Belleğe yazan komutlar daha uzundur:
INC sayacönce okur, sonra yazar (iki yol döngüsü). - AX'e doğrudan adresten yükleme kısa akümülatör biçimini kullanır: 10 tur.
- 1000 kez dönen döngüde sayaç CX'teyse artırma 1000 × 2 = 2000 saat turu, bellekteyse 1000 × 21 = 21 000 tur sürer; 5 MHz'de 0,4 ms yerine 4,2 ms.
IP ve Bayraklar · Kodu adım adım çalıştır
Kod İzleme: IP Nasıl İlerler?
Program CS:0100h'ye yüklenir; IP = 0100h ilk komutu gösterir.
MOV AX, 5 (B8 05 00) getirilir: IP = 0103h, yürütülünce AX = 0005h.
3 bayt daha: IP = 0106h, BX = 0002h.
INC AX tek bayttır (40h): IP = 0107h, AX = 0006h.
ADD AX, BX 2 bayt: IP = 0109h, AX = 0008h.
RET yığından 0000h'yi çeker: IP = 0000h, SP = 0000h. PSP:0000'daki INT 20h programı bitirir.
ORG 100h MOV AX, 5 ; 3 bayt MOV BX, 2 ; 3 bayt INC AX ; 1 bayt ADD AX, BX ; 2 bayt RET ; 1 bayt
IP ve Bayraklar · Kodu adım adım çalıştır
Kod İzleme: Hangi Komut Bayrağa Dokunur?
ORG 100h STC ; CF = 1 MOV AL, 0FFh ; bayraklar aynı INC AL ; CF'ye dokunmaz MOV CX, 0 ; ZF aynı kalır DEC AL ADD AL, 1 ; CF yeni CLC NOT AL ; bayraklar aynı RET
STC: CF = 1. Bayrağı doğrudan değiştiren komutlardan biri.
MOV AL, 0FFh: AL değişti, bayrakların hiçbiri değişmedi. MOV bayrak etkilemez.
INC AL: FFh + 1 = 00h → ZF = 1, AF = 1, PF = 1. CF hâlâ 1: INC ve DEC elde bayrağına dokunmaz.
MOV CX, 0: sonuç sıfır olsa da ZF yeniden hesaplanmaz; önceki komutun ZF'si kalır.
DEC AL: 00h − 1 = FFh → SF = 1, ZF = 0. CF yine 1: DEC ödünç almayı CF'ye yazmaz.
ADD AL, 1: FFh + 1 = 100h → AL = 00h. ADD bütün durum bayraklarını yeniden yazar: CF = 1 bu kez ADD'in eldesi.
CLC: CF = 0.
NOT AL: AL = FFh, ama ZF hâlâ 1. NOT hiçbir bayrağı değiştirmez; sonucu sınamak için ardından TEST AL, AL ya da CMP gerekir.
MOV, NOT, XCHG, LEA, PUSH ve POP bayrakları değiştirmez; INC ve DEC CF dışındakileri değiştirir. Koşullu atlamadan hemen önce bayrağı hangi komutun ayarladığına bakılır.
İlk Program
.COM Program Şablonu
ORG 100h ; .COM: kod 0100h'den başlar MOV AX, 5 ; AX = 5 MOV BX, 3 ; BX = 3 ADD AX, BX ; AX = AX + BX = 8 MOV CL, AL ; CL = 08h RET ; DOS'a dön sayi DB 0 ; değişkenler RET'ten sonra
ORG 100h: .COM programı kesimin 0100h adresine yüklenir; ilk 256 bayt (PSP) DOS'a aittir.- Komutlar yukarıdan aşağı, sırayla yürütülür.
RET: işletim sistemine geri döner.- Değişkenler kodun sonuna (RET'ten sonra) konur ki CPU onları komut sanıp yürütmesin.
- .COM'da başlangıçta
CS = DS = ES = SS,IP = 0100h,SP = FFFEh.
İlk Program · Kodu adım adım çalıştır
Kod İzleme: .COM Programı Bellekte
ORG 100h ; kod 0100h'den MOV AX, 5 MOV BX, 3 ADD AX, BX ; AX = 8 MOV CL, AL ; CL = 08h RET ; DOS'a dön sayi DB 0 ; veri
Program 0700:0100'e yüklendi. CS = DS = ES = SS = 0700h, IP = 0100h, SP = FFFEh; yığın tepesinde 0000h var.
MOV AX, 5 (3 bayt): AX = 0005h, IP = 0103h.
MOV BX, 3 (3 bayt): BX = 0003h, IP = 0106h.
ADD AX, BX (2 bayt): AX = 0008h, IP = 0108h.
MOV CL, AL (2 bayt): CL = 08h, IP = 010Ah.
RET yığından 0000h'yi alır: IP = 0000h, SP = 0000h. PSP:0000'daki INT 20h programı bitirir; 010Bh'deki sayi hiç yürütülmedi.
Komutlar 3, 3, 2, 2 ve 1 bayttır; IP her komutta uzunluğu kadar ilerler. Veriler RET'ten sonra durduğu için komut olarak yürütülmez.
İlk Program
Program Bellekte: Bayt Bayt
| Bağıl konum | Baytlar | Kaynak satırı | Not |
|---|---|---|---|
| 0100h | B8 05 00 | MOV AX, 5 | B8 + yazmaç no (AX = 0); sabit little-endian |
| 0103h | BB 03 00 | MOV BX, 3 | B8 + 3 (BX) |
| 0106h | 03 C3 | ADD AX, BX | C3 = 11 000 011: yazmaç–yazmaç, AX, BX |
| 0108h | 8A C8 | MOV CL, AL | C8 = 11 001 000: CL, AL |
| 010Ah | C3 | RET | tek baytlık komut |
| 010Bh | 00 | sayi DB 0 | veri; komut değil |
- .COM dosyası tam olarak bu 12 bayttır: başlık yoktur, DOS baytları 0100h'den itibaren belleğe kopyalar.
ORG 100hsatırının karşılığında bayt yoktur; yalnızca ilk baytın konumunu belirler.- Aynı komutun birden çok kodlaması olabilir:
ADD AX, BXiçin01 D8de geçerlidir. MASM 03 C3'ü seçer; ikisi de aynı işi yapar. - Bellekte komut ile veri arasında hiçbir işaret yoktur: 010Bh'deki 00, IP oraya gelseydi komut olarak çözülürdü.
İlk Program
emu8086 Öykünücü Penceresi
- single step bir komut yürütür; değişen yazmaçlar ve bellek hemen görünür.
- step back son adımı geri alır; bir hatanın nedenine geri dönmeyi kolaylaştırır.
- Komut listesindeki vurgulu satır sıradaki komuttur (CS:IP), az önce yürütülen değil.
- Komut listesi sabitleri onaltılık ve 5 basamakla gösterir (00005h).
- Ek pencereler: ekran çıktısı, değişkenler, yığın ve bayraklar.
Bellek sütunu fiziksel adresleri gösterir: 0700:0100 = 07100h. Çizim pencerenin yalnızca ana bölümlerini gösterir.
İlk Program
Yazım Kuralları
25 veya 25d onluk · 19h onaltılık · 00011001b ikili · 31o sekizli. Hepsi aynı değer: 25.0 konur: 0FFh, 0B800h. FFh yazılırsa assembler onu bir ad (etiket/değişken) sanır.'A' → ASCII kodu 41h. MOV CL, 'A' ile MOV CL, 41h aynı makine kodunu üretir.-1 8 bitte FFh, 16 bitte FFFFh olarak saklanır (ikiye tümleyen).mov, MOV, Mov aynıdır; var1 ile VAR1 aynı addır.; sonrası açıklamadır. Her satıra “ne” değil “neden” yazmak iyi alışkanlıktır.İlk Program
Sık Yapılan Hatalar
| Hatalı | Neden? | Doğrusu |
|---|---|---|
MOV AL, BX | Boyutlar farklı (8 ↔ 16 bit) | MOV AL, BL veya MOV AX, BX |
MOV DS, 1234h | Kesim yazmacına sabit atanamaz | MOV AX, 1234h · MOV DS, AX |
MOV AL, [AX] | Adreslemede yalnız BX, SI, DI, BP | MOV BX, AX · MOV AL, [BX] |
MOV AL, FFh | FFh bir ad sanılır | MOV AL, 0FFh |
MOV IP, 200h | IP'ye MOV ile yazılamaz | JMP ile atla |
MOV AL, 300 | 300 > 255, 8 bite sığmaz | MOV AX, 300 |
Bu kurallar MOV komutunun işlenen kısıtlarından gelir.
İlk Program
Daha Fazla Söz Dizimi Hatası
| Hatalı | Neden? | Doğrusu |
|---|---|---|
MOV CS, AX | CS yalnız JMP, CALL, RET, INT ile değişir | uzak atlama |
MOV ES, DS | kesimden kesime MOV yok | MOV AX, DS · MOV ES, AX |
MOV [BX], [SI] | iki bellek işleneni | MOV AL, [SI] · MOV [BX], AL |
INC [BX] | boyut belirsiz | INC BYTE PTR [BX] |
MOV AL, [BX+BP] | iki taban yazmacı birlikte olmaz | [BX+SI] ya da [BP+DI] |
ADD 5, AX | hedef sabit olamaz | ADD AX, 5 |
PUSH 5 | 80186'dan önce yok | MOV AX, 5 · PUSH AX |
SHL AX, 2 | 8086'da sayı yalnız 1 ya da CL | MOV CL, 2 · SHL AX, CL |
PUSH sabit ve SHL AX, 2 80186 ve sonrasında geçerlidir. MASM 8086 için derlerken hata verir; emu8086 kabul eder, ama bu kod gerçek bir 8086'da çalışmaz.
İlk Program
Derleme Hatası mı, Mantık Hatası mı?
MOV AL, BX: boyut uyuşmazlığıJMP bsla: tanımsız etiketMOV AL, 300: sığmayan sabit
- RET'i unutmak: veri komut sanılır
- İşaretli sayı için
JAkullanmak - ADC yerine ADD: elde kaybolur
- .EXE'de DS'yi yüklememek
Laboratuvar · 8086 komutları adım adım
Laboratuvar: İlk Programlar
Özet
Özet
[etiket:] komut hedef, kaynak ; açıklama. Direktifler (ORG, DB, EQU) makine kodu üretmez.ORG 100h ile 0100h'den başlar; veriler RET'ten sonra durur.Özet
Alıştırmalar
- AX = 0ABCDh iken
MOV AH, 0sonrası AX, AL ve BX değerleri nedir? - AX = 1234h, BL = 03h iken
MUL BLsonrası AX kaçtır? AH'deki 12h'ye ne olur? - 8 MHz'lik bir 8086'da 2000 kez dönen bir döngüde sayaç
INC sayac(21 tur) yerineINC CX(2 tur) ile artırılırsa kaç saat turu ve kaç milisaniye kazanılır? - AL = 80h iken
ADD AL, 80hsonrası AL, CF, ZF, SF, OF? - Program 0100h'de başlar: 3 + 2 + 1 + 4 baytlık dört komut yürütülünce IP ne olur?
MOV CX, ALveMOV ES, 0B800hneden hatalıdır? Düzeltin.
Cevaplar
- AX = 00CDh, AL = CDh; BX değişmez.
- MUL BL, AL'yi (34h = 52) BL ile çarpar: 52 × 3 = 156 = 009Ch. Sonuç bütün AX'e yazılır; AH'deki 12h silinir.
- 2000 × (21 − 2) = 38 000 tur; bir tur 1/8 MHz = 0,125 µs → 4,75 ms.
- 80h + 80h = 100h → AL = 00h, CF = 1, ZF = 1, SF = 0, OF = 1 (−128 + −128 sığmaz).
- 0100h + 10 = 010Ah.
- Boyut uyumsuz →
MOV CL, AL(ya daMOV CH, 0+MOV CL, AL); kesime sabit atanamaz →MOV AX, 0B800h·MOV ES, AX.
Özet
Kaynaklar
- emu8086 belgeleri, 8086 assembler tutorial for beginners (bölüm 1: numbering systems, bölüm 2: memory access).
- Intel, 8086 16-Bit HMOS Microprocessor veri sayfası.
- Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson.
- Muhammad Ali Mazidi, Janice G. Mazidi, The 80x86 IBM PC and Compatible Computers, Pearson.