2 votes

Comprendre le concept de STDCALL vs CDECL avec le nettoyage EBP et ESP

Je pense avoir compris la différence entre STDCALL et CDECL mais je me demande si je peux trouver des éclaircissements dans ce code.

Je comprends que dans STDCALL, le CALLEE est responsable du nettoyage de la pile, et je comprends que dans CDECL, le CALLER est responsable du nettoyage de la pile.

Je comprends également que le "nettoyage de la pile" signifie essentiellement la réinitialisation du pointeur de la pile, mais je suppose que mon confusion intervient à cette ligne de code où la valeur de esp est déplacée dans ebp, le pointeur de base. Si cette fonction se produit, est-ce que c'est la même chose que de "nettoyer la pile" ? Ou est-ce qu'il faut que quelque chose se déplace spécifiquement dans ESP ?

Voici le code que j'ai sous les yeux

main PROC
    push 4
    push 5
    call sub_12
    push 5
    call sub_48
    add esp, 4
    INVOKE ExitProcess, 0
main endp

sub_12 PROC
    push ebp
    mov ebp, esp
    mov eax, 10
    mul DWORD PTR [ebp+12]
    pop ebp
    ret 8
sub_12 endp

sub_48 PROC
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    mul DWORD PTR [ebp+8]
    pop ebp
    ret
sub_48 endp

Ma réponse initiale est que sub_12 et sub_48 sont toutes deux CDECL car l'appelant est responsable du nettoyage de la pile. Mais maintenant je continue à regarder les instructions [mov ebp, esp] et je me demande si ce n'est pas en fait un exemple de STDCALL.

Quelqu'un a-t-il des conseils à me donner ou une information supplémentaire qui pourrait me faire défaut ?

1voto

paulsm4 Points 39422

Voici une bonne discussion sur CDECL vs. STDCALL :

Quelle que soit la convention d'appel, le destinataire de l'appel enregistre généralement le pointeur de pile actuel dans le pointeur de trame (EBP) afin de pouvoir pousser et tirer des variables locales vers/depuis la pile à volonté.

Quand il est prêt à revenir, l'appelant MUST puis restaurer le pointeur de pile (ESP) pour que le "retour" réussisse.

Q : Est-ce que ça a du sens ? Cela répond-il à votre question ?

INFORMATIONS COMPLÉMENTAIRES :

Il y a deux problèmes : 1) l'appel de la sous-routine (cette partie est "stdcall" contre "cdecl" (entre autres - ce ne sont pas les deux seules options), et 2) le retour de la sous-routine.

La principale différence entre la CDECL et la STDCALL réside dans le fait de savoir qui est responsable du nettoyage de la pile pour les variables locales lors du "retour".

L'appelant TOUJOURS restaure le pointeur de pile. C'est la seule façon dont "return" peut fonctionner correctement.

Pour STDCALL, le demandeur AUSSI efface la pile de ses propres variables locales.

Grosso modo :

  • STDCALL peut utiliser un peu moins d'espace, parce que le "code de nettoyage" ne se trouve qu'à un seul endroit : dans l'appelant. Pour les appels CDECL, le nettoyage doit être répété partout où la sous-routine est appelée. Votre exemple sub_12 est "STDCALL".

  • CDECL est plus souple : il permet de passer un nombre variable de paramètres dans la sous-routine. Votre exemple de sub_48 est "CDECL".

J'espère que ça aidera...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X