我有这个小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 encode.c将其编译为目标文件,然后使用objdump -M intel -d encode.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级优化时,代码似乎可以理解并且与源代码相关。但为什么?
最佳答案
参数将加载到调用方中的寄存器中。例:
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
是读取生成的程序集的最佳优化级别。也可以禁用帧指针,从而将简单功能的开销降至最低。关于c - 函数参数加载到x64上的寄存器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28350773/