c - 我如何让 GCC 在 ah/bh/ch/dh 中放置一个字符?

标签 c gcc assembly x86 inline-assembly

假设我有一些需要特定 char 的内联程序集值在 ah , bh , ch , 或 dh .我怎么能告诉 GCC 把它放在那里?我没有看到相关的约束来做到这一点,但 GCC 手册说“如果你必须使用特定的寄存器,但你的机器约束没有提供足够的控制来选择你想要的特定寄存器,局部寄存器变量可能会提供一个解决方案",所以我试过:

void f(char x) {
    register char y __asm__("ah") = x;
    __asm__ __volatile__(
        "# my value ended up in %0" :: "a"(y)
    );
}

但它没有用。放在al反而:
        movb    4(%esp), %al
        # my value ended up in %al

x86 专用 Q约束看起来也接近我想要的,所以我尝试用它代替 a ,但结果相同。我还尝试使用更通用的 r .

有趣的是,当我使用 Clang 而不是 GCC 编译时(无论是使用 aQ 还是 r ),我确实得到了想要的结果:
        movb    4(%esp), %ah
        # my value ended up in %ah

我也试过 bh , ch , 和 dh代替 ah ,它们的每一个组合都会导致类似的结果。

我还尝试编译为 64 位而不是 32 位。在那里,GCC 仍然做着基本相同的错误:
        movl    %edi, %eax
        # my value ended up in %al

而 Clang 完全无法使用 Cannot encode high byte register in REX-prefixed instruction 进行编译除非我关闭优化(我打开了 LLVM bug #45865 左右),在这种情况下,它最终确实在正确的位置获得了值:
        movb    %dil, -1(%rsp)
        movb    -1(%rsp), %al
        movb    %al, -2(%rsp)
        movb    -2(%rsp), %ah
        # my value ended up in %ah

这是我应该报告的 GCC 中的错误,还是这不应该起作用并且只是在 Clang 中偶然起作用?如果是后者,有没有办法做我想做的事,或者我必须接受mov我自己从议会内部的其他地方把它放在那里?

32-bit Godbolt link . 64-bit Godbolt link .

最佳答案

显然,约束不允许选择嵌套寄存器,但您可以添加 h指令引用的修饰符。这在 Input Operands 的文档中有所提及.例如,

void f(char x) {
    char a;
    __asm__ __volatile__(
        "mov  %0, %h1" :: "X"(x), "a"(a)
    );
}

产生
f:
        xorl    %eax, %eax
        mov  4(%esp), %ah
        ret

我一直无法摆脱 xor清除 eax .我的猜测是代码生成器将“%h1”解释为设置了 8 位的 32 位字,而不是字符寄存器引用。例如,这个:
char f(char x) {
    char a;
    __asm__ __volatile__(
        "movb  %0, %h1" :: "X"(x), "a"(a)
    );
    return a;
}

... 编译为相同的代码,即使它返回 \0 ,不是很直观。

关于c - 我如何让 GCC 在 ah/bh/ch/dh 中放置一个字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61705478/

相关文章:

无法将字符串分配给数组

c++ - G++无法内联多态方法吗?

c - 带有 -Ofast 的 -DNDEBUG 比只有 -Ofast 慢

c - 汇编代码转C代码(添加指令问题)

C StdLib malloc 来自 (N)ASM

c++ - 将一个128位xmm寄存器的上下64位相加

c++ - 如何从正在运行的 VC++ 项目生成 DLL?

c - 与远程主机安全连接并检查

c++ - 在段错误之前缺少 cout

c - 在C程序中包含ffmpeg