c - C 编译器是否保证两个八字节字段结构将在 SysV x64 上作为 INTEGER 传递?

标签 c assembly x86-64 abi sysv

特别是在 the SysV x86-64 ABI 的上下文中

如果我有一个只有两个字段的结构,例如:

typedef struct {
    void *foo;
    void *bar;
} foobar_t;

然后我将它传递给一个定义如下的函数:

foobar_t example_function(foobar_t example_param);

ABI 似乎说每个八字节字段都应作为 INTEGER 传递给函数,因此 rdi == foorsi == bar。类似地,返回时我们应该能够使用raxrdx,因为我们不需要rdi 中的内存指针。如果 example_function 简单定义为:

foobar_t example_function(foobar_t example_param) {
    return example_param;
}

一个有效的汇编实现,忽略序言和结语,将是:

example_function:
   mov rax, rdi
   mov rdx, rsi
   ret

可以想象,一个智力缺陷的编译器可以用 NO_CLASS 填充填充结构,并以某种方式使该程序集无效。我想知道是否在任何地方都写下了只有两个八字节字段的结构必须以这种方式处理。

我的问题的更大背景是我正在编写一个简单的 C11 任务切换器以供我自己学习。我主要基于 boost.context 和 this is exactly how boost passes two-field structs around .我想知道它是否在所有情况下都符合犹太洁食标准,或者 boost 是否有点作弊。

最佳答案

The ABI seems to say that each eightbyte field should be passed as INTEGER to the function, therefore rdi == foo and rsi == bar.

同意,对于可从多个编译单元访问的“全局”函数,参数结构被分成八字节的部分,第一个完全由 foo 填充,并且第二个完全由 bar 填充。它们被归类为 INTEGER,因此分别传入 %rdi 和 %rsi。

Similarly, when returning we should be able to use rax and rdx, since we don't need a memory pointer in rdi.

我不同意你关于 %rdi 的观点,但我同意返回值的成员在 %rax 和 %rdx 中返回。

A valid assembly implementation, ignoring prologue and epilogue, would be: [...]

同意。

Conceivably, a mentally-deficient compiler could fill the struct with NO_CLASS padding and make that assembly invalid somehow. I'm wondering if it's written down anywhere that a struct with only two eightbyte fields must be handled this way.

生成符合 SysV x86-64 ABI 代码的编译器将使用已经讨论过的寄存器来传递参数和返回返回值。这样的编译器当然没有义务完全按照您的描述实现函数体,但我没有看到您的担忧。是的,这些细节都写下来了。尽管您提供的具体案例未在您链接的 ABI 规范中明确描述,但上面讨论的所有行为都遵循该规范。这就是它的

生成行为不同的代码(针对全局函数)的编译器不是智力缺陷,而是不符合规范

The larger context to my question is that I'm writing a simple C11 task switcher for my own edification. I'm basing it largely on boost.context and this is exactly how boost passes two-field structs around. I want to know if it's kosher under all circumstances or if boost is cheating a little.

要确定 Boost 在您指向的代码中究竟做了什么,我需要进行比我准备花费的更多的分析。请注意,它不是您在example_function 中呈现的内容。但是有理由假设 Boost 至少在尝试根据 ABI 实现其函数调用。

关于c - C 编译器是否保证两个八字节字段结构将在 SysV x64 上作为 INTEGER 传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56483028/

相关文章:

C - 赋值从指针生成整数而不进行强制转换

C 交换二维数组中的元素

c - 删除视频的某些部分并重新制作关键帧(c++ + libav)

ios - 超频崩溃:return NSMutableString as NSString to use

程序集:文件描述符0或2用于读取用户输入

c - 尝试打印 double 时程序崩溃(但其他类型都可以)

c - 如何在 Windows 7 X64 SP1(x64 模式)下执行直接系统调用?

c - K&R函数声明

assembly - 二元炸弹第三阶段卡住了

c - 为什么clang用-O0产生效率低的asm(对于这个简单的 float 和)?