Pablo Ogilvie
En cuestión Compiladores: comprender el código ensamblador generado a partir de pequeños programas, el compilador usa dos variables locales sin ajustar el puntero de la pila.
no ajustar RSP para el uso de variables locales parece no interrumpir seguro por lo que el compilador parece depender de que el hardware cambie automáticamente a una pila del sistema cuando se produzcan interrupciones. De lo contrario, la primera interrupción que se presente empujaría el puntero de instrucción a la pila y sobrescribiría la variable local.
El código de esa pregunta es:
#include <stdio.h>
int main()
{
for(int i=0;i<10;i++){
int k=0;
}
}
El código ensamblador generado por ese compilador es:
00000000004004d6 <main>:
4004d6: 55 push rbp
4004d7: 48 89 e5 mov rbp,rsp
4004da: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0
4004e1: eb 0b jmp 4004ee <main+0x18>
4004e3: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0
4004ea: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1
4004ee: 83 7d f8 09 cmp DWORD PTR [rbp-0x8],0x9
4004f2: 7e ef jle 4004e3 <main+0xd>
4004f4: b8 00 00 00 00 mov eax,0x0
4004f9: 5d pop rbp
4004fa: c3 ret
Las variables locales son i
en [rbp-0x8]
y k
en [rbp-0x4]
.
¿Alguien puede arrojar luz sobre este problema de interrupción? ¿El hardware realmente cambia a una pila de sistema? ¿Cómo? ¿Estoy equivocado en mi entendimiento?
-
Gracias por tu respuesta. Lo explica todo. Entonces, ante una interrupción, el hardware empuja el puntero de instrucción 128 bytes hacia abajo en la pila y, por lo tanto, no sobrescribe las variables locales. Si la función requiere más de 128 bytes para almacenamiento local, debe ajustar el puntero de pila.
–Paul Ogilvie
25 de marzo de 2017 a las 8:34
-
@Paul: el kernel usa una pila separada, por lo que una interrupción privilegiada no tocará la pila del código de usuario.
– Bo Person
25 de marzo de 2017 a las 9:21
-
@Paul: no soy un experto en System V, pero creo que el sistema operativo no le permitirá instalar un controlador de interrupciones en el código de nivel de usuario. Así que nunca sucede.
– Bo Person
25 de marzo de 2017 a las 15:54
-
El código del kernel usa un ABI diferente donde no hay una zona roja. El ajuste de la pila en 128 bytes entra en juego durante el procesamiento de la señal. Cuando una señal “interrumpe” un proceso, el kernel ajusta el puntero de pila 128 bytes hacia abajo antes de ejecutar el controlador de señal.
– Ross Ridge
25 de marzo de 2017 a las 17:22
-
Modifiqué la respuesta para proporcionar la entrada Wiki actualizada (recientemente modifiqué el artículo Wiki). El anterior sugirió incorrectamente que la zona roja comienza debajo de la ubicación donde se almacena la dirección de retorno. Esto es inexacto: son los 128 bytes directamente debajo del valor actual de RSP . RSP puede o no estar apuntando a la dirección del remitente.
-Michael Petch
15 de abril de 2017 a las 19:14
Tal vez esto podría ser de su interés: stackoverflow.com/questions/28759227/…
– Apoya a Ucrania
25 de marzo de 2017 a las 7:26
Tenga en cuenta que las interrupciones HW no utilizan la pila de usuario. pilas de kernel hipocresía use una zona roja porque HW golpea de forma asíncrona. La pila de usuario solo se usa de forma asincrónica por cosas impulsadas por software: señal controladores y GDB llamando a una función para
print foo()
.– Peter Cordes
10 mayo 2020 a las 10:50