2009-08-09 15 views
8

Je viens de commencer à bricoler avec ASM et je ne suis pas sûr si ma compréhension des appels de procédure est correcte.Comment fonctionnent les appels de procédure dans l'assembleur?

dire à un moment donné dans le code il y a un appel de procédure

call dword ptr[123] 

et la procédure se compose d'une seule commande, RET:

ret 0004 

quel serait l'effet de cet appel de procédure , et où la valeur de retour serait-elle stockée? J'ai lu quelque part qu'une valeur de retour de 2 octets serait stocké dans AX, mais quand je remplace l'appel de procédure par

mov AX, 0004 

(ainsi que les PON nécessaires) le programme se bloque.

Répondre

12

en assembleur x86 le paramètre au moyen de l'instruction ret:

RET immediate

Retour à la procédure d'appel et de la pop immédiate octets de la pile.

(citant Intel® 64 and IA-32 Architectures Software Developer's ManualsVol 2B)

Ainsi, lorsque vous tapez:

ret 0004 

Vous dire la CPU pour revenir à l'instruction immédiatement après la call, et pop 4 octets off la pile. C'est génial si vous poussé 4 octets sur la pile avant l'appel.

push eax 
call dword ptr[123] 

Notez que cela n'a rien à voir avec la valeur de retour. En fait, une procédure dans Assembly n'a aucun moyen de spécifier qu'une valeur est une valeur return. Tout cela est fait par convention. La plupart des compilateurs dont je suis conscient utiliseront EAX pour contenir la valeur de retour, mais cela est vrai uniquement parce que la fonction appelant attend le résultat.

donc votre code d'appel serait:

call dword ptr [123] 
mov dword ptr [result], eax 

et votre fonction qui renvoie la valeur 4 serait:

mov eax, 4 
ret 
+0

merci! la plupart des tutoriels que j'ai googlé simplement utilisé ret, et n'a pas expliqué l'opération ret immédiate. Je suis devenu plus confus quand l'assembleur LLVM avait apparemment une commande "ret ". – int3

+0

Y at-il une raison pour laquelle RET peut retourner à un endroit autre que l'appel? Je viens de créer une question et j'ai trouvé ceci dans les questions connexes – lisovaccaro

+0

oui, si vous avez manipulé l'adresse de retour que 'CALL' a poussé sur la pile. –

-1

Je ne pense pas que la valeur de retour est stockée dans le registre AX

+0

aucune idée où, alors? – int3

+0

@ int3: Cela dépend de la convention d'appel. Il n'y a rien d'automatique ici. La fonction appelante et la fonction appelée doivent s'entendre sur l'emplacement de la valeur de retour. –

1
// possibly there are arguments pushed here 
... 
call dword ptr[123] // push next OP code offset in the stack and jump to procedure 

// procedure 
... 
ret 0004 // pop offset, set EIP to that offset and decrease ESP by 4 

nous en outre diminuer la ESP si nous avions poussé des arguments dans la pile avant l'appel de la procédure.


S'il y a des arguments poussés, votre programme se bloque car vous ne les faites pas apparaître. Le décalage de retour pour la procédure en cours sera incorrect car il obtiendra une valeur de l'un des arguments poussés en tant que décalage.

2

Tout dépend du calling convention utilisé. Je ne vais pas répéter l'article Wikipedia ici, il suffit de lire la définition.

Dans le C calling convention, par exemple, la valeur de retour serait dans EAX/AX/AL. Votre single-instruction n'en a pas: c'est une fonction vide qui prend environ 4 octets de paramètres (éventuellement un seul int) qui ne fait rien. Comme il est du devoir de l'appelé de nettoyer la pile dans cette convention d'appel, ignorer de le faire et remplacer l'appel par un 'mov ax' ne fonctionne pas.

Aussi je soupçonne que vous pouvez bricoler avec l'assemblage 32 bits tout en lisant un document 16 bits. Ce n'est pas un gros problème, mais vous devez être conscient des différences.