2011-03-29 59 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