2011-03-29 77 views
0
(gdb) l main 
1 #include <stdio.h> 
2 
3 int main(void) 
4 { 
5  int i = 6; 
6  printf("%d",sizeof(unsigned short)); 
7  return 0; 
8 } 
(gdb) disas main 
Dump of assembler code for function main: 
0x0000000000400498 <main+0>: push %rbp 
0x0000000000400499 <main+1>: mov %rsp,%rbp 
0x000000000040049c <main+4>: sub $0x10,%rsp 
0x00000000004004a0 <main+8>: movl $0x6,-0x4(%rbp) 
0x00000000004004a7 <main+15>: mov $0x2,%esi 
0x00000000004004ac <main+20>: mov $0x4005c8,%edi 
0x00000000004004b1 <main+25>: mov $0x0,%eax 
0x00000000004004b6 <main+30>: callq 0x400398 <[email protected]> 
0x00000000004004bb <main+35>: mov $0x0,%eax 
0x00000000004004c0 <main+40>: leaveq 
0x00000000004004c1 <main+41>: retq 

我有兩個疑惑:大會分析問題

  1. 對於int i = 6,只有4字節是必要的,爲什麼16字節分配呢?
  2. 一些函數使用棧傳遞參數(通過push xxx),但爲什麼printf使用esiedi來做到這一點?

UPDATE

似乎printf不從esiedi取:

(gdb) disas printf 
Dump of assembler code for function [email protected]: 
0x0000000000400398 <[email protected]+0>: jmpq *0x2004c2(%rip)  # 0x600860 <_GLOBAL_OFFSET_TABLE_+24> 
0x000000000040039e <[email protected]+6>: pushq $0x0 
0x00000000004003a3 <[email protected]+11>: jmpq 0x400388 

回答

1
  1. 它應該是4個字節整型,堆棧幀指針的8個字節(RBP 64位寄存器)和4個字節的返回值(堆棧)。

  2. 我沒有真正目睹它(我是oldschool:P),但我聽說這是一種推動價值的新方法。通過直接將值存儲到堆棧,它應該會更快。

+0

對於2,函數如果知道從哪裏得到參數,如果有多個分支? – gdb 2011-03-29 03:28:22

+0

對於1,返回地址不應該是8字節,比如「0x00000000004004ac」? – gdb 2011-03-29 03:30:02

+2

這個答案完全是假的。您可能會注意到,在* frame指針被壓入後,16個字節保留在堆棧*上。 – 2011-03-29 03:37:52

3

爲什麼16字節

因爲x86_64 ABI要求堆棧來的16字節的呼叫指令之前對準

爲什麼printf的使用ESI和EDI

由於x86_64 ABI具體說明(前6個)整數參數在rdi,rsi,rdx,rcx,r8r9寄存器中傳遞。

+0

感謝16字節對齊answer.But似乎爲什麼printf使用esi和edi沒有回答?如果函數知道從哪裏得到參數,如果有多個分支? – gdb 2011-03-29 03:50:21

+0

在這種情況下,分支將首先完成,一旦分支完成,參數被加載到寄存器.. – Zimbabao 2011-03-29 05:33:40

+0

@津巴布奧,我的意思是如何sub_function知道在哪裏獲取參數? – gdb 2011-03-29 05:48:47