Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么参数的函数大小增加到单词大小?_C_Linux_Assembly_X86_Abi - Fatal编程技术网

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

C 为什么参数的函数大小增加到单词大小?,c,linux,assembly,x86,abi,C,Linux,Assembly,X86,Abi,我读取了i386和AMD64的SystemV ABI。他们告诉我们,参数必须四舍五入到单词大小的倍数。我不明白为什么 这是目前的情况。如果将4个字符参数传递给i386体系结构上的函数,则每个字符参数将占用16个字节和4个字节。为所有4个参数只分配4个字节不是更有效吗 对齐不是答案。因为在这两种情况下,16字节堆栈对齐可能需要4-12字节的填充。将4个字符放在单个寄存器或堆栈位置将需要创建并随后提取各个参数,这在指令方面非常昂贵。请注意,即使您谈论的是堆栈,内存访问也应该非常快,因为它很可能位于缓

我读取了i386和AMD64的SystemV ABI。他们告诉我们,参数必须四舍五入到单词大小的倍数。我不明白为什么

这是目前的情况。如果将4个字符参数传递给i386体系结构上的函数,则每个字符参数将占用16个字节和4个字节。为所有4个参数只分配4个字节不是更有效吗

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

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

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

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


如果你真的想节省那么多空间,你仍然可以自己使用一个4字节的参数来实现。

我认为最初的C作者着眼于可移植性和可维护性,而不是压缩每个字节和周期。并不是说C对资源不小心,而是做了适当的权衡

将每个参数提升到堆栈颗粒大小是有意义的,现在仍然如此。如果您不顾一切地想挤进去,您可以随时更换:

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


现代的C编译器对用户不是那么友好;或者更确切地说,他们唯一的朋友是一个名为benchmark的luser…

我认为最初的C作者着眼于可移植性和可维护性,而不是压缩每个字节和周期。并不是说C对资源不小心,而是做了适当的权衡

将每个参数提升到堆栈颗粒大小是有意义的,现在仍然如此。如果您不顾一切地想挤进去,您可以随时更换:

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

现代的C编译器对用户不是那么友好;或者更确切地说,他们唯一的朋友是一个名叫benchmark的luser

这不是更有效率吗

您必须始终说出要优化的内容:

执行速度快 小程序大小 更少的堆栈使用 更简单的编译器 ... 如果您想优化以减少堆栈使用,那么将字节传递给函数确实会更有效

但是,通常您希望优化以获得快速执行速度或较小的程序大小

与将参数移动到堆栈中的现代编译器不同,我知道90年代编写的大多数编译器将参数推送到堆栈中。如果编译器使用推送操作,将字节放入堆栈将相当复杂——这将使程序变慢和变长

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

这不是更有效率吗

您必须始终说出要优化的内容:

执行速度快 小程序大小 更少的堆栈使用 更简单的编译器 ... 如果您想优化以减少堆栈使用,那么将字节传递给函数确实会更有效

但是,通常您希望优化以获得快速执行速度或较小的程序大小

与将参数移动到堆栈中的现代编译器不同,我知道90年代编写的大多数编译器将参数推送到堆栈中。如果编译器使用推送操作,将字节放入堆栈将相当复杂——这将使程序变慢和变长


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

我不擅长组装,但我不明白为什么它会很昂贵。如果您传递了字数参数,您得到的参数如下:mov-8%ebp%ecx mov-12%ebp%edx等。。在我的示例中,它将类似于movb-8%ebp%ecx movb-9%ebp%edx等。。也许我不明白什么。@yevhen:大多数参数都是在寄存器中传递的。@请注意,调用约定实际上将4个字符打包到一个寄存器中,如果它们是结构类型参数的成员。@Yevhenglushko AFAIK movb需要一个字节大小的目的地,即这些指令不存在。@Yevhenglushko是的,这可以工作,但是请注意,它仍然是一个不对齐的访问,因此它很可能读取4个字节,并在引擎盖下进行一些按摩。我不知道确切的性能,请随意在最近的CPU中测量!我不擅长组装,但我不明白为什么它会很昂贵。如果您传递了字数参数,您得到的参数如下:mov-8%ebp%ecx mov-12%ebp%edx等。。在我的示例中,它将类似于movb-8%ebp%ecx movb-9%ebp%edx等。。也许我不明白什么。@yevhen:大多数人都不明白
uments在寄存器中传递。@请注意,调用约定实际上将4个字符打包到一个寄存器中,如果它们是结构类型参数的成员。@Yevhenglushko AFAIK movb需要一个字节大小的目的地,即这些指令不存在。@Yevhenglushko是的,这会起作用,但请注意它仍然是一个不对齐的访问,因此,它很可能读取4个字节,并在引擎盖下进行一些按摩。我不知道确切的性能,请随意在最近的CPU中测量!你不能打开一个字符。您可以弹出一个单词。堆栈args约定至少可能重复:您不能弹出字符。您可以弹出一个字。堆栈参数约定至少可能重复:要获取当前调用约定中的参数,您应该执行mov 0x8%ebp%ecx mov 0xc%ebp%ebx mov 0x10%ebp%edx mov 0x14%ebp%eax,但在我的示例中,它将是movsbl 0x8%ebp%ecx movsbl 0x9%ebp%ebx movsbl 0xa%ebp%edx movsbl 0xb%ebp%eax是否较慢?@Yevhenglushko读取参数:否。问题是写入参数。在20世纪80年代或90年代,当SystemV调用约定被开发出来时,大多数编译器使用push指令将参数放在堆栈上。并且不能推送8位值。要获取当前调用约定中的参数,应执行mov 0x8%ebp%ecx mov 0xc%ebp%ebx mov 0x10%ebp%edx mov 0x14%ebp%eax,但在我的示例中,它将是movsbl 0x8%ebp%ecx movsbl 0x9%ebp%ebx movsbl 0xa%ebp%edx movsbl 0xb%ebp%eax是否较慢?@Yevhenglushko读取参数:否。问题是写入参数。在20世纪80年代或90年代,当SystemV调用约定被开发出来时,大多数编译器使用push指令将参数放在堆栈上。并且不能推送8位值。