“shld”指令产生了奇怪的价值

问题描述 投票:1回答:1

我在内联汇编中使用“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'。

c++ c gcc assembly inline-assembly
1个回答
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相同,这似乎没用,除了它使该寄存器既是输入又是输出。

© www.soinside.com 2019 - 2024. All rights reserved.