为什么参数的函数大小增加到单词大小?

时间:2019-09-04 18:44:02

标签: c linux assembly x86 abi

我阅读了i386和AMD64的System V ABI。他们说参数必须四舍五入为单词大小的倍数。而且我不明白为什么。

这里是情况。如果将4个char参数传递给i386体系结构上的一个函数,它将占用16个字节(每个char参数4个字节)。像为局部变量分配所有4个参数一样,仅分配4个字节不是更有效吗?

对齐不是答案。因为在两种情况下对齐16个字节的堆栈都可能需要4-12个字节的填充。

3 个答案:

答案 0 :(得分:2)

将4个char放在单个寄存器(或堆栈位置)中将需要创建并随后提取各个参数,这在指令方面是昂贵的。请注意,即使您在谈论堆栈,内存访问也应该非常快,因为它很可能在缓存中。

如果您真的想节省那么多空间,您仍然可以使用一个4字节的参数自己完成操作。

答案 1 :(得分:2)

  

...效率更高吗?

您总是必须说出要优化的地方:

  • 快速执行速度
  • 程序小
  • 减少堆栈使用量
  • 更简单的编译器
  • ...

如果要优化以减少堆栈使用量,将字节传递给函数确实会更有效。

但是,通常您要针对快速执行速度或较小的程序大小进行优化。

与现代编译器(将mov用作堆栈的参数)不同,大多数1990年代编写的编译器我都知道push堆栈的参数。如果编译器使用push操作,则将字节放入堆栈会相当复杂-会使程序变慢和变长。

(请注意,我从未见过对参数执行pop操作。)

答案 2 :(得分:0)

我认为原始的C语言作者更注重可移植性和可维护性,而不是压缩每个字节和每个周期。并不是说C在资源上很粗心,而是做出了适当的权衡。

将每个参数提升为堆栈粒度是合理的,而且实际上仍然可行。如果您迫切希望将其插入,则可以随时替换:

int f(int a, int b, int c, int d) { ... }

使用

struct fparm { char a,b,c,d; }; int f(struct fparm a) { ... }

现代C编译器不是那么用户友好;或更确切地说,他们唯一的朋友是名为“基准”的luser。