Programming from the Ground Up을 읽고 있는데... 스택에 대해?
Programming from the Ground Up이라는 문서를 구해 책으로
만들어서 보고있습니다.
as 어셈에 대해서 설명이 잘 되어 있다고 해서~~~
그런데, 함수(스택) 호출에서 이해하기 힘든 부분이 있어서 이렇게 글을 올립니다.
다름이 아니라..
함수가 호출이 되면,
--- 서브함수 시작부분---
.type test, @function
test:
pushl %ebp
mov %esp, %ebp
스택에 아래와 같이 값들이 저장된다고 하던데...
Parameter #N <-------- N*4+4(%ebp)
...
Parameter 2 <--------- 12(%ebp) /* 전에 저장된 값 */
Parameter 1 <--------- 8(%ebp) /* 전에 저장된 값 */
Return Address <--------- 4(%ebp) <--- 함수 호출
Old %ebp <--------- (%esp) and (%ebp)
pushl %ebp을 왜 하는지 잘 모르겠네요. 왜 Old %ebp가 필요한지~~
또 mov %esp, %ebp 를 하기전에 %esp는 무슨 값을 가지고 있는지..
마지막으로 정말로 궁금한 것은~~
서브함수의 마지막 부분에
movl %ebp, %esp #restore the stack pointer
popl %ebp #restore the base pointer
ret
가 있는데, 주석에는 stack pointer와 base pointer를 제거하는 것이라고
했는데, 어떻게 해서 제거가 되는지..
제 생각으로는
%esp <= %ebp 이고 popl %ebp하면 %esp는 제거가 안되는$^@#$
아~~ 미치겠습니다..
어셈 초보라서 그런는데~~ 고수님들 부탁드립니다.
짧은 영어 실력에 변역을 하려니 통 무슨 말인지 모르겠고... 2일 동안 3페이지를 왔다갔다 하고있음..
위 내용을 자세히 좀 설명해주세요..
:cry:
ebp 레지스터는 base pointer로 함수 내에서 스택상에 저장된
ebp 레지스터는 base pointer로 함수 내에서 스택상에 저장된 값을 참조할 때 기준이 되는 포인터 입니다. 로컬 변수나 인자로 들어온 변수, 배열등을 스택에 저장해 놓고 그 값을 참조하고 싶을 때 ebp + 4, ebp -4 와 같은 식으로 참조를 합니다.
함수를 새로 호출하게 되면 새로운 기준점을 설정하고 이전의 기준점은 저장해야 합니다. 이전의 기준점을 저장해야 새로 호출된 함수를 종료하고 상위로 돌아갔을 때 다시 기준점을 찾을 수 있으니까요. 그래서 x86 어셈에서 새로이 함수 호출을 하게 되면 기존의 ebp 레지스터를 저장하고 esp 레지스터를 ebp 레지스터로 mov 함으로써 새로운 base를 설정하게 됩니다.
esp는 항상 스택의 최고점 ( 주소값은 제일 낮은 ) 을 가리키고 있습니다. 그 상황에서 esp보다 낮은 주소값에 있는 스택상의 데이터들은 전혀 의미가 없습니다. ( 정상적인 흐름에서 )
movl %ebp, %esp #restore the stack pointer
popl %ebp #restore the base pointer
이것은 leave로 대체할 수 있습니다. 처음에 esp를 ebp로 옮겼으니 다시 ebp를 esp로 옮기고 저장한 ebp를 스택에서 pop 해서 상위 함수의 기준점을 다시 설정합니다. 이로써 함수 호출하기 이전의 스택 레지스터들이 원래 값을 찾습니다.
정말로 감사합니다.
위 내용이 이젠 무슨 뜻인 줄 알겠습니다..
쉬운 것 같으면서도 어렵네요..~~~
감사~~
댓글 달기