将 64 位 int 作为输出传递到 32 位内联 asm

Pass 64-bit int as output to 32-bit inline asm

本文关键字:asm 输出 int      更新时间:2023-10-16
#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++ 代码中,它只是一个变量。

我试图在内联汇编中复制它,但我不得不这样做:

#include <stdarg.h>
#include <stdint.h>
int64_t test_func(int n)
{
    return 9223372036854775805;
}

int main()
{
    int32_t rlow = 0, rhigh = 0;
    asm(
        "push $10n"
        "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 位整数然后移动位?

您需要 "A" 约束,它将 64 位值绑定到 eax/edx 寄存器对。 像这样:

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

应该做这个伎俩。