C.7.1. Birleştirici İle Bağlayıcının Kullanılması
⚠
Uyarı
Kitabın bu kısmı
eski bilgiler içermektedir. Ancak, okuyucunun
yararına olabileceği düşünülerek aynen korunmuştur.
Bir C programında, fonksiyon isimleri dışsal simgelermiş gibi işlem görürler ve bağlayıcı tarafından kullanılmaları için, amaç program dosyasına kaydedilirler. Fakat bir farkla: C derleyicisi her fonksiyon isminin önüne bir altçizgi ekler. Örneğin:
xyz (…) { … }
fonksiyon tanımında, fonksiyon ismi amaç
programda _xyz şeklinde kaydedilir. (Eski) Standarda göre,
dışsal tanıtıcı sözcüklerde, anlamlı karakter sayısı en az 8’dir.
Ayrıca, küçük büyük harf ayırımı yapılmayabilir.
Bir C fonksiyonu başka bir C fonksiyonunu çağırdığında, çağrıdaki argümanlar ve dönüş adresi, yığıt adı verilen bir veri yapısı içinde çağrılan fonksiyona geçirilir ve çağrılan fonksiyon değişiklikleri bu yığıt içinde yapar. Bundan dolayı, çağıran ile çağrılan fonksiyonun bu yığıtı nasıl değiştirdiğini anlamak çok önemlidir.
Yığıt, belleğin büyük adreslerinden küçük adreslerine doğru büyür. C derleyicisi, çağrıdaki argümanları, argüman listesindeki sıralarına göre, fakat sağdan başlayarak yığıta yerleştirir. Böylece, yığıta en son itilen ve bundan dolayı en düşük adreste bulunan argüman en soldaki, yani argüman listesindeki ilk argümandır. Çağıran yordam tarafından yığıta en son itilen şey ise dönüş adresidir. Çağrılan yordam Taban Yazmaç BP’nin içeriğini saklayarak, yerel verileri için yer ayırarak ve, SI ile DI gibi, içerikleri değişebilecek olan yazmaçların içeriklerini saklayarak yığıtta değişiklikler yapar. Aşağıdaki çizelge yığıtın içeriğini göstermektedir.
| n’inci argüman | (büyük adres) | ||
| çağıran fonksiyon | n-1’inci argüman | ||
| tarafından değiştirilen | … | ||
| yığıt bölümü | birinci argüman | ||
| dönüş adresi | |||
| çağrılmış fonksiyon | saklanmış BP | ← BP | |
| tarafından değiştirilen | yerel veriler | ||
| yığıt bölümü | saklanmış yazmaçlar | ← SP | (küçük adres) |
Her argüman için kullanılan bayt sayısı argümanın tipi ve, değerle veya referansla çağrı gibi, argümanı geçirmek için kullanılan yönteme bağlıdır. Referansla çağrı durumunda, bir adres geçirildiğine göre, bu sayı adresin yakın/uzak niteliğine de bağlıdır. Aynı durum dönüş adresi için de söz konusudur. Her biri için kullanılan bayt sayısı şöyledir:
| Yöntem | Tip | Bayt |
|---|---|---|
| değerle | short, int | 2 |
| değerle | long | 4 |
| değerle | float | 4 |
| değerle | double | 8 |
| referansla | yakın | 2 |
| referansla | uzak | 4 |
| dönüş adresi | yakın | 2 |
| dönüş adresi | uzak | 4 |
Program minik, küçük veya kısa bellek modelinde derlenmişse
dönüş adresi yakın, aksi takdirde uzaktır. Uzak adresler
kesim:uzaklık şeklinde olurlar.
C’de dizi dışındaki tüm veri yapılarının değerle, dizilerin ise referansla geçirildiğini anımsayın. Eğer bir dizinin değerle geçirilmesi isteniyorsa, o zaman değerle geçirilen bir yapının tek üyesi olarak tanımlanmalıdır.
Çağrılan yordam, işini bitirdikten sonra, hesapladığı değeri şu şekilde döndürür:
| Döndürülen değer | Yazmaç |
|---|---|
| 1 bayt | AL |
| 2 bayt | AX |
| 4 bayt | yüksek baytlar DX’te, düşük baytlar AX’te |
| > 4 bayt | değerin adresi DX:AX’te |
Aşağıdaki örnekte, birleştirici dilde yazılmış xyz adındaki
fonksiyonu çağıran bir C main fonksiyonu gösterilmektedir:
extern int xyz (int, int); main (…) { … xyz(3,5); … }
.MODEL SMALL
.CODE
PUBLIC _xyz
_xyz PROC
push bp ; Taban gösterge yazmacını sakla
mov bp,sp ; Yığıtta … boyunda yeni
sub sp,… ; bir taban bölge aç
push si ; SI ve DI yazmaçlarını sakla
push di ;
pushf ; Bayrak yazmacını sakla
mov ax,[bp+4] ; İlk argümanı AX'e taşı
mov cx,[bp+6] ; İkinci argümanı CX'e taşı
… ; xyz'nin hesaplaması
… ; gereken şeyi hesapla
mov ax,… ; Dönüş değerini koy
popf ; Bayrak yazmacını geri al
pop di ; DI ve SI yazmaçlarını geri al
pop si
mov sp,bp ; Yığıtı temizle
pop bp ; Eski BP'yi geri al
ret ; Çağırana dön
_xyz ENDP
END
Programları ayrı ayrı amaç dosyaları içine derleyin ve birleştirin; daha sonra bu iki dosyayı tek bir yürütülebilir dosya şeklinde bağlayın.