2010-03-30 16 views
7

Esto es lo que veo por el desmonte de la declaración function(1,2,3);:¿Cómo se especifica la dirección de retorno en la pila?

movl $0x3,0x8(%esp) 
movl $0x2,0x4(%esp) 
movl $0x1,(%esp) 
call 0x4012d0 <_Z8functioniii> 

Parece que la dirección de ret no se empuja en la pila en absoluto, entonces, ¿cómo lo hace ret trabajo?

Respuesta

3

Depende de la ITB y la arquitectura, pero si la dirección de retorno no terminan en la pila que es un efecto secundario de la instrucción call que lo pone allí.

5

Idealmente, la declaración call debería encargarse de eso. La próxima ubicación del contador del programa se insertará en la pila. Cuando la función (sub rutina) que se llamó la completa, funciona y cuando encuentra una declaración de devolución, el control ahora va a la dirección que se insertó en la pila y se abrirá.

+1

'¿Cómo funciona acuerdo call' con él, entonces? Sólo quiero ver donde la dirección ret * * es especificado – Mask

+0

Tendrás dividido el método de llamada para codificar más el código hexadecimal. La hoja de trucos para el conjunto de instrucciones especificado para el procesador en particular lo revelaría. Por ejemplo, si toma el microprocesador 8085 más simple y la instrucción ADD X no mostrará el segundo valor (supongamos que S le gusta AGREGAR X, Y). En su lugar, agregará el valor X a algún registro reservado dentro del procesador, digamos H y almacenará el valor en H. El bit de desbordamiento debería haber alguno almacenado en otro registro. Así es como está diseñada la instrucción ADD. La instrucción CALL también tendrá reglas predefinidas similares. – bragboy

+5

. Parte del trabajo de la instrucción de llamada es insertar la dirección de retorno en la pila. La dirección de retorno es solo la dirección directamente después de los parámetros de la instrucción de llamada. Para ver cuál es la dirección de devolución en su ejemplo anterior, tendría que mirar la pila tan pronto como el programa entre en el procedimiento en 0x4012d0. –

4

En un procesador x86 (como por ejemplo el lenguaje ensamblador), la instrucción call empuja la dirección de retorno en la pila y transfiere el control a la función.

No todas las arquitecturas de procesador ponen la dirección de retorno en la pila; a menudo hay un conjunto de uno o más registros diseñados para contener direcciones de devolución. En los procesadores ARM, la instrucción BL coloca la dirección de retorno en un registro específico (LR, o el 'registro de enlace') y transfiere el control a la función. El procesador ia64 hace algo similar, excepto que hay varios registros posibles (b0 - b7) que pueden recibir la dirección de retorno y uno se especificará en la instrucción (siendo b0 el valor predeterminado).

1

llamada empuja el valor actual del registro PIR (dirección de retorno) a la pila + hace la llamada
ret aparece la dirección de retorno (que llamada empujó a) de la parte superior de la pila (RSP registrar puntos allí) y lo escribe en el registro RIP.

Ejemplo en un cuadro GNU/Linux: la función f llama a la función g y veamos el marco de g.

resolver el bajo

... < - RSP (stack pointer muestra la parte superior de la pila) registrará los puntos en esta dirección
VARs locales de g
puntero de base de f (valor RBP edad) < - RBP (puntero de base) se registra puntos en esta dirección
dirección ret de f (valor de RIP de edad) (esto es lo que la llamada (desde f) empujó, y lo que el ret (desde g) emergerá)
args que f llamaron g y no encajaron en los registros (creo que en Windows esto es diferente)
...

ALTA DIRECCIÓN

g liberará a los VARs locales (movq% RSP,% RBP)
g aparecerá la "vieja RBP" y lo almacenan en el registro de tales prácticas (pop% RBP)
g se ret, que modificará RIP con el valor que se almacena en el RSP apunta a

creo que sirve

Cuestiones relacionadas