작성
·
410
0
답변 1
1
레지스터는 종류가 엄청 많지 않을텐데, 만약 지역 변수가 100개라면 어떻게 관리가 될까? 이것을 Push와 Pop으로 관리하고 있을까?
지역 변수는 스택에 들어가니, 레지스터의 개수랑은 무관하며
데이터를 스택에 고이 간직하다가
연산이 필요한 상황이 생기면 스택에 접근하거나,
스택에 있는 데이터를 레지스터에 로드해서 사용합니다.
hp라는 애를 어셈블리에서는 모를텐데,
mov dword ptr [hp], 0 이라는 명령어가 이상해보일 수도 있습니다.
그리고 사실 이상한게 맞고, 엄밀히 말해 저건 '찐' 어셈블리 코드가 아닙니다.
단지 Visual Studio상에서 우리가 보기 편하라고 저렇게 보여준 것이죠.
실제 '찐' 어셈블리 코드는 다음과 같이 되어 있습니다.
mov dword ptr [ebp-12], 0
ebp를 기준으로 특정 오프셋을 빼서 접근하게 되어 있습니다.
따라서 int a, int b, int c... 형태로 지역변수 100개를 만든다면
mov dword ptr [ebp-12], 0
mov dword ptr [ebp-16], 0
mov dword ptr [ebp-20], 0
...
과 같은 형태로 되어 있겠죠 (세부적인 -수치는 컴파일러에 따라 다릅니다)
여기서 궁금한것은 따로 .data 영역이나 .bss 영역처럼 변수를 생성 해 준 것 같지 않은데, 어떻게 hp 를 특정 주소로 인식하여 계산을 처리하는 지 입니다.
스택 영역의 주소를 계산해서 처리해야 하는데,
여기서 문제는 함수 호출 순서에 따라 스택 주소는 계속 변합니다.
그렇다면 어떻게 특정 지역 변수의 영역을 특정할 수 있을까요?
답은 기준이 되는 ebp가 있기 때문에, 그것을 기준으로 +- 해서 접근하는 것입니다.
이는 함수 인자로 넘겨준 매개변수도 유사한 원리로 작동하는데
매개변수들을 접근할 때는 ebp+8과 같이 ebp 기준으로 윗쪽 주소로 접근하게 되고,
지역 변수들은 ebp-XX 주소에 위치해 있게 됩니다.
이렇게 하면 함수의 시작 프레임 기준이 되는 ebp만 고정이 되면,
나머지 매개변수/지역변수 들은 ebp+@로 고정된 주소에 접근이 되는 것이죠.
(따라서 ebp가 운항하는 배의 닻 같은 존재라고 보시면 됩니다)
마지막으로 변수를 100개 한다고 해도 일일히 push를 해줄 필요 없이
ebp와 esp 세팅만 끝내주면, 그 다음부턴 ebp+@로 바로 접근 가능합니다.
마찬가지로 함수 호출이 끝나도 일일히 지역 변수들을 소멸(?) 시킬 필요도 없이
ebp, esp만 이전 함수 기준으로 바꿔주면 호출이 끝난 함수의 지역 변수는 접근할 수 없게 됩니다.
이럴수가... Rookiss 님은 신입니다...
열심히 강의 수강하겠습니다 :)
감사합니다.