【问题标题】:Pass 64-bit int as output to 32-bit inline asm将 64 位 int 作为输出传递给 32 位内联 asm
【发布时间】:2015-01-06 06:39:05
【问题描述】:
#include <stdarg.h>
#include <stdint.h>

uint64_t test_func(int n)
{
    return 9223372036854775805;
}


int main()
{
    uint64_t r = test_func(10);

    return 0;
}

转换为:

test_func(int):
    push    ebp
    mov ebp, esp
    mov eax, -3
    mov edx, 2147483647
    pop ebp
    ret

main:
    push    ebp
    mov ebp, esp
    and esp, -8
    sub esp, 24
    mov DWORD PTR [esp], 10
    call    test_func(int)
    mov DWORD PTR [esp+16], eax
    mov DWORD PTR [esp+20], edx
    mov eax, 0
    leave
    ret

您可以看到它使用 2 个寄存器来存储该 64 位整数。但是,在 C/C++ 代码中,它只是一个变量。

我试图在 inline-assembly 中复制它,但我不得不这样做:

#include <stdarg.h>
#include <stdint.h>

int64_t test_func(int n)
{
    return 9223372036854775805;
}


int main()
{
    int32_t rlow = 0, rhigh = 0;

    asm(
        "push $10\n"
        "\tcall %P2"
        : "=a"(rlow), "=d"(rhigh)
    : "i"(&test_func) : "memory");

    return 0;
}

输出是:

test_func(int):
    push    ebp
    mov ebp, esp
    mov eax, -3
    mov edx, 2147483647
    pop ebp
    ret
main:
    push    ebp
    mov ebp, esp
    sub esp, 16
    mov DWORD PTR [ebp-8], 0
    mov DWORD PTR [ebp-4], 0
    push $10
    call test_func(int)
    mov DWORD PTR [ebp-8], eax
    mov DWORD PTR [ebp-4], edx
    mov eax, 0
    leave
    ret

现在您可以看到我必须手动将低位和高位位放入两个单独的整数中。然后我执行移位使其成为一个 64 位整数。

有没有一种方法可以自动将其放入单个 64 位整数中,而无需我提供两个 32 位整数然后移位?

【问题讨论】:

  • 看起来像 32 位编译器的输出。如果你使用 64 位编译器,它可能会直接使用 64 位寄存器。
  • gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html 查看 386 下的字母“A”。是的,那是你应该看的第一个地方......
  • 32 位代码不能使用 64 位寄存器。它必须在 32 位架构上可执行。这就是为什么它被称为 32 位代码。
  • 另外,没有“C/C++”。
  • 上面的代码是无效的C。那些头文件在C中不存在;至少不在那些名字下。

标签: c++ c gcc inline-assembly


【解决方案1】:

您需要"A" 约束,它将一个 64 位值绑定到 eax/edx 寄存器对。比如:

uint64_t r;
asm("push $10\n"
    "\tcall %P1"
    : "=A"(r) : "i"(&test_func) : "memory");

应该可以解决问题。

【讨论】:

  • 请链接到官方文档,因为人们似乎很难找到它:-(
  • Machine Constraints - 在页面中搜索“Intel 386”
猜你喜欢
  • 2014-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 2011-01-31
  • 2019-08-24
  • 2012-11-23
  • 2013-08-01
相关资源
最近更新 更多