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

나는 두 가지 의문이 있습니다 int i = 6를 들어조립 분석 문제

  1. 4 바이트가 필요하다, 왜 16 바이트 할당?
  2. 일부 함수는 스택을 사용하여 매개 변수를 전달하지만 (push xxx), printfesiedi을 사용하는 이유는 무엇입니까?

UPDATE

printfesiedi로부터 인출되지 보인다

(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. 는 INT 4 바이트 스택 프레임 포인터에 대한 8 바이트 (RBP 64이어야 비트 레지스터)와 반환 값 (스택에있는)에 대한 4 바이트.

  2. 나는 그것을 목격하지 못했다. (나는 oldschool : P이다.) 그러나 나는 값을 밀기위한 새로운 방법이라고 들었다. 스택에 직접 값을 저장하여 더 빠르다고 가정합니다.

+0

2 개 이상인 경우 함수는 분기가 두 개 이상인 경우 매개 변수를 얻는 위치를 어떻게 알 수 있습니까? – gdb

+0

1의 경우, 반환 주소가 '0x00000000004004ac'과 같이 8 바이트가 아니어야합니까? – gdb

+2

이 답변은 완전히 가짜입니다. * 프레임 포인터가 눌려진 후 스택 *에 16 바이트가 예약되어 있음을 알 수 있습니다. –

3

이유는 16 바이트

x86_64 ABI 스택이 16 바이트가 호출 명령 전에 정렬 될 것을 요구하기 때문에

의 printf는 ESI와 EDI

를 사용하는 이유

x86_64 ABI 지정 rdi, rsi, rdx, rcx, r8r9 레지스터에 (처음 6 개의) 정수 매개 변수가 전달되도록합니다.

+0

16 바이트 정렬 답변 주셔서 감사합니다.하지만 printf가 esi를 사용하고 edi가 응답하지 않는 것 같습니다. 함수가 분기가 두 개 이상인 경우 함수가 매개 변수를 얻는 위치를 어떻게 알 수 있습니까? – gdb

+0

그런 경우 분기가 먼저 수행되고 분기가 완료되면 매개 변수가 레지스터에로드됩니다. – Zimbabao

+0

@Zimbabao, sub_function이 매개 변수를 가져올 위치를 어떻게 알 수 있습니까? – gdb