GCC未在函数调用上保存/恢复保留寄存器

GCC未在函数调用上保存/恢复保留寄存器,c,gcc,assembly,gnu-assembler,register-allocation,C,Gcc,Assembly,Gnu Assembler,Register Allocation,GCC中有一个场景会给我带来问题。我得到的行为不是我期望的行为。为了总结这种情况,我为x86-64提出了几个新的指令,这些指令在硬件模拟器中实现。为了测试这些指令,我使用现有的C源代码,并使用十六进制对新指令进行手工编码。因为这些指令与现有的x86-64寄存器交互,所以我使用输入/输出/clobber列表来声明GCC的依赖项 发生的情况是,如果我调用一个函数,例如printf,依赖寄存器不会被保存和恢复 比如说 register unsigned long r9 asm ("r9") = 1

GCC中有一个场景会给我带来问题。我得到的行为不是我期望的行为。为了总结这种情况,我为x86-64提出了几个新的指令,这些指令在硬件模拟器中实现。为了测试这些指令,我使用现有的C源代码,并使用十六进制对新指令进行手工编码。因为这些指令与现有的x86-64寄存器交互,所以我使用输入/输出/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) );
101被分配给r9,内联程序集(本例中为假)依赖于r9。在没有printf的情况下,它可以正常运行,但是当它存在时,GCC不会保存和恢复r9,并且在调用我的自定义指令时,另一个值已经存在

我想GCC可能已经秘密地更改了变量r9的赋值,但是当我这样做的时候

asm volatile (".byte %0" : /* no output */ : "q" (r9) );
看看程序集输出,它确实使用了%r9

我使用的是GCC4.4.5。你认为会发生什么?我认为GCC总是会在函数调用时保存和恢复寄存器。有什么办法可以强制执行吗

谢谢

编辑:顺便说一下,我是这样编译程序的

gcc -static -m64 -mmmx -msse -msse2 -O0 test.c -o test

gcc不会保存像这样的显式寄存器变量。基本上,您使用的寄存器表示法使变量成为寄存器的直接别名,假设您希望能够读回被调用方在寄存器中留下的值。如果您使用被叫方保存的寄存器而不是呼叫中断(被叫方保存的)寄存器,问题就会消失。

第3.2.1节说:

寄存器%rbp、%rbx和%r12到%r15“属于”调用函数和 调用的函数是 需要保存它们的值。换句话说,被调用的函数必须保留 这些寄存器为其调用者设置了值。其余寄存器“属于”被调用的寄存器 作用如果调用函数希望在整个 函数调用时,它必须将值保存在其本地堆栈帧中


因此,除了%rbp、%rbx和%r12到%r15之外,您不应该期望通过函数调用保留其他寄存器。

谢谢您的澄清,我不知道这一点。作为后续问题,是否有一种简单(一行)的方式要求在printf之前保存一组自定义寄存器,并在printf之后恢复?
unsigned long tmp=r9;printf(…);r9=tmp谢谢,我甚至不知道有呼叫者/被呼叫者保存的注册表!