我在由g ++(7.3.0)编译的内联汇编中使用“ shld”指令。 会产生一些奇怪的结果。
在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'。
答案 0 :(得分:5)
您需要指定hi
既是输入也是输出。像这样:
asm volatile (
"shld $0x3, %1, %0;\n"
: "=r"(hi)
: "r"(lo)
, "0"(hi)
:
);
产生以下汇编代码:
mov -0x10(%rbp),%rdx
mov -0x8(%rbp),%rax
shld $0x3,%rdx,%rax
mov %rax,-0x8(%rbp)
“ 0”表示此操作数(数字2)必须与操作数0相同,这似乎没有用,只是它使该寄存器既是输入又是输出。