web-dev-qa-db-fra.com

ret, retn, retf - comment les utiliser

J'ai le code asm suivant:

; int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
_wWinMain@16 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

D'après ce que j'ai lu, vous avez 3 types d'instructions de retour: ret, retn et retf, ce qui signifie retour, retour près et retour loin. Ils autorisent un argument facultatif nBytes, que je suppose que c'est le nombre d'octets à extraire, à partir des variables définies. Quand dois-je utiliser retn ou retf au lieu de ret? Comment puis-je calculer le paramètre facultatif, nBytes?

33
devoured elysium

Dans le mnémonique ret N, N est la taille des paramètres sur la pile. Dans ce cas, il s'agit de 4 * 4 = 16 (10h) pour 4 DWORD.
Mais cela ne s'applique qu'aux conventions d'appel lorsque l'appelé est responsable du nettoyage de la pile. En cas de convention cdecl, le ret doit être sans numéro, car l'appelant est responsable du nettoyage de la pile.

28
Max

Il n'y a en fait que deux retours différents, retn (retour proche) et retf (retour lointain). Lorsque vous utilisez simplement ret, l'assembleur ou le compilateur est suffisamment intelligent pour choisir celui qui est nécessaire. Un retour proche est un saut à l'intérieur du segment de code existant, un retour lointain est un saut à un segment de code différent. Sous Windows, vous n'avez qu'un seul segment de code, et donc ret ne devrait être qu'un mnémonique pour retn. Des instructions retn et retf distinctes sont un retour en arrière aux anciens jours où les modèles de mémoire segmentée étaient courants. Presque tous les systèmes x86 32 bits fonctionnant aujourd'hui utilisent un modèle de mémoire plat et non segmenté.

Ret sans argument sort l'adresse de retour de la pile et y saute. Certaines conventions d'appel (comme __stdcall) spécifient que la fonction appelée nettoie la pile. Dans ce cas, ils appellent ret avec un nombre d'octets pour extraire ces paramètres de la pile. Les 16 octets sont les paramètres de la fonction winmain.

60
Michael

Il s'agit en fait de deux types: retn et retf. Le troisième ret est codé par l'assembleur dans l'un des deux premiers.

La différence est que retn (retour près) fera apparaître le pointeur d'instruction (IP) uniquement. Alors que retf (retour loin) fera apparaître à la fois le pointeur d'instruction (IP) et le segment de code (CS).

23
Aziz