High-level dillerde program yazarken, arka planda otomatik yapılan ama low-level dillerde (özellikle Assembly) manuel olarak yönetmemiz gereken pek çok işlem vardır. Bunların en önemlilerinden birisi de prologue ve epilogue işlemleridir.

İşlemin Assembly dilindeki görüntüsü
Bu konuya başlamadan önce birkaç temel kavrama değineceğim:
- Register: CPU’nun en hızlı veri depolama alanıdır; işlem yapılacak veriler burada tutulur.
- Stack: LIFO (Last In, First Out) mantığıyla çalışan, fonksiyon çağrılarında geçici veri tutan bellek alanıdır.
- Stack Frame: Her fonksiyon çağrıldığında stack üzerinde ayrılan, argümanlar ve yerel değişkenleri barındıran bellek bloğudur.
- ESP/RSP: Stack pointer; stack’in en üstünü gösterir. x86’da ESP, x64’te RSP olarak adlandırılır.
- EBP/RBP: Base pointer; stack frame’in taban adresini tutar, değişkenlere erişimde referans noktasıdır.
- Calling Convention: Fonksiyonlara argümanların nasıl aktarıldığını ve dönüş değerlerinin nasıl alındığını belirleyen kurallar bütünüdür.
- Push: Bir değeri stack’e ekler, stack pointer’ı aşağı kaydırır.
- Pop: Stack’in en üstündeki değeri alır, stack pointer’ı yukarı kaydırır.
Bu kavramların hepsi prologue ve epilogue işlemlerini anlamanın temelini oluşturur. Zira bu iki işlem, stack frame’i oluşturup kaldırmaktan ibarettir.
Prologue Nedir ?
Prologue, fonksiyonun başında çalışır ve stack üzerinde bir “frame” oluşturur. Bu frame, fonksiyonun yerel değişkenlerini ve kaydedilmesi gereken registerları saklamak için kullanılır. Bu işlem aşağıdaki resimde göreceğiniz gibi 3 aşamadan oluşur.

Şimdi ise bu 3 adımı teker teker inceleyim.
1. push ebp
Önce elimizdeki eski referans noktasını kaydediyoruz. Bulunduğumuz fonksiyon bittiği zaman artık fonksiyon içerisinde kullandığımız değerlerin stackte durması gereksiz olacağından dolayı daha frame açılmadan fonksiyon bitiminde geriye dönmesi gereken kısmı not ediyoruz.
2. mov ebp,esp
Burada ise aslında kuracağımız framein üst çerçevesini hazırlıyoruz. EBP’yi ESP’nin olduğu yere taşıyoruz. Yani diyoruz ki; ‘buradan itibaren bu fonksiyonun alanı başlıyor.’ Böylece bu fonksiyonun stack içerisindeki kendi çalışma alanı net bir şekilde belirlenmiş oluyor.
3. sub esp,0x10
Son olarak, bu fonksiyon ne kadar stackte depolama kullanmak isterse o kadar yer açıyoruz ve bu şekilde de frame alanının geri kalanı tamamlanmış oluyor. ESP’yi biraz aşağı indiriyoruz; yani stack’te biraz yer açıyoruz. Bu yer, fonksiyonun yerel değişkenleri için ayrılmış özel alan oluyor.
Özetle
Bu üç adım aslında stack frame oluşturma sürecidir. İlk komut eski EBP değerini saklayarak geri dönüş yolunu güvence altına alır. İkinci komut, yeni stack frame’in tabanını belirler ve erişimleri kolaylaştırır. Son adım ise yerel değişkenlerin saklanacağı kadar alan açar. Böylece fonksiyon kendi izole çalışma ortamına sahip olur ve başka fonksiyonların verilerini bozmaz.
Epilogue Nedir?
Epilogue, bir fonksiyonun sonunda çalışan ve prologue’un yaptığı işleri tersine çeviren koddur. Temel amacı, fonksiyonun stack üzerinde açtığı alanı temizlemek, eski düzeni geri getirmek ve çağıran koda güvenli bir şekilde dönmektir. Prologue, stack frame’i kurarken; epilogue stack frame’i kaldırır. Bu ikisi birlikte fonksiyonların güvenli ve düzenli çalışmasını sağlar.
Epilogue genellikle üç temel adımda gerçekleşir:

1. mov esp, ebp
Bu adım, fonksiyonun kullandığı stack alanını serbest bırakır. Stack pointer (ESP), fonksiyonun başında işaretlediği base pointer’a (EBP) geri getirilir. Böylece fonksiyonun geçici olarak kullandığı alan stack’e geri kazandırılmış olur.
2. pop ebp
Prologue sırasında stack’in en üstüne koyulan eski base pointer (EBP) şimdi geri yüklenir. Yani fonksiyon öncesi ortam, stack ve base pointer tam olarak eski haline gelir. Bu sayede fonksiyon sanki hiç çağrılmamış gibi bir izlenim bırakır.
3. ret
Son adımda CPU, instruction pointer’ı (EIP) stack’ten alır ve çağıran koda geri döner. Artık fonksiyonun işi tamamen bitmiştir ve program akışı kaldığı yerden devam eder.
Epilogue olmadan stack bozulur ve programın akışı karışır. Stack frame kaldırılmazsa ESP yanlış yerde kalır ve fonksiyonlar doğru şekilde geri dönemez.
Fonksiyonlar programların temel yapı taşlarıdır ve doğru çalışmaları için hem prologue hem de epilogue adımlarına ihtiyaç duyarlar. Prologue fonksiyonun ihtiyacı olan ortamı hazırlar, epilogue ise işi bitirip ortamı temizler ve eski düzene geri döner.
Epilogue’u anlamak, özellikle düşük seviyeli programlama ve Assembly ile çalışırken kritik bir noktadır. Çünkü stack’in doğru yönetilmesi, programın stabilitesi ve güvenliği için şarttır. Bu nedenle, bir fonksiyonun nasıl başladığını ve nasıl sonlandığını görmek, kodun iç işleyişini anlamak için büyük bir adımdır.
Bu metinde Tersine Mühendislik’te veya Assembly okurken kişilerin sıklıkla karşılaşacağı temel iki işlemden bahsettik. Konumuz buraya kadar. Bir sonraki metinde görüşmek üzere