Подтвердить что ты не робот

Ret, retn, retf - как их использовать

У меня есть следующий код asm:

; 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

Из того, что я прочитал, у вас есть 3 типа команды возврата: ret, retn и retf, что означает return, return near and return far. Они разрешают необязательный аргумент nBytes, что я думаю, это количество байтов, которые нужно поп, из определенных переменных. Когда следует использовать retn или retf вместо ret? Как рассчитать необязательный параметр nBytes?

4b9b3361

Ответ 1

В мнемонике ret N, N - размер параметров в стеке. В этом случае это 4 * 4 = 16 (10 часов) для 4 DWORDs.
Но это относится только к вызовам, когда вызывающий отвечает за очистку стека. В случае соглашения cdecl ret должен быть без каких-либо чисел, поскольку вызывающий отвечает за очистку стека.

Ответ 2

На самом деле есть только два разных результата: retn (near return) и retf (long return). Когда вы просто используете ret, ассемблер или компилятор достаточно умен, чтобы выбрать, какой из них необходим. Ближайшее возвращение - это переход в существующий сегмент кода, далекий возврат - переход к другому сегменту кода. В Windows у вас есть только один сегмент кода, и, таким образом, ret должен быть просто мнемоником для retn. Отдельные команды retn и retf - это возврат к более старым временам, когда сегментированные модели памяти были обычными. Практически все 32-разрядные системы x86, работающие сегодня, используют плоскую, несегментированную модель памяти.

Ret без аргумента выводит адрес возврата из стека и переходит к нему. Некоторые соглашения о вызовах (например, __stdcall) указывают, что функция вызываемого абонента очищает стек. В этом случае они вызывают ret с количеством байтов, чтобы вытащить эти параметры из стека. 16 байтов являются параметрами функции winmain.

Ответ 3

На самом деле два типа: retn и retf. Третий ret кодируется ассемблером в один из первых двух.

Отличие состоит в том, что retn (возврат рядом) выдает только указатель инструкции (IP). В то время как retf (возвращение далеко) появится как указатель инструкции (IP), так и сегмент кода (CS).