2012-06-24 6 views
8

메모리와 스택의 작동 방식을 이해하기 위해 gcc -S으로 놀고 있습니다. 이 연극을하는 동안 나는 분명하지 않은 몇 가지 점을 발견했다. 이유를 이해하도록 도와 주시겠습니까?어셈블러 코드를 만들 때 gcc가 왜 그렇게합니까?

  1. 언제 함수를 호출하는 대신 pushmovesp 사용하는라는 하나의 인수를 설정합니다. push을 사용하지 않는 이점은 무엇입니까?

  2. 스택 위치 인수와 함께 작동하는 함수는 ebp + (N + offset) (N은 반송 주소 용으로 예약 된 크기 임)으로 가리 킵니다. 나는 더 이해할 수있는 esp - offset을 볼 것으로 예상한다. ebp을 어디서나 사용하는 이유는 무엇입니까? 나는이 사람들이 평등하지만 어쨌든 알고 있습니까?

  3. main의 처음에이 마법은 무엇입니까? 왜 이런 방식으로 esp을 초기화해야합니까?

    and esp,0xfffffff0 
    

감사

,

+3

이것은 세 가지 질문 일 수 있습니다. 어쨌든, 세 번째 포인트에 대한 대답은 스택 정렬입니다. – Mysticial

답변

7

난 당신이 때문에 인수가 레지스터에 전달되는 64 비트 환경에서 32 비트 환경에서 작업하는 가정합니다.

질문 1

아마 여기서 부동 소수점 인수를 전달 중입니다. 32 비트 런타임의 push 명령어는 한 번에 4 바이트를 푸시하므로 값을 분리해야하므로 직접 푸시 할 수 없습니다. 때때로 esp에서 8을 빼는 것이 더 쉬우 며 8 바이트 쿼드 워드를 [esp]으로 이동하는 것이 더 쉽습니다.

질문 2

ebp 종종 32 비트 코드의 인덱스로 스택 프레임에 대해 매개 변수 및 주민 사용된다. 이렇게하면 스택 포인터가 움직여도 프레임 내의 오프셋을 수정할 수 있습니다. 당신은 단지 esp와 스택 프레임의 내용을 액세스 예를 들어 지금

void f(int x) { 
    int a; 
    g(x, 5); 
} 

을 고려, 다음 a[esp]에있다, 반환 주소는 [esp+4]에있을 것이며 x[esp+8]에있을 것입니다. 이제 g을 호출하는 코드를 생성 해 보겠습니다. 먼저 5를 밀고 나서 x을 밀어야합니다. 하지만 5를 밀면 x의 오프셋이 esp에서 변경되었습니다. 이것이 ebp이 사용 된 이유입니다. 일반적으로 함수에 입력 할 때 이전 값인 ebp을 저장 한 다음 espebp에 복사합니다. 이제 ebp을 사용하여 스택 프레임 내용에 액세스 할 수 있습니다. 우리가 논증을 저울렀을 때 움직이지 않을 것입니다.

질문 3

and이 명령은 16 바이트 경계에 정렬, esp의 마지막 4 개 비트를 제로로. 스택이 아래로 자라기 때문에 이것은 안전하고 안전합니다.

+1

Q3 : 마지막 4 비트를 0으로 만듭니다. – hirschhornsalz

+0

오, 감사합니다, @drhirsch. 생각없이 타이핑. 무서운. 정말 고마워! 편집 됨. –

관련 문제