c - 为什么 GCC 在使用 int foo asm ("ebx") 将 var 固定到寄存器时放置空操作推送/弹出?

标签 c gcc assembly x86

我正在尝试编写代码以从寄存器中读取,这是我目前所拥有的:

unsigned int readEBX(void) {
    register unsigned int reg asm("ebx");
    return reg;
}

该函数似乎可以正常工作,但它会编译成一些奇怪的东西:

readEBX():
    mov  eax, ebx
    push ebx
    pop  ebx
    ret

为什么这个 push-then-pop ebx?这不是什么都不做吗?当我将 ebx 替换为另一个寄存器(例如 eaxecx)时,它会生成更清晰的代码(只是一个 retmov eax, ecx; ret 分别)。

查看此示例 Godbolt result .

最佳答案

由于您明确地告诉编译器您对寄存器感兴趣,因此他试图变得聪明。既然要观察寄存器,就不要告诉编译器,让他乱来。

这对我有用(模 mov 操作的顺序)

unsigned int readEBX(void) {
  register unsigned int ret __asm__("eax");
  __asm__ volatile("mov %%ebx, %0" : "=r"(ret));
  return ret;
}

它只是确保ret 使用不同的寄存器,所以没有冲突。

关于c - 为什么 GCC 在使用 int foo asm ("ebx") 将 var 固定到寄存器时放置空操作推送/弹出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33089689/

相关文章:

c - 使用 sscanf 读取字符串缓冲区

c - 为什么 GCC 的 __attribute__((...)) 语法使用双括号?

gcc - CMake:C 编译器无法编译简单的测试程序

assembly - 无法在 Windows 7 中运行 nasm 生成的可执行文件

arrays - 在 x86 程序集中声明数组

c++ - GCC 内联汇编错误 : block assembly operand not recognized

c++ - 输入整数的最快方法

c - 当父进程不是 root 时,有什么方法可以确定子进程被内核用 SIGKILL 杀死

c# - 嵌入单声道时如何从对象获取数组字段

python - 使用 pysandbox 限制功能 (RF)