如果函数参数在 x86 的堆栈中分配,则通过 push/pop
分配至少 4 个字节。如果每个函数调用有许多大小小于 4 字节的参数,这会浪费内存。一个原因可能是 push and pop work on 4 bytes least ,但是为什么不直接对 esp
进行操作以节省堆栈空间,可以将 1 个字节中的 4 个参数打包到一个 4 个字节的内存中,如下所示?
sub esp, 4
mov byte ptr [esp], para1
mov byte ptr [esp+1], para2
mov byte ptr [esp+2], para3
mov byte ptr [esp+3], para4
call func
最佳答案
这种行为通常由应用程序二进制接口(interface) (ABI) 控制,而最常用的 x86 ABI(Win32 和 Sys V)只要求每个参数至少占用 4 个字节。这主要是因为如果数据没有正确对齐,大多数 x86 实现都会遭受性能损失。虽然您的示例不会“取消对齐”堆栈,但仅采用三个字节大小的参数的子例程会这样做。当然,可以在 ABI 中定义特殊规则来克服这一点,但这会使事情变得复杂而收效甚微。
还要记住,x86 ABI 是在 1990 年左右设计的。当时,指令的数量是衡量某段代码速度的一个很好的衡量标准。如果 para1-para4 位于寄存器中,则与四个推送相比,您的示例需要一个额外的指令,在最坏的情况下需要五个额外的指令,所有参数都必须从内存中加载(x86 支持直接推送内存位置)。
此外,在您的示例中,您可以在堆栈上节省 12 个字节以换取 14 个额外的代码字节:如果 para1-para4(例如 al-dl)位于寄存器中,而四次推送需要,您的代码序列需要 18 个字节的代码4字节。所以总的来说,只有在代码中有递归时,才能减少内存占用。
关于assembly - 为什么函数参数在 x86 上占用至少 4 个字节的堆栈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30679702/