2013-10-13 4 views
2

스택 메커니즘을 이해하려고합니다.Printf 인수가 스택에 푸시되지 않았습니다.

필자가 본 이론에서 함수가 호출되기 전에 인수가 스택에 푸시됩니다. 아래 코드에서의 printf를 호출 할 때

그러나 그들 중 누구도 밀어되지 않습니다 :

#include<stdio.h> 

int main(){ 

    char *s = " test string"; 
    printf("Print this: %s and this %s \n", s, s); 
    return 1; 
} 

은 내가 printf와 명령에 GDB에서 휴식을 넣고 한 3 개 인자의 스택 없음을 표시 할 때 스택에 밀어 넣습니다.

0x000000000040052c <+0>: push %rbp 
    0x000000000040052d <+1>: mov %rsp,%rbp 
    0x0000000000400530 <+4>: sub $0x10,%rsp 
    0x0000000000400534 <+8>: movq $0x400604,-0x8(%rbp) // variable pushed on the stack 
    0x000000000040053c <+16>: mov -0x8(%rbp),%rdx 
    0x0000000000400540 <+20>: mov -0x8(%rbp),%rax 
    0x0000000000400544 <+24>: mov %rax,%rsi 
    0x0000000000400547 <+27>: mov $0x400611,%edi 
    0x000000000040054c <+32>: mov $0x0,%eax 
    0x0000000000400551 <+37>: callq 0x400410 <[email protected]> 
    0x0000000000400556 <+42>: mov $0x1,%eax 
    0x000000000040055b <+47>: leaveq 

사실, 분해 코드에서 지금까지 나타나는 유일한 인수 때입니다 "이 인쇄 :

유일한 것은 스택에 푸시는 아래의 분해 코드에서 볼 수 있듯이 문자열 주소 s입니다 : % s의이 % s의 \ 없음 "%의 EDI에 넣고 ...

0x0000000000400547 <+27>: mov $0x400611,%edi 

그래서 제 질문은 : 왜 난 내 세 개의 인수 각각 3 푸시 지시가 표시되지 않는 건가요?

끝나면 uname -a : 3.8.0-31-일반적인 # 46 - 우분투 SMP (화) 9월 10일 세계 협정시 20시 03분 44초 2013 x86_64에의 x86_64에의 x86_64의 GNU/리눅스 64 비트에

답변

3

리눅스 - 64 시스템 x86-64 ABI (x86-64 Application Binary Interface)은 스택에서 인수를 푸시하지 않지만 일부 레지스터를 사용합니다 (이 calling convention은 약간 빠름).

많은 인수를 전달하면 -e.g. 그 중 12 명이 스택에 밀려납니다.

012-64 ABI 사양을 읽기 전에 우선 x86 calling conventions에서 위키 백을 읽으십시오.

printf과 같은 가변 기능의 경우 세부 사항은 조금 두려워합니다.

-1

컴파일러에 따라 포인터의 힙에 공백을 할당해야합니다.

는 PUSH 명령어가 표시되지 않는 이유는 부분적으로 할 수있는 임의 일 수있다 - 대신 char *s; 사용 char s[300]; 의 객실 그렇지 않으면 '의'는 단순히 스택을 가리키는 300 바이트를 할당합니다.

또한 printf에 필요한 포인터에 대해 PUSH 명령이 있어야하는 이유가 표시되지 않습니까? 어셈블러는 단순히 포인터의 값을 복사 (MOV)합니다.

+0

아니요, 인수가 전달되는 방법은 ABI의 문제입니다. 300 바이트 로컬 문자열을 선언하면 인수가 전달되는 방식이 아니라 첫 번째 명령어 (호출 프레임 설정)에만 영향을 미칩니다. –

+0

예, 당신이 바실레입니다. 필자는 printf 함수를 컴파일러 (ABI)에 더 집중해야했습니다. – Grantly

관련 문제