2016-06-26 1 views
2

, 나는 다음과 같은 C 코드 작성 :; :이 간단한 (디스 어셈블 된) C 프로그램에서 스택 포인터는 어떻게됩니까? 어셈블리 언어/컴퓨터 아키텍처에 대한 자세한 내용을 학습의 방법으로

; my_caller function 
push ebp 
mov ebp,esp 
sub esp,byte +0x18 
sub esp,byte +0xc 
push dword 0xbaba 
call dword 0x1e 
add esp,byte +0x10 
mov [ebp-0xc],eax 
mov eax,[ebp-0xc] 
leave 
ret 

; my_callee function 
push ebp 
mov ebp,esp 
mov eax,[ebp+0x8] 
pop ebp 
ret 

int my_caller() { 
    int a = my_callee(0xbaba); 
    return a; 
} 

int my_callee(int a) { 
    return a; 
} 

이 분해 다음에 (내 컴퓨터에 몇 가지 추가 의견) my_caller에서 esp

에 관한 치료 :

  1. 왜 우리 0x18으로 sub esp 다음에서 0xc; 왜 0x24의 하위 하나가 아닌가?
  2. my_callee에서 돌아온 후 add esp,byte 0x10의 요점은 무엇입니까? leave 명령어는 암시 적으로 mov esp,ebp으로이를 취소합니다.

감사합니다.

+5

최적화를 사용하지 않으 셨습니다. – Jester

+1

컴파일러는 * 좋은 * 코드를 생성하지만 최적화가 있거나없는 * 최상 * 코드를 생성 할 필요는 없습니다. 예를 들어 두 개의 연속적인'sub esp' 명령어가 두 가지 다른 이유로 생성 되었기 때문에 생성 될 수 있습니다. 표시되는 코드는 "스택 프레임"과 매개 변수 및 지역 변수를 관리하는 것입니다. "모든 언어는 어떻게 다른가?" 이것이 라이브러리를 호출하거나 단일 프로젝트에서 언어를 혼합하는 것이 까다로울 수있는 한 가지 이유입니다. –

+0

은 컴파일러 (및 해당 버전) 및 시작 프로그램의 명령 줄 옵션에 따라 다릅니다. 예를 들어, gcc를 사용하면 코드를 볼 때 완벽하게 이해할 수 있습니다. 한 가지 경우에는 한 가지 조정을하고 또 다른 이유는 훔치지 않는 옵티 마이저가 도달 할 수없는 조정 인 경우가 있습니다. 아니면 어떤 최적화 컴파일러를 사용하지 않고 심지어 엿보는 ... –

답변

2

컴파일러에서 컴파일 속도가 빠르고 좋은 코드를 만들지 말고 gdb과 같은 디버거에서 사용하기 쉬운 코드를 사용하기를 원했습니다. -O0 모드에서는 gcc가 동일한 함수의 다른 부분간에 많은 부분을 최적화하지 않으므로 호출 후 add esp, 0x10이 스택을 팝한 다음 leave을 별도로 나타냅니다.

-O0은 굉장히 시끄럽다 (상점/재충전으로 가득 찼음), 인간으로 읽는 것을 빨기도합니다.

int 인수가있는 함수를 살펴보고 int을 반환하는 것이 더 나을 것입니다. 함수에 __attribute__((noinline))을 사용하여 인라인으로 중지 할 수 있습니다.

예를 들어 Godbolt compiler explorer에서 간단한 기능을 살펴보십시오. 태그 위키를 참조하십시오.

관련 문제