函数参数加载到x64上的寄存器

时间:2015-02-05 17:53:11

标签: c gcc assembly operating-system cpu-architecture

我有这个小C代码

void decode(int *xp,int *yp,int *zp)
{
      int a,b,c;
      a=*yp;
      b=*zp;
      c=*xp;
      *yp=c;
      *zp=a;
      *xp=b;
}

然后我使用gcc -c -O1 decode.c将其编译为目标文件,然后使用objdump -M intel -d decode.o转储对象,其等效汇编代码为

mov ecx,DWORD PTR [rsi]
mov eax,DWORD PTR [rdx]
mov r8d,DWORD PTR [rdi]
mov DWORD PTR [rsi],r8d
mov DWORD PTR [rdx],ecx
mov DWORD PTR [rdi],eax
ret

我注意到它根本不使用堆栈。但首先仍然需要将值加载到寄存器中。所以我的问题是如何将参数加载到寄存器中?编译器是否自动将参数加载到幕后的寄存器中?或其他什么事情发生?因为没有指令可以将参数加载到寄存器中。


有点偏离主题。当您为了编译原始源代码和机器代码之间的关系而增加优化时,会产生很多困难,将机器代码与源代码联系起来。默认情况下,如果您没有为GCC指定优化标志,则不会优化代码。所以我尝试编译而没有任何优化来从源获得预期的结果,但我得到的是与源相关且可理解的4-5倍更大的机器代码。但是,当我应用1级优化时,代码似乎可以理解并与源相关。但为什么呢?

1 个答案:

答案 0 :(得分:0)

参数被加载到调用者的寄存器中。例如:

int a;
int b;

int f(int, int);

int g(void) {
  return f(a, b);
}

查看为g生成的代码:

$ gcc -O1 -S t.c
$ cat t.s
…
movl    b(%rip), %esi
movl    a(%rip), %edi
call    f

第二个问题:

  

所以我尝试编译时没有任何优化来从源获得预期的结果,但我得到的是与源相关的4-5倍大的机器代码并且可以理解。

这是因为未经优化的代码是愚蠢的。它是中间表示的直接转换,其中每个变量都存储在堆栈中,即使它不需要,每个转换都由显式操作表示,即使不需要一个,依此类推。 -O1是读取生成的程序集的最佳优化级别。也可以禁用帧指针,这可以将开销保持在最小的简单函数。