Regardez cela dans le contexte de appelant cette fonction. Le code qui le fait ressemble à quelque chose comme:
caller+...: push argN
caller+...: ...
caller+...: push arg0
caller+...: call func
-à-dire les arguments sont mis sur la pile dans cet ordre que, à l'entrée de func()
, la pile aura la mise en page suivante:
[esp+(N*4)] : argN
... : arg(N-1)...arg2
[esp+4 ] : arg1
[esp ] : <return address to caller()+...>
Ensuite, vous effectuez la séquence push %ebp; mov %esp, %ebp
, qui change%esp
(par -4) afin que votre mise en page est maintenant:
[ebp+4+(N*4)][esp+(N*4)] : argN
... : arg(N-1)...arg2
[ ebp+8 ][esp+8 ] : arg1
[ ebp+4 ][esp+4 ] : <return address to caller()+...>
[ ebp ][esp ] : <saved %ebp of caller>
Le code continue ensuite à pousser un peu plus de registres sur la pile - puisque cela augmente à chaque fois que %esp
est modifié par -4. En fin de compte (que vous n'avez pas montré dans votre démontage mais il sera là) vous aurez une instruction subl $..., %esp
. Qui est ce qui alloue de l'espace pour vos variables locales.La mise en page de la pile finale est quelque chose comme:
[ebp+4+(N*4)][ ] : argN
... : arg(N-1)...arg2
[ ebp+8 ][ ] : arg1
[ ebp+4 ][ ] : <return address to caller()+...>
[ ebp ][ ] : <saved %ebp of caller>
[ ebp-4 ][ ] : <saved %ebx of caller>
[ ebp-8 ][ ] : ...
... : region for local variables
[ ebp-?? ][ esp ] : end of stack for func()
Toute adresse entre [esp ... ebp-4]
est dans ce qu'on appelle le cadre de pile pour votre fonction, et il contient soit un registre enregistrée au nom de l'appelant (comme ebx
dans le cas du démontage montré par vous) ou des variables locales. Par conséquent, lorsque votre code affiche un accès à %ebp - XX
, il se trouve dans l'espace des variables locales, si vous voyez %ebp + YY
, il se trouve dans l'espace contenant les arguments de la fonction.
Et la raison pour laquelle ils le font, est que les arguments peuvent toujours être référencés par le même décalage de ebp. Vous ne pouvez pas utiliser esp à cette fin, car cette fonction peut nécessiter l'utilisation du pointeur de pile pour les instructions push/pop temporaires. –