¿Cuál es la estructura de un marco de pila y cómo se usa al llamar funciones en el ensamblaje?¿Qué es el marco de pila en el montaje?
Respuesta
El marco de pila x86-32 se crea mediante la ejecución de
function_start:
push ebp
mov ebp, esp
por lo que es accesible a través de ebp y se parece a
ebp+00 (current_frame) : prev_frame
ebp+04 : return_address
....
prev_frame : prev_prev_frame
prev_frame+04 : prev_return_address
Hay algunas ventajas de utilizar ebp para marcos de pila por el diseño de instrucciones de montaje , por lo tanto, se accede a los argumentos y a los lugareños con el registro de ebp.
Los compiladores (dependiendo del compilador) pueden usar el marco de la pila x86 para pasar parámetros (o indicadores a los parámetros) y devolver valores. Consulte this
Esto es diferente según el sistema operativo y el idioma utilizado. Debido a que no hay un formato general para la pila en ASM, lo único que la pila está haciendo en ASM es almacenar la dirección de retorno al hacer una subrutina de salto. Al ejecutar un retorno desde la subrutina, la dirección se recoge de la pila y se coloca en el contador de programa (ubicación de la memoria donde se va a realizar la siguiente instrucción de ejecución de la CPU)
Deberá consultar su documentación para el compilador que está utilizando.
Cada rutina utiliza una parte de la pila, y la llamamos un marco de pila. Aunque un programador ensamblador no está obligado a seguir el siguiente estilo, es muy recomendable como buena práctica.
El marco de la pila para cada rutina se divide en tres partes: parámetros de función, retroceder al marco anterior de la pila y variables locales.
Parte 1: Parámetros de la función
Esta parte del marco de pila de una rutina está configurado por la persona que llama. Usando la instrucción 'push', la persona que llama empuja los parámetros a la pila. Diferentes idiomas pueden presionar los parámetros en diferentes órdenes. C, si no recuerdo mal, los empuja de derecha a izquierda. Es decir, si usted está llamando ...
foo (a, b, c);
El llamante convertir esto en ...
push c
push b
push a
call foo
A medida que cada elemento se inserta en la pila, la pila crece hacia abajo. Es decir, el registro del puntero de la pila se reduce en cuatro (4) bytes (en modo de 32 bits), y el elemento se copia a la ubicación de la memoria apuntada por el registro del puntero de la pila. Tenga en cuenta que la instrucción 'call' implícitamente empujará la dirección de retorno en la pila. La limpieza de los parámetros se abordará en la parte 5.
Parte 2: StackFrame volver puntero
En este punto en el tiempo, la instrucción 'llamada' se ha emitido y ahora nos encontramos en el inicio de la llamada rutina. Si queremos acceder a nuestros parámetros, podemos acceder a ellos les gusta ...
[esp + 0] - return address
[esp + 4] - parameter 'a'
[esp + 8] - parameter 'b'
[esp + 12] - parameter 'c'
Sin embargo, esto puede ser torpe después de que dejan espacio para las variables locales y otras cosas. Entonces, usamos un registro de puntero de pila-base además del registro de puntero de pila.Sin embargo, queremos que el registro de la pila-puntero se configure en nuestro cuadro actual, y no en la función anterior. Por lo tanto, guardamos el anterior en la pila (que modifica los desplazamientos de los parámetros en la pila) y luego copiamos el registro de puntero de pila actual en el registro de puntero de pila-base.
push ebp ; save previous stackbase-pointer register
mov ebp, esp ; ebp = esp
Algunas veces puede ver esto hecho usando solo la instrucción 'ENTER'.
Parte 3: Talla de espacio para las variables locales
Las variables locales se almacenan en la pila. Dado que la pila crece hacia abajo, restamos algunos # de bytes (lo suficiente para guardar las variables locales):
sub esp, n_bytes ; n_bytes = number of bytes required for local variables
Parte 4: Poner todo junto. parámetros se accede mediante el registro stackbase triple ...
[ebp + 16] - parameter 'c'
[ebp + 12] - parameter 'b'
[ebp + 8] - parameter 'a'
[ebp + 4] - return address
[ebp + 0] - saved stackbase-pointer register
Las variables locales se accede mediante el registro de pila triple ...
[esp + (# - 4)] - top of local variables section
[esp + 0] - bottom of local variables section
Parte 5: StackFrame limpieza
Cuando salgamos de la rutina, el marco de pila debe limpiarse.
mov esp, ebp ; undo the carving of space for the local variables
pop ebp ; restore the previous stackbase-pointer register
A veces puede ver la instrucción 'DEJAR' reemplazando esas dos instrucciones.
Dependiendo del idioma que estaba usando, puede ver una de las dos formas de la instrucción 'RET'.
ret
ret <some #>
Cualquiera que sea elegido dependerá de la elección de la lengua (o estilo que desea seguir si escribir en ensamblador). El primer caso indica que la persona que llama es responsable de eliminar los parámetros de la pila (con el ejemplo de foo (a, b, c) lo hará a través de ... agregar esp, 12) y es la forma en que 'C' lo hace eso. El segundo caso indica que la instrucción de retorno mostrará # palabras (o # bytes, no puedo recordar cuál) de la pila cuando vuelva, eliminando así los parámetros de la pila. Si mal no recuerdo, este es el estilo utilizado por Pascal.
Es largo, pero espero que esto lo ayude a comprender mejor las estructuras de pila.
+1 - Muy buena respuesta. ¿Puedes recomendar algunos buenos libros para estas partes? –
Como rara vez leo libros de programación, no tengo ninguna recomendación. La información anterior es solo algunas de las cosas que recuerdo de la escuela hace décadas y cosas que he aprendido de la experimentación a lo largo de los años. – Sparky
@AbidRahmanK: Recomiendo este curso en Coursera https://www.coursera.org/course/hwswinterface Es un curso muy bueno y debe tomarse en serio. – jyz
- 1. ¿Qué es el marco PastryKit?
- 2. ¿Este marco de pila producido es el correcto?
- 3. ¿Qué es el desenrollado de la pila?
- 4. ¿Qué es el marco basado en interfaz?
- 5. ¿Cómo puedo simular el montaje?
- 6. ¿Qué es el contenedor en el marco de primavera?
- 7. Dibujando un marco de pila para el ensamblaje x86
- 8. ¿Dónde asigna CUDA el marco de pila para los granos?
- 9. ¿Cómo puedo examinar el marco de pila con GDB?
- 10. ¿Qué tan seguro es el marco de membresía de ASP.NET?
- 11. ¿Qué es una pila LAMP?
- 12. ¿Qué es el Marco de Extensibilidad Administrado (MEF)?
- 13. ¿Cómo hago el montaje en línea en el iPhone?
- 14. ¿Qué es la pila USB?
- 15. Cómo leer el montaje atributos
- 16. ¿Entrar y ABANDONAR en el montaje?
- 17. ¿por qué el marco web lift es escalable?
- 18. ¿Qué es el Marco CSLA y su uso?
- 19. Marco de pila completo para Java
- 20. Cómo detectar el valor de registros en un marco de pila de llamadas específico en windbg
- 21. ¿Qué es un desbordamiento de pila?
- 22. ¿Qué es la pila de Linux?
- 23. ¿Qué es un "error de doble pila"?
- 24. ¿Qué es exactamente un marco?
- 25. ¿Qué significa __forwarding__ en el seguimiento de pila?
- 26. ¿Es posible construir programáticamente un marco de pila Python y comenzar la ejecución en un punto arbitrario en el código?
- 27. ¿Cuál es el marco de registro más utilizado en C#?
- 28. ¿Qué significan los números en el seguimiento de pila?
- 29. copia sombra con el fin de no bloquear el montaje
- 30. Punteros de pila/base en el ensamblaje
http://stackoverflow.com/questions/2466170/drawing-a-stack-frame-for-x86-assembly/2466587#2466587 – NAVEED