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?
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.
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.
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).