【问题标题】:Creating a C++ pre-increment operation with CLANG inline assembly使用 CLANG 内联汇编创建 C++ 预增量操作
【发布时间】:2019-11-20 16:10:20
【问题描述】:

我正在尝试使用内联汇编执行与 b = ++a; 等效的操作,但在执行代码后我的变量中出现了奇怪的值。我正在使用 clang++(g++ 兼容)来编译内联汇编。到目前为止,这是我得到的:

#include <iostream>

using std::endl;
using std::cout;

int main()
{
    uint64_t a = 0;
    uint64_t b = 0;

    asm volatile(
    "pushq %%rbp;"
    "movq %%rsp, %%rbp;"
    "movl $0, -4(%%rbp);"
    "movl $0, -8(%%rbp);"
    "addq $1, -4(%%rbp);"
    "mov -4(%%rbp), %%rax;"
    "mov %%rax, -8(%%rbp);"
    "mov -4(%%rbp), %0;"
    "mov -8(%%rbp), %1;"
    "movq %%rbp, %%rsp;"
    "popq %%rbp"
    :"=r" (a), "=r" (b)
    :
    :"%rax", "%rbp", "%rsp"
    );
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}

【问题讨论】:

  • 什么是clang (GCC)
  • 苹果 clang 版本 11.0.0 (clang-1100.0.33.12) 目标:x86_64-apple-darwin18.7.0
  • movl $0, -4(%%rbp) 只写入低 32 位,因此前 32 位是随机垃圾。此外,一个 64 位整数是 8 个字节。所以你想要-8(%rbp)-16(%rbp)。您的代码当然在其他方面被破坏了,例如覆盖包含函数的红色区域,无论如何都没有多大意义。
  • 谢谢,是的,它适用于 -8 和 -16,但我应该改变什么才可以?

标签: c++ x86 x86-64 inline-assembly clang++


【解决方案1】:

您的代码过于复杂,看来您可能已经查看了编译器从其他地方生成的代码来创建答案。

b=++a; 是做什么的?它首先递增a,然后将该值分配给b。在这样的表达式中,a 既用作输入又用作输出。读取a 的值,加1,保存并将结果复制到b。使用 GCC 的 extended inline assembly,您可以使用 constraint 上的 + modifiera 视为输入和输出操作数。 b 可以与仅输出操作数一起使用,在约束上使用 = 修饰符。 INC 指令可用于递增 aMOV 指令可用于复制该值 b

内联汇编可能看起来像:

#include <iostream>

using std::endl;
using std::cout;

int main()
{
    uint64_t a = 0;
    uint64_t b = 0;

    asm ("inc %0\n\t"
         "mov %0, %1"
         : "+r" (a), "=r" (b)
    );
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}

输出应该是:

a = 1, b = 1


注意:由于除了我们告诉编译器我们要修改的寄存器之外没有其他副作用,因此没有必要在asm 语句中使用volatile

【讨论】:

  • 谢谢,是的,这是正确的,但我在示例中修改的红色区域是什么?如何解决这个问题?
  • @oleg red zone 是当前 RSP 正下方的 128 个字节。您必须在使用堆栈之前从 RSP 中减去 128,并在完成后加回 128。一个例子在这里:stackoverflow.com/a/37503773/3857942
  • 如果您在内联汇编中以 64 位代码将数据放入堆栈,您只需要担心红色区域。红色区域在 32 位 Linux 中不存在。在我的示例中,我不使用堆栈,因此我不需要关心红色区域。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多