【发布时间】:2026-01-08 12:10:01
【问题描述】:
我在内联汇编中使用“shld”指令,由 g++ (7.3.0) 编译。 它会产生一些奇怪的结果。
在 Ubuntu 和 WSL 上试过。
unsigned long long hi, lo;
//some code goes here
//...
asm volatile (
"shld $0x3, %1, %0;\n"
: "=r"(hi)
: "r"(lo)
:
);
//I expect the asm produces this:
//hi = (hi << 3) | (lo >> 61);
//but the actual result is:
//hi = (lo << 3) | (lo >> 61);
//you can see the real assembly produced by gcc below.
我希望“hi”中的结果值是
(hi << 3) | (lo >> 61)
但实际结果是
(lo << 3) | (lo >> 61)
详情请见https://en.wikibooks.org/wiki/X86_Assembly/Shift_and_Rotate。
原来g++把我的代码翻译成这样:
6e6a: 48 8b 45 a0 mov -0x60(%rbp),%rax
6e6e: 48 0f a4 c0 03 shld $0x3,%rax,%rax
6e73: 48 89 45 98 mov %rax,-0x68(%rbp)
其中 -0x60(%rbp) 是“lo”,-0x68(%rbp) 是“hi”。
【问题讨论】:
-
因为我的代码会修改变量“hi”
-
是的,它解决了问题,但看起来很奇怪。
-
我可以在没有任何优化选项的情况下通过测试,但是当我打开优化器 ("-O3") 时,程序会产生不同的结果并且测试失败。
-
@rcgldr, "=r" 表示操作数只是一个输出。 “+r”用于表示既是输入又是输出的操作数。 “r”表示输入。
-
@PeterCordes - 已删除,稍后将删除。
标签: c++ c gcc assembly inline-assembly