gcc2.9至5.3中的不同装配说明

gcc2.9至5.3中的不同装配说明,c,gcc,assembly,C,Gcc,Assembly,我有以下C代码: #include <stdio.h> void function(int a, int b, int c) { int buff_1[5]; int buff_2[10]; buff_1[0] = 6; buff_2[0] = 'A'; buff_2[1] = 'B'; } int main(void) { int i = 1; function(1,2,3); return 0; } 底层对象文件是使用gcc-5.3-O0-

我有以下C代码:

#include <stdio.h>

void function(int a, int b, int c) {
  int buff_1[5];
  int buff_2[10];

  buff_1[0] = 6;
  buff_2[0] = 'A';
  buff_2[1] = 'B';
}

int main(void) {
  int i = 1;
  function(1,2,3);
  return 0;
}
底层对象文件是使用
gcc-5.3-O0-c functions.c
创建的。 但是,如果我使用
objdump
创建汇编代码,我会得到以下说明:

movl $3, %edx
movl $2, %esi
movl $1, %edi
就我所理解的汇编(我对它很陌生)而言,第一个对我来说更有意义


这本书完全错了吗?或者是因为使用了gcc 2.9,图书输出已经过时了该图书对于64位x86已经过时了。每个维基百科的主题是:

系统V AMD64 ABI

在Solaris、Linux、FreeBSD、OS X和其他类似UNIX或兼容POSIX的操作系统上,遵循System V AMD64 ABI的调用约定。前六个整数或指针参数在寄存器RDI、RSI、RDX、RCX(Linux内核接口中的R10)、R8和R9中传递,而XMM0、XMM1、XMM2、XMM3、XMM4、XMM5、XMM6和XMM7用于某些浮点参数。与Microsoft x64调用约定一样,附加参数在堆栈上传递,返回值存储在RAX中。
由于传递32位值,gcc使用每个寄存器的下半部分,因此
%edi
%esi
%edx

gcc是否有特定的中间表示或字节码?第二个示例类似于特定于目标的程序集。也就是说,不是每个处理器都会有这些寄存器,它们是x86特定的(我可能错了,我通常不会处理低级的东西)。此外,可能是一个优化,并不是所有关闭“-O0”,构造函数省略是一个我知道的,但不是。可能相关:它只是一个不同的调用约定——在寄存器中而不是在堆栈中传递前N个参数。然而,使用这些登记册并不是我承认的惯例,也不是我的习惯。这是64位的电脑吗?尝试使用
-m32
进行编译,也许可以获得32位约定,我认为默认情况下是堆栈。它只是使用x86_64调用约定,使用寄存器RDI、RSI和RDX的下半部分(它们是x86_64调用约定中的前3个电阻)“这是一个重新发布:为什么它使用movl而不是push?”-否,不是。这个问题涉及GCC 3.x将参数推送到堆栈上的方法,即保留一些空间,然后写入该空间,而不是使用推指令。David是正确的:这是因为您正在编译64位代码,这是标准的64位Linux调用约定。尝试
-m32
获得32位代码,该代码看起来像你的书,或者至少像链接问题中的代码,这相当于你书中的代码(这部分是gcc 2.95与更现代的gcc)。该代码发生于1999年7月至2001年3月,非常陈旧。x86_64当时还处于婴儿期。请参阅,代码生成似乎是使用x86_64调用约定描述的,但不是使用寄存器的下半部分,就是错误地使用x86寄存器名。学习历史没有问题,但是如果你打算使用当前代码,你需要一个全新的参考。小补充:它实际上使用了整个寄存器(
%rdi
%rsi
,…)。移到32位GP寄存器中,零扩展到整个64位寄存器。这些指令是执行mov$3、%rdx等操作的有效方法。@MargaretBloom:Gotcha。我通常不在这个级别工作,所以我不知道所有的细微差别。如果您觉得有必要,请随意编辑答案。
movl $3, %edx
movl $2, %esi
movl $1, %edi