2009-09-08 13 views
31

nasıl kullanılacağını aşağıdaki asm kodu vardır:ret, ret RETF - Onlara

Okuduğum kadarıyla
; int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) 
[email protected] proc near 

var_8= dword ptr -8 
var_4= dword ptr -4 
hInstance= dword ptr 8 
hPrevInstance= dword ptr 0Ch 
lpCmdLine= dword ptr 10h 
nShowCmd= dword ptr 14h 

push ebp 
mov  ebp, esp 
sub  esp, 8 
mov  [ebp+var_4], 5 
mov  eax, [ebp+var_4] 
add  eax, 1 
mov  [ebp+var_8], eax 
xor  eax, eax 
mov  esp, ebp 
pop  ebp 
retn 10h 

sonra gönderici talimatı 3 tip vardır: ret, ret ve RETF, geri dönüşü anlamına gelen iade yakın ve geri dönmek. İsteğe bağlı argüman nBytes'e izin verir, sanırım tanımlı değişkenlerden gelen bayt sayısıdır. Ret yerine ne zaman ret veya retf kullanmalıyım? İsteğe bağlı parametre nBytes'i nasıl hesaplayabilirim?

cevap

23

Mnemonik ret N'de, N, yığındaki parametrelerin boyutudur. Bu durumda 4 DWORD için 4 * 4 = 16 (10h) 'dir.
Ancak bu, yalnızca arayan kişinin yığın temizlemesinden sorumlu olduğu çağrıları çağırmak için geçerlidir. CDecl sözleşmesi durumunda, arayanın yığın temizlemesinden sorumlu olması nedeniyle, ret herhangi bir rakam olmadan olmalıdır.

+0

Ah, bu nedenle N, N'de N, düşündüğüm gibi yerel değişkenleri değil, arayan tarafından iletilen itilmiş argümanların sayısını ifade eder. Bu mu? –

+1

Evet. İtilen argümanların sayısı. Yerliler mov esp, sonunda ebp komutu ile açılır – Max

50

Aslında yalnızca iki farklı getiri var, retn (dönüş yanında) ve retf (uzak dönüş). Ret'i kullandığınızda, assembler veya derleyici hangisinin gerekli olduğunu seçmek için yeterince akıllıdır. Yakın bir geri dönüş, mevcut kod segmentinin içine atlamaktır, uzak dönüş farklı bir kod segmentine atlamaktır. Windows'da yalnızca tek bir kod segmentine sahipsiniz ve bu nedenle sadece retn için bir anımsatıcı olmalıdır. Ayrılmış geri alma ve retf talimatları, bölümlere ayrılmış bellek modellerinin yaygın olduğu eski günlere bir geri dönüştür. Bugün çalışan neredeyse tüm 32 bit x86 sistemleri, düz, bölümlere ayrılmış olmayan bir bellek modeli kullanıyor.

Hiçbir argüman olmadan geri al, yığının önüne dönüş adresini girer ve atlar. Bazı çağrı kuralları (__stdcall gibi), callee işlevinin yığını temizlediğini belirtir. Bu durumda, bu parametreleri yığından çıkarmak için bayt sayısıyla ret çağırırlar. 16 bayt, winmain işlevinin parametreleridir. retn ve retf:

+0

Üzgünüz, bu son bölümü alamadım. Retn 'u kullanırken neyi temizlemeliyim? Bu 2 değişken + ebp (4 bayt)? Söylediğiniz gibi 8 + 4 = 12, ancak kod 16 gösterir. 4 byte'lar neler kaldı? –

+0

Üzgünüz, çağrı düzeninin __stdcall olduğunu unutun. Cevabımı güncelleyeceğim. – Michael

+0

Erosog fonksiyonunu 0ch ile değiştirirseniz, arama fonksiyonunda ebp içeriği yanlış olur. – Max

20

Aslında iki tür var. Üçüncü bir ret, montajcı tarafından ilk ikisinden birine kodlanmıştır.

Buradaki fark, retn (dönüş yanında) yalnızca yönerge işaretçisini (IP) açacaktır. retf (geri dönüş), hem yönlendirme işaretçisini (IP) hem de kod parçasını (CS) açacaktır.

İlgili konular