2015-02-05 61 views
0

我这个小C代码函数参数加载到寄存器在x64

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英特尔-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 

而且我注意到,它不使用堆栈在all.But首先值仍然需要加载到寄存器。所以我的问题是如何将参数加载到寄存器中?编译器会自动将参数加载到幕后的寄存器中吗?或其他事情发生?,因为没有将参数加载到寄存器的指令。


而且有点偏离主题。当您为编译原始源代码和机器代码之间的关系而增加优化时,会降低机器代码与源代码的关联度。默认情况下,如果你不指定GCC的优化标志,它不会优化代码。所以我试图在没有任何优化的情况下进行编译以获得源代码的预期结果,但是我得到的是机器代码的4-5倍,与源代码无关并且可以理解。但是当我应用1级优化时,代码看起来是可以理解的并且与源相关。但为什么?

+1

http://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI – EOF 2015-02-05 18:00:56

+0

不要一次提出两个问题。 – 2015-02-05 18:06:23

+0

@EOF是的我知道,前6个int或ptr参数被传递给寄存器。但我不明白如何?我的意思是寄存器不能填满空气中的数据,传递必须转化为一些机器代码,否则我失去了一些可怕的东西? – BsD 2015-02-05 18:06:28

回答

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是读取生成的程序集的最佳优化级别。也可以禁用帧指针,这可以将简单函数的开销降至最低。

+0

我写了主要测试程序{int a,b,c;解码(&a,&b,&c);}但是当我从objdump查看主机代码时,它所做的只是一些奇怪的指令retz ret而没有其他任何东西。你是什么意思? – BsD 2015-02-05 21:22:11

+1

@ simple16最有可能的是你的函数'decode'被内联到内部'main'。为了让你成为一个例子,我不得不删除'f'的实现,否则GCC会保持内联。如果这不能解释它,那么请提出一个新问题。 – 2015-02-05 21:39:23

+0

它是有道理的。我还注意到没有代码将本地变量加载到寄存器。编译器管理变量到寄存器的分配? – BsD 2015-02-06 13:11:46

相关问题