在 ASM 中,c 编译器如何处理函数的结构返回值 [英] how c compiler treats a struct return value from a function, in ASM

查看:33
本文介绍了在 ASM 中,c 编译器如何处理函数的结构返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说到C函数的返回值,返回值存放在EAX寄存器中.假设我们谈论的是 32 位寄存器,欢迎使用整数,但是当我们返回这些类型时会发生什么:long longlong double,大于 32 位的 struct/union.

When speaking about C function's return value, the return value is stored in the EAX register. Suppose we are speaking about 32 bit register, integers are welcomed, but what happens when we return these types: long long, long double, a struct/union that is larger than 32bit.

推荐答案

在常见的 x86 调用约定中,适合两个寄存器的对象在 RDX:RAX 中返回.这是相同的寄存器对,它是 div 和 mul 指令以及 cdq/cqo 的隐式输入/输出(符号将 e/rax 扩展为 e/rdx).

In common x86 calling conventions, objects that fit in two registers are returned in RDX:RAX. This is the same register pair that is an implicit input/output for div and mul instructions, and for cdq / cqo (sign extend e/rax into e/rdx).

i386 Linux (SysV) 调用约定仅以这种方式返回 64 位整数.结构体(即使是由单个 int32_t 组成的结构体)使用隐藏参数方法而不是打包 eaxedx:eax.64 位 Linux 和 Microsoft 当前的标准 __vectorcall 都将结构体打包到 e/raxe/rdx:e/rax 中.

The i386 Linux (SysV) calling convention only returns 64bit integers that way. Structs (even a struct consisting of a single int32_t) use the hidden-parameter method instead of being packed eax or edx:eax. 64bit Linux, and Microsoft's current standard __vectorcall, both pack structs into e/rax, or e/rdx:e/rax.

许多调用约定通过添加一个隐藏的额外参数来处理更大的对象:一个指向用于存储返回值的空间的指针.请查阅您正在使用的特定 ABI 的 ABI 文档.(链接在 wiki).

Many calling conventions handle larger objects by adding a hidden extra parameter: a pointer to space for storing the return value. Consult the ABI documentation for the specific ABI you are using. (links at in the x86 wiki).

与注释中讨论的其他调用约定(例如隐式使用堆栈上的空间来存储返回的大对象)相比,传递指针可以保存副本,因为指针可以指向最终目标而不是临时空间堆栈.

Compared to other calling conventions discussed in comments (e.g. implicitly using space on the stack to store large objects being returned), passing a pointer can save a copy, because the pointer can point to the final destination instead of scratch space on the stack.

但通常只有当最终目的地在堆栈上时.被调用者可以假设返回值对象不是与/不为任何全局或任何可以通过指针访问的内存的对象.即调用者必须进行逃逸分析.请参阅什么阻止了将函数参数用作隐藏指针? - 在 C 抽象机中,不写入返回值对象直到函数返回的那一刻,在它完成读取任何内容之后.

But usually only if the final destination is on the stack. The callee can assume the return-value object is not the same object as / doesn't alias any global or any memory it can reach via pointers. i.e. the caller has to do escape analysis. See What prevents the usage of a function argument as hidden pointer? - In the C abstract machine, the return value object isn't written until the moment the function is returning, after it's done reading anything.

但它可以指向调用者堆栈帧中任何方便的位置,而不是相对于 RSP 的固定位置,这样可以避免复制.

But it can point to whatever convenient place in the caller's stack frame, not a fixed place relative to RSP, which may avoid a copy.

这篇关于在 ASM 中,c 编译器如何处理函数的结构返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆