GCC不在函数调用中保存/恢复保留寄存器

hay*_*sti 2 c assembly gcc gnu-assembler register-allocation

我在GCC有一个场景给我带来了问题.我得到的行为不是我期望的行为.总结一下这种情况,我提出了一些x86-64的新指令,它们是在硬件模拟器中实现的.为了测试这些指令,我正在使用现有的C源代码并使用十六进制对新指令进行手动编码.因为这些指令与现有的x86-64寄存器交互,所以我使用input/output/clobber列表来声明GCC的依赖关系.

发生的事情是,如果我调用一个函数,例如printf,则不会保存和恢复相关寄存器.

例如

register unsigned long r9  asm ("r9")  = 101;
printf("foo %s\n", "bar");
asm volatile (".byte 0x00, 0x00, 0x00, 0x00" : /* no output */ : "q" (r9) );
Run Code Online (Sandbox Code Playgroud)

101被分配给r9,内联汇编(本例中为假)依赖于r9.这在没有printf的情况下正确运行,但是当它存在时,GCC不会保存和恢复r9,并且在调用自定义指令时会有另一个值.

我想也许GCC可能秘密地将赋值更改为变量 r9,但是当我这样做时

asm volatile (".byte %0" : /* no output */ : "q" (r9) );
Run Code Online (Sandbox Code Playgroud)

看看汇编输出,确实使用的是%r9.

我正在使用gcc 4.4.5.您认为可能会发生什么?我认为GCC将始终在函数调用中保存和恢复寄存器.有什么方法可以强制执行吗?

谢谢!

编辑:顺便说一句,我正在编译这样的程序

gcc -static -m64 -mmmx -msse -msse2 -O0 test.c -o test
Run Code Online (Sandbox Code Playgroud)

APr*_*mer 7

ABI,第3.2.1节说:

寄存器%rbp,%rbx和%r12到%r15"属于"调用函数,并且需要被调用函数来保存它们的值.换句话说,被调用函数必须为其调用者保留这些寄存器的值.剩余寄存器"属于"被调用函数.如果调用函数想要在函数调用中保留这样的寄存器值,则它必须将值保存在其本地堆栈帧中.

所以你不应该期望函数调用保留除%rbp,%rbx和%r12到%r15之外的寄存器.