Pregunta

He creado este código de ensamblaje simple y sin sentido (Y86) para ver si entiendo todo lo que sucede en la pila cuando se usan las instrucciones call, pushl, popl y ret.

Como dije, este código no tiene sentido, es solo para fines de prueba / aprendizaje. Sin embargo, todas las direcciones de memoria fueron calculadas correctamente (esperanzadoras) y no son aleatorias.

El código de ensamblaje es el siguiente:

     | .pos 0
0x00 |   irmovl Stack, %esp
0x06 |   rrmovl %esp, %ebp
0x08 |   irmovl $5, %eax
0x0E |   call func
0x13 |   halt
0x14 | func:
0x14 |   pushl %ebp
0x16 |   rrmovl %esp, %ebp
0x18 |   pushl %eax
0x1A |   popl %eax
0x1C |   popl %ebp
0x1E |   ret
     | .pos 50
0x32 | Stack: .long 0

Lo siguiente es lo mejor para dibujar una pila y explicar qué hace cada paso (instrucción) con la pila. Tenga en cuenta que usé SP y BP para referirme a% esp y% ebp respectivamente porque se usan mucho y hacen que sea más fácil de leer.

Lo que quiero saber es si entendí todo bien o si me perdí algo. Siéntase libre de copiar / pegar lo que desee y corregir algunos pasos en su respuesta.

También tenga en cuenta que mi comprensión de esto es muy importante, tengo un examen el lunes para el que necesito estar preparado y me gustaría la mejor respuesta que me puedan dar. Dependiendo de sus respuestas, podría (o no) tener algunas preguntas relacionadas que nos ocuparemos en la sección de comentarios.

- INSTRUCTION: irmovl Stack, %esp
- INSTRUCTION: rrmovl %esp, %ebp
  1) Point %esp (SP) and %ebp (BP) to Stack

     |  ...  |
0x2E |-------|
     |       |
0x32 |-------| <--- SP & BP

- INSTRUCTION: irmovl $5, %eax
  1) Sets %eax = 5

- INSTRUCTION: call func
  1) Decrements SP by 4 (0x32 -> 0x2E)
  2) Saves return address (0x13) in memory location pointed by SP (0x2E)
  3) Jumps to "func" memory address (0x14)

     |  ...  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: pushl %ebp
  1) Decrements SP by 4 (0x2E -> 0x2A)
  2) Saves BP value (0x32) in memory location pointed by SP (0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: rrmovl %esp, %ebp
  1) Sets BP = SP (0x32 -> 0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: pushl %eax
  1) Decrements SP by 4 (0x2A -> 0x26)
  2) Saves %eax value (5) in memory location pointed by SP (0x26)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------| <--- SP
     | 0x32  |
0x2A |-------| <--- BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %eax
  1) Saves value (5) in memory location pointed by SP (0x26) in %eax
  2) Increments SP by 4 (0x26 -> 0x2A)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %ebp
  1) Saves value (0x32) in memory location pointed by SP (0x2A) in %ebp
  2) Increments SP by 4 (0x2A -> 0x2E)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: ret
  1) Jumps to memory address (0x13) in memory location pointed by SP (0x2E)
  2) Increments SP by 4 (0x2E -> 0x32)
¿Fue útil?

Solución

Por lo que puedo decir, lo tienes todo bien.

Un punto menor que puedo hacer es que probablemente sea más intuitivo escribir las direcciones por encima del valor en esas direcciones. Es decir:

0x2E |-------|
     | 0x13  |
0x32 |-------|

La razón es que el rango de direcciones cubre el valor ( 0x2E , 0x2F , 0x30 , 0x31 ) va hacia la siguiente dirección 0x32 .

Por supuesto, es posible que desee utilizar la notación esperada por su profesor al hacer el examen.

Otros consejos

Lo entendiste bien.

Lo que está haciendo es ejercitar una llamada de función utilizando convenciones estándar de llamador-llamador, creando un marco para el llamante. Luego realiza un simple empuje y estallido de un registro antes de regresar a la persona que llama. Esto es totalmente correcto y su comprensión es correcta (consulte http: //y86tutoring.wordpress .com / 2012/10/31 / operating-stacks / para más detalles)

Todo se ve bien. La única sugerencia es que no necesita definir una palabra 0x0000 en la pila. Simplemente definir la etiqueta de la pila lo habría hecho.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top