Bölüm 7: Prosedürler
Çoktan Seçmeli · Tanımlama
Soru 1: Direktif mi, Komut mu?
Aşağıdakilerden hangisi assembler direktifi değildir, işlemcinin yürüttüğü bir komuttur?
C: CALL (yakın çağrıda E8) ve RET (C3) makine koduna çevrilen komutlardır. PROC/ENDP prosedürün başını, sonunu ve türünü (NEAR/FAR) assembler'a bildirir; END kaynağın bittiğini söyler. Direktifler bellekte yer kaplamaz.
Kod Okuma · Tanımlama
Soru 2: Prosedüre Düşmek
Programcı ana programın sonuna RET yazmayı unutmuş. Program bittiğinde AX kaçtır? ikiyle prosedürü kaç kez çalışır?
ORG 100h MOV AX, 2 CALL ikiyle ikiyle PROC ADD AX, AX RET ikiyle ENDP
Cevabı göster
AX = 0008h; prosedür iki kez çalışır.
- CALL ikiyle: dönüş adresi 0106h itilir; AX = 2 + 2 = 4; RET 0106h'ye döner.
- 0106h, prosedürün kendi ilk komutudur: işlemci ENDP'yi "görmez", akış prosedüre düşer. AX = 8.
- Bu RET yığından DOS'un koyduğu 0000h'yi alır ve program sonlanır.
Düzeltme: CALL'dan sonra RET; prosedürler ana programın RET'inden sonra yazılır.
Çoktan Seçmeli · CALL ve RET
Soru 3: RET Ne Yapar?
Yakın (near) bir prosedürün sonundaki RET komutu ne yapar?
A: RET yığının üstündeki sözcüğü dönüş adresi olarak IP'ye alır ve SP'yi 2 artırır (POP IP gibi). B, CALL'ın ilk yarısını anlatır. CS ile IP'yi birlikte alan uzak dönüş RETF'tir (D). Dönüş adresi yazmaçta değil, yığında saklanır (C).
Çıktı Sorusu · CALL ve RET
Soru 4: CALL, RET ve Dönüş Adresi
CALL KARE çalışınca yığına ne yazılır, SP ve IP ne olur? Program bittiğinde AX ve DX nedir? (Yorumlar komut adresleridir.)
ORG 100h MOV AX, 3 ; 0100h CALL KARE ; 0103h ADD AX, 1 ; 0106h RET ; 0109h KARE PROC MUL AX ; 010Ah RET ; 010Ch KARE ENDP
Cevabı göster
CALL, sonraki komutun adresini iter: SP = FFFCh, [FFFCh] = 0106h; IP ← 010Ah (KARE).
MUL AX: DX:AX ← 3 × 3 = 9 → AX = 0009h, DX = 0000h (16 bitlik MUL DX'i de yazar).
KARE'deki RET 0106h'yi IP'ye alır, SP = FFFEh. ADD AX, 1 → AX = 000Ah, DX = 0000h; son RET programı bitirir.
Hesap Sorusu · CALL ve RET
Soru 5: CALL'ın Makine Kodu
Yakın CALL 3 bayttır: E8 + 16 bitlik uzaklık. (a) 0100h'deki CALL m1, m1 0107h'de. (b) 0120h'deki CALL p, p 0100h'de. Makine kodları nedir, yığına hangi adres itilir?
Cevabı göster
Uzaklık = hedef − (CALL adresi + 3).
(a) 0107h − 0103h = 0004h → E8 04 00; yığına 0103h itilir.
(b) 0100h − 0123h = −23h = FFDDh → E8 DD FF; yığına 0123h itilir.
16 bitlik değer little-endian saklanır: önce düşük bayt. Hedef mutlak adres olarak değil uzaklık olarak saklandığından kod bellekte taşınsa da çalışır.
Çoktan Seçmeli · CALL ve RET
Soru 6: Üç CALL, Hiç RET
SP = FFFEh iken arka arkaya üç yakın CALL yürütülüyor (iç içe çağrılar, henüz hiç RET yok). SP kaç olur?
D: Her yakın CALL yığına 2 baytlık dönüş adresi iter: FFFEh − 3 × 2 = FFF8h. Yığın aşağı doğru büyür, SP azalır (C yanlış). FFF4h 4 baytlık uzak çağrılara, FFFBh 1 baytlık itmeye karşılık gelirdi; 8086 yığına hep sözcük yazar.
Adım Adım Çalıştırma · Örnek Programlar
Soru 7: İç İçe Çağrılar
main, A'yı; A da B'yi çağırıyor. Yığında en çok kaç dönüş adresi birikir? RET'ler hangi sırayla döner? Sonunda AX nedir?
AX = 1. SP = FFFEh; yığında DOS'un 0000h'si var.
CALL A: dönüş adresi 0106h itilir (SP = FFFCh), IP = 0107h.
A içinde AX = 3.
A içinden CALL B: 010Dh itilir, SP = FFFAh. Yığında iki dönüş adresi var.
B: AX = AX + AX = 6.
B'nin RET'i en üstteki 010Dh'yi alır: A'ya döner (LIFO). SP = FFFCh.
A devam eder: AX = 10 = 000Ah.
A'nın RET'i 0106h'yi alır: main'e döner, SP = FFFEh. Son çağrılan ilk döndü. main'in RET'i programı bitirir: AX = 000Ah.
ORG 100h MOV AX, 1 CALL A RET A PROC ADD AX, 2 CALL B ADD AX, 4 RET A ENDP B PROC ADD AX, AX RET B ENDP
Çıktı Sorusu · Parametreler
Soru 8: Yazmaçlarla Parametre
m2 prosedürü parametrelerini AL ve BL'de alır, sonucu AX'te verir. Program bittiğinde AX nedir? İkinci çağrı neden farklı sonuç verir?
ORG 100h MOV AL, 5 MOV BL, 3 CALL m2 CALL m2 RET m2 PROC ; Girdi: AL, BL MUL BL ; Çıktı: AX = AL * BL RET m2 ENDP
Cevabı göster
1. çağrı: AX = 5 × 3 = 15 = 000Fh. AL artık 0Fh.
2. çağrı: AX = 0Fh × 3 = 45 = 002Dh.
MUL BL sonucu AX'e yazar ve AL'yi değiştirir; ikinci çağrının birinci parametresi, ilk çağrının sonucu olur. Prosedürün girdi, çıktı ve bozduğu yazmaçlar (burada AX, CF, OF) başına açıklama olarak yazılmalıdır.
Çoktan Seçmeli · Parametreler
Soru 9: Parametre Yolları
Parametre geçirme yolları için hangisi doğrudur?
B: Adres (işaretçi) ile geçirmede yalnızca dizinin başlangıç adresi verilir; veri kopyalanmaz (print_me örneğinde SI). Yazmaçlar en hızlı yoldur (A). Bellek değişkenleri kalıcıdır (C). 8086'da SP taban yazmacı olamaz; yığındaki parametreler BP ile ([BP+4]) okunur (D).
Hata Bulma · Parametreler
Soru 10: Döngü Neden Bitmiyor?
Program 3 kez "**" yazmak için yazıldı ama hiç bitmiyor. Neden? İki düzeltme önerin.
ORG 100h MOV CX, 3 tekrar: CALL yaz LOOP tekrar RET yaz PROC MOV CX, 2 ic: MOV AL, '*' MOV AH, 0Eh INT 10h LOOP ic RET yaz ENDP
Cevabı göster
yaz, ana döngünün sayacı CX'i kendi döngüsü için kullanıyor. Prosedür dönerken CX = 0'dır. Ana döngüdeki LOOP CX'i FFFFh yapar ve geri atlar; her çağrı CX'i yine 0 yaptığı için bu sonsuza dek sürer: ekrana durmadan * yazılır.
- Prosedürde koruma: girişte
PUSH CX, RET'ten öncePOP CX. Böylece çıktı 6 yıldız olur. - Ya da çağıran taraf korur:
PUSH CX/CALL yaz/POP CX.
Adım Adım Çalıştırma · Örnek Programlar
Soru 11: Harf Dönüştüren Prosedür
buyuk prosedürü AL'deki küçük harfi büyüğe çevirir, diğer karakterleri değiştirmez. Döngü bittiğinde metin ne olur?
SI = metin'in adresi (011Dh), CX = 3 karakter.
Tur 1: AL = 'a' (61h). 'a' ≤ AL ≤ 'z' → SUB AL, 20h: 'A' (41h). RET'ten sonra belleğe yazıldı.
Tur 2: AL = '1' (31h) < 'a' → CF = 1, JB son: değişmeden döner, bellekte '1' kalır. JB işaretsiz karşılaştırmadır.
Tur 3: 'b' → 'B'.
LOOP: CX = 0, döngü biter. metin = 'A1B'. buyuk CX'e dokunmadığı için LOOP sayacı güvende; girdi ve çıktı AL'dedir.
ORG 100h LEA SI, metin MOV CX, 3 dongu: MOV AL, [SI] CALL buyuk MOV [SI], AL INC SI LOOP dongu RET buyuk PROC CMP AL, 'a' JB son CMP AL, 'z' JA son SUB AL, 20h son: RET buyuk ENDP metin DB 'a1b'
Çoktan Seçmeli · Sık Yapılan Hatalar
Soru 12: CALL Yerine JMP
Programcı CALL ekle yerine yanlışlıkla JMP ekle yazmış. .COM programında ekle'nin sonundaki RET ne yapar?
ORG 100h MOV AX, 1 JMP ekle MOV BX, 9 ; çalışır mı? RET ekle PROC ADD AX, 5 RET ekle ENDP
A: JMP dönüş adresi itmez. RET yığının üstünde ne varsa onu IP'ye alır; ana program bir şey itmediyse bu DOS'un 0000h'sidir: PSP'deki INT 20h programı sessizce bitirir ve JMP'ten sonraki satırlar hiç çalışmaz. Yığında başka bir değer olsaydı rastgele bir adrese dönülürdü.
Çoktan Seçmeli · Sık Yapılan Hatalar
Soru 13: Sonucu Korumak
Bir prosedür sonucunu AX'te döndürüyor; girişte PUSH AX, RET'ten önce POP AX yapıyor. Ne olur?
C: POP AX, girişteki değeri geri yükleyerek hesaplanan sonucu siler. PUSH/POP sayısı eşit olduğu için yığın dengelidir ve RET doğru döner (A). Kural: prosedür kullandığı yazmaçları korur, ama sonuç döndüren yazmacı korumaz.
Kod Yazma · Örnek Programlar
Soru 14: Büyük Olanı Döndür
AX ve BX'teki işaretsiz sayılardan büyüğünü AX'te döndüren buyugu prosedürünü yazın. Prosedür başka yazmacı bozmasın. Çağırma örneği de verin.
Cevabı göster
; Girdi: AX, BX (işaretsiz)
; Çıktı: AX = büyük olan
buyugu PROC
CMP AX, BX
JAE tamam
MOV AX, BX
tamam:
RET
buyugu ENDPMOV AX, 5 MOV BX, 9 CALL buyugu ; AX = 9
İşaretsiz karşılaştırma için JAE (CF = 0). Yalnızca AX değişir; başka yazmaç kullanılmadığı için PUSH/POP gerekmez. Denendi: (5, 9) → 9, (9, 5) → 9, (7, 7) → 7, (FFFFh, 1) → FFFFh; CX ve BX korunur. İşaretli sayılar için JGE kullanılırdı.
Adım Adım Çalıştırma · Sık Yapılan Hatalar
Soru 15: Kendini Çağıran Prosedür
fakt kendini çağırarak AX = CX! hesaplıyor (CX = 3). Yığın en çok ne kadar derinleşir? Durma koşulu olmasaydı ne olurdu?
CALL fakt: 0109h itildi, SP = FFFCh. CX = 3.
CX = 3 > 1: AX = 1 × 3 = 3, CX = 2; kendini çağırır: 0115h itildi, SP = FFFAh.
AX = 3 × 2 = 6, CX = 1; yine CALL: üçüncü dönüş adresi, SP = FFF8h.
CMP CX, 1 → CX ≤ 1, JBE bitti: durma koşulu. İlk RET 0115h'ye döner (SP = FFFAh).
İkinci RET de 0115h'ye döner (SP = FFFCh): her RET bir dönüş adresi tüketir, 0115h'deki RET art arda çalışır.
Üçüncü RET 0109h'ye döndü, SP = FFFEh. Ana program: AX = 6. Durma koşulu (CMP/JBE) olmasaydı her çağrı 2 bayt yer, yığın kodun üzerine kadar büyürdü (yığın taşması).
ORG 100h MOV CX, 3 MOV AX, 1 CALL fakt RET fakt PROC CMP CX, 1 JBE bitti MUL CX DEC CX CALL fakt bitti: RET fakt ENDP
Çoktan Seçmeli · Sık Yapılan Hatalar
Soru 16: Ad Uyuşmazlığı
Hangisi assembler'ın derleme sırasında yakalayabileceği bir prosedür hatasıdır?
D: PROC ve ENDP'deki adlar aynı olmalıdır; uyuşmazlık bir sözdizimi hatasıdır. Diğerleri geçerli koddur ve yalnızca çalışma sırasında ortaya çıkar: RET yoksa akış prosedürden sonraki koda düşer, PUSH/POP dengesizliğinde RET yanlış adrese döner, bozulan CX döngüyü şaşırtır.