본문 바로가기
코스웨어/13년 스마트컨트롤러

9월 23일 어셈블리 수업 정리(컨텍스트 보존하기) - 석주원

by 알 수 없는 사용자 2013. 9. 23.
728x90
반응형


LINUX 프로시져 호출 전 스택에 _EFL 변수의 시작 주소를 PUSH 해둔다.

_EFL변수의 주소를 스택에 저장해 둠으로써 C언어의 함수의 인수와 같이 사용할 수 있도록 한다.

이렇게 함수를 호출하는 측에서(caller) 인수를 처리하는 방식을 cdecl 방식이라고 하고,

그 반대로 호출받는 측에서 (callee) 인수를 처리하는 것을 stdcall 방식이라고 한다.


LINUX 프로시져에서 주의할 점은 EFL의 값이 ADD연산을 거칠 때 변한다는 점과

디버그 중일 때는 EFL의 8번째 비트 TF (Trap Flag)가 1로 변한다는 점이다.

그러므로 다른 레지스터의 값을 스택에 보존해주기에 앞서서 EFL 레지스터의 값부터 추출해주고,

8번째 비트인 TF의 값을 0으로 초기화 시키기 위해 AND 연산으로 마스킹해준다.

그리고 그 값을 스택에 넣어둔다.


각 레지스터의 값을 보존해 줄때 주의해야할 또 다른 레지스터는 ESP, EIP가 있는데

MAIN함수에서의 ESP는 아래 그림에서 보듯

현재 EBP에서 +12를 한 주소이지만, "PUSH EBP+12" 와 같은 니모닉은 어셈블리에서

허용되지 않으므로, EBP의 주소값을 EAX로 옮겨와 덧셈을 해주는 방식으로 해결한다.

MOV         EAX, EBP

ADD         EAX, 8

PUSH EAX


EIP의 경우는 LINUX 프로시져로 제어가 넘어오기전의 명령어를 가리키는 값이므로,

Return Address가 바로 main의 EIP값이다.

그러므로 EBP+4가 가리키는 값을 푸쉬해준다.


EFL레지스터의 값은 LINUX의 스택에 보존해 두었으므로,

EBP-4가 가리키는 값을 PUSH해준다.






728x90