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?
Ответы
Ответ 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).