Aquí está la tabla completa de registros y su uso de la documentación [Enlace PDF]:
r12
, r13
, r14
, r15
, rbx
, rsp
, rbp
son los registros guardados por la persona que llama:tienen un "Sí" en la columna "Conservados en las llamadas a funciones".
Enfoque experimental:desensamblar el código GCC
Principalmente por diversión, pero también como una verificación rápida de que entendiste bien el ABI.
Intentemos eliminar todos los registros con el ensamblado en línea para obligar a GCC a guardarlos y restaurarlos:
principal.c
#include <inttypes.h>
uint64_t inc(uint64_t i) {
__asm__ __volatile__(
""
: "+m" (i)
:
: "rax",
"rbx",
"rcx",
"rdx",
"rsi",
"rdi",
"rbp",
"rsp",
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
"ymm0",
"ymm1",
"ymm2",
"ymm3",
"ymm4",
"ymm5",
"ymm6",
"ymm7",
"ymm8",
"ymm9",
"ymm10",
"ymm11",
"ymm12",
"ymm13",
"ymm14",
"ymm15"
);
return i + 1;
}
int main(int argc, char **argv) {
(void)argv;
return inc(argc);
}
GitHub ascendente.
Compilar y desensamblar:
gcc -std=gnu99 -O3 -ggdb3 -Wall -Wextra -pedantic -o main.out main.c
objdump -d main.out
El desmontaje contiene:
00000000000011a0 <inc>:
11a0: 55 push %rbp
11a1: 48 89 e5 mov %rsp,%rbp
11a4: 41 57 push %r15
11a6: 41 56 push %r14
11a8: 41 55 push %r13
11aa: 41 54 push %r12
11ac: 53 push %rbx
11ad: 48 83 ec 08 sub $0x8,%rsp
11b1: 48 89 7d d0 mov %rdi,-0x30(%rbp)
11b5: 48 8b 45 d0 mov -0x30(%rbp),%rax
11b9: 48 8d 65 d8 lea -0x28(%rbp),%rsp
11bd: 5b pop %rbx
11be: 41 5c pop %r12
11c0: 48 83 c0 01 add $0x1,%rax
11c4: 41 5d pop %r13
11c6: 41 5e pop %r14
11c8: 41 5f pop %r15
11ca: 5d pop %rbp
11cb: c3 retq
11cc: 0f 1f 40 00 nopl 0x0(%rax)
y entonces vemos claramente que lo siguiente se presiona y se abre:
rbx
r12
r13
r14
r15
rbp
El único que falta en la especificación es rsp
, pero esperamos que la pila se restaure, por supuesto. Una lectura atenta del montaje confirma que se mantiene en este caso:
sub $0x8, %rsp
:asigna 8 bytes en la pila para guardar%rdi
en%rdi, -0x30(%rbp)
, que se realiza para el ensamblado en línea+m
restricciónlea -0x28(%rbp), %rsp
restaura%rsp
volver a antes delsub
, es decir, 5 pops después demov %rsp, %rbp
- hay 6 pulsaciones y 6 pops correspondientes
- ninguna otra instrucción toca
%rsp
Probado en Ubuntu 18.10, GCC 8.2.0.