为什么GCC在使用int foo asm("ebx")将var固定到寄存器时会发出无操作的push/pop?

Ale*_*ing 4 c x86 assembly gcc

我正在尝试编写代码来从寄存器中读取,这是我到目前为止所做的:

unsigned int readEBX(void) {
    register unsigned int reg asm("ebx");
    return reg;
}
Run Code Online (Sandbox Code Playgroud)

该函数似乎正在工作,但它编译成奇怪的东西:

readEBX():
    mov  eax, ebx
    push ebx
    pop  ebx
    ret
Run Code Online (Sandbox Code Playgroud)

为什么要推出那款pop-then-pop ebx?这不是什么都不做?当我替换ebx为另一个寄存器(说eaxecx),则它产生理智代码(只是一个retmov eax, ecx; ret分别地).

看这个例子Godbolt结果.

Jen*_*edt 6

由于您明确告诉编译器您对寄存器感兴趣,因此他试图变得聪明.既然你想观察寄存器,不要告诉编译器,所以他不能乱七八糟.

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

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

它只是确保ret使用不同的寄存器,因此没有冲突.