gpt4 book ai didi

c - 从程序集返回函数参数

转载 作者:太空宇宙 更新时间:2023-11-04 03:38:29 25 4
gpt4 key购买 nike

我在 Linux 上使用的是 AMD 64 位(我认为确切的架构并不重要),也是 64 位。用 gcc 编译成 elf64。

我从 C ABI 中看到整数参数通过通用寄存器传递给函数,我可以在代码的汇编端(被调用方)找到这些值。当我需要将结果从被调用方检索到调用方时,问题就出现了。

据我所知,RAX 获取第一个整数返回 值,我可以很容易地找到并使用那个值。第二个整数 返回 值通过 RDX 传递。这就是让我感到困惑的一点。

我还可以从 C ABI 中看到,RDX 是用于将第三个整数函数参数从调用方传递给被调用方的寄存器,但我的函数不使用第三个参数。

如何从我的函数中取出 RDX?我是否必须在函数中伪造一个参数才能在调用方引用它?


定点乘法 16.16:

从 C 调用看起来像:

typedef long int Fixedpoint;
Fixedpoint _FixedMul(Fixedpoint v1, Fixedpoint v2);

这是函数本身:

_FixedMul:
push bp
mov bp, sp
; entering the function EDI contains v1, ESI contains v2. So:
mov eax, edi ; eax = v1
imul dword esi ; eax = v1 * v2
; at this point EDX contains the higher part of the
; imul moltiplication, EAX the lower one.
add eax, 8000h ; round by adding 2^(-17)
adc edx, 0 ; whole part of result is in DX
shr eax, 16 ; put the fractional part in AX
pop bp
ret

来自 System V Application Binary InterfaceAMD64 Architecture Processor Supplement

Returning of Values algorithm:

The returning of values is done according to the following

  1. Classify the return type with the classification algorithm.
  2. If the type has class MEMORY, then the caller provides space for the return value and passes the address of this storage in %rdi as if it were the first argument to the function. In effect, this address becomes a “hidden” first ar- gument. This storage must not overlap any data visible to the callee through other names than this argument. On return %rax will contain the address that has been passed in by the caller in %rdi.
  3. If the class is INTEGER, the next available register of the sequence %rax, %rdx is used.

我希望我的意思更清楚。

PS:对于我在评论中造成的混淆,我们深表歉意。感谢您的提示。

最佳答案

AMD64 calling conventions (System V ABI)指定寄存器 RDX 的双重用途角色:它可以用来传递第三个参数(如果有的话)并且它可以用作第二个返回寄存器。 (参见图 3.4,第 21 页)

根据函数签名,它用于这些角色之一或不用于这些角色。

那么为什么有 2 个返回寄存器(即 RAX 和 RDX)?这允许函数在通用寄存器中返回最多 128 位的值 - 例如 __int128 或具有两个 8 字节字段的 struct

因此,要从 C 调用站点访问 RDX 寄存器,您只需调整函数的签名。这意味着代替

typedef long int Fixedpoint;
Fixedpoint _FixedMul(Fixedpoint v1, Fixedpoint v2);

声明为:

typedef long int Fixedpoint;
struct Fixedpoint_Pair { // when used as return value:
Fixedpoint fst; // - passed in RAX
Fixedpoint snd; // - passed in RDX
};
typedef struct Fixedpoint_Pair Fixedpoint_Pair;

Fixedpoint_Pair _FixedMul(Fixedpoint v1, Fixedpoint v2);

然后您可以在 C 代码中像这样访问 RDX:

Fixedpoint_Pair r = _FixedMul(a, b);
printf("RDX: %ld\n", r.snd);

引用资料:

  • 第 18,19 页:尤其是“聚合的分类(结构和数组)”,第 3 点:

If the size of the aggregate exceeds a single eightbyte, each is classified separately. Each eightbyte gets initialized to class NO_CLASS.

  • 第 22 页:“值(value)返回”,第 3 点:

If the class is INTEGER, the next available register of the sequence %rax, %rdx is used.

关于c - 从程序集返回函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30412676/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com