qq_花开花谢_0
实验方法:反汇编GCC代码主要是为了好玩,但也作为一个快速验证,你明白ABI是正确的。让我们尝试使用内联汇编来破坏所有寄存器以强制GCC保存和恢复它们:main.c中#include 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上游。编译和反汇编: gcc -std=gnu99 -O3 -ggdb3 -Wall -Wextra -pedantic -o main.out main.c objdump -d main.out反汇编包含:00000000000011a0 : 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)所以我们清楚地看到以下内容被推送和弹出:rbxr12r13r14r15rbp规范中唯一缺少的是rsp,但我们希望堆栈当然可以恢复。仔细阅读程序集确认在这种情况下维护它:sub $0x8, %rsp:分配堆栈8个字节以保存%rdi在%rdi, -0x30(%rbp),其被用于内联组件进行+m约束lea -0x28(%rbp), %rsp恢复%rsp到之前sub,即之后的5个流行音乐mov %rsp, %rbp有6个推送和6个相应的流行音乐没有其他指示触摸 %rsp在Ubuntu 18.10,GCC 8.2.0中测试。