c - GCC 不保存/恢复函数调用的保留寄存器

标签 c gcc assembly gnu-assembler register-allocation

我在 GCC 中遇到了一个问题。我得到的行为不是我期望的行为。总结一下情况,我提出了几个在硬件模拟器中实现的 x86-64 新指令。为了测试这些指令,我使用现有的 C 源代码并使用十六进制对新指令进行手动编码。因为这些指令与现有的 x86-64 寄存器交互,所以我使用输入/输出/破坏列表来声明 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 可能已经 secret 地改变了对变量 r9 的赋值,但是当我这样做的时候

asm volatile (".byte %0" : /* no output */ : "q" (r9) );

并查看汇编输出,它确实使用了 %r9。

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

谢谢!

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

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

最佳答案

ABI ,第 3.2.1 节说:

Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling function and the called function is required to preserve their values. In other words, a called function must preserve these registers’ values for its caller. Remaining registers “belong” to the called function. If a calling function wants to preserve such a register value across a function call, it must save the value in its local stack frame.

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

关于c - GCC 不保存/恢复函数调用的保留寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6863004/

相关文章:

assembly - ADD 可以同时设置进位和溢出标志吗?

ios - 在 macOS 中创建 C 定时器

c - 将标准输入中的空格分隔的数字读取到链接列表中

c++ - 如何编译适用于旧版 Linux 发行版的二进制文件?

创建进程 : No such file or directory

c - gcc 链接器错误 : version node not found for symbol

gdb - 带汇编程序的gdb:带进位标志的打印状态

assembly - 汇编中的跳转指令如何与多个进程一起工作?

c - 如何将新节点插入空列表?

c - "ar_ptr = arena_for_chunk(p);"是什么意思?