문맥교환(컨텍스트 스위칭)을 연습해 보았다.
main.c
#include <stdio.h> |
monitor.asm
.386
.MODEL FLAT
PUBLIC _STST ; Store Status
PUBLIC _LDST ; Load Status
.CODE
_STST PROC NEAR32
PUSH EBP
MOV EBP, ESP
PUSHFD
AND DWORD PTR [EBP-4], 0FFFFFEFFh
MOV ESP, [EBP+8]
ADD ESP, 40
PUSHAD
ADD ESP, 16
;Old EBP, RA, 인자, Main과의 경계
MOV EAX, EBP
ADD EAX, 8
PUSH EAX ; 메인 ESP
PUSH [EBP] ; Old EBP
SUB ESP, 8
PUSH [EBP+4] ; EIP(Return Address)
PUSH [EBP-4] ; EFL
MOV ESP, EBP
POP EBP
RET
_STST ENDP
_LDST PROC NEAR32
MOV ESP, [ESP+4] ; ESP = &Context
POPFD ; EFL = Context.EFL
; 플래그 레지스터에 값을 넣음
POP EAX ; EAX = Context.EIP
; 예전 EIP를 EAX 저장
MOV EBX, ESP ; EBX = Current ESP
; 현재 ESP 백업
MOV ESP, [ESP+12] ; ESP = Old ESP
; 과거 ESP로 점프
PUSH EAX ; Save Old EIP
; 과거 ESP에 EAX를 푸쉬하여 RA덮어씀
MOV ESP, EBX ; ESP = Current ESP
; 백업해둔 ESP를 다시 복원
POPAD ; ESP를 제외한 모든 값을 복원
MOV ESP, [ESP-20] ; Old ESP값을 복원
SUB ESP, 4 ; ESP를 RA위로 올려주어야 한다(RET이 POP하기때문)
RET
_LDST ENDP
END
결과
실행 순서 |
|
1 |
CPU 정보 구조체 선언 및 초기화 |
2 |
구조체 내용 출력 |
3 |
구조체에 CPU 정보 저장 |
4 |
구조체 내용 출력 |
5 | 구조체에 저장된 정보를 CPU 레지스터에 넣음 (STST의 RA가 가르키는 곳, 즉 4로 되돌아감) |
6 (실행되지 않음) | Kernel Panic 출력 |
실제로는 STST가 수행된 직후 상황을 강제로 재구현하는 방식이다. 원래라면 LDST를 실행한 후 printf를 실행하여 Kernel Panic이 출력되며 종료되어야 하나, LDST로 CPU정보를 STST에서 저장한 값으로 바꾸어버렸기 때문에 무한루프를 돌게 된다.
pushad로 넣은 값을 읽어들일 때 popad를 쓸 수 있는데, popad는 ESP의 값을 쌩깐다는 점에 유의한다.(ESP의 위치는 이동하지만 값은 유지되어있다) POP은 ESP에서 이루어지는데 ESP가 도중에 변경되면 지장을 줄 수 있다는 문제때문인 듯 하다.
끝에 SUB ESP, 4를 해주는 이유는 RA의 위로 이동하여야 제대로 RET명령이 POP한 주소로 이동되는 방식으로 수행되기 때문이다.
'Programming > Assembly' 카테고리의 다른 글
[Assembly] C언어의 if 문, switch 문을 어셈블리로 분석해 보기 (2) | 2013.09.04 |
---|---|
[Assembly] 130828 수요일 어셈블리 (6) | 2013.08.28 |
[Assembly] 컴파일 (0) | 2013.08.27 |
PC Assembly Language(Paul A. Carter) - 머리말(Preface) (0) | 2013.08.20 |
[Assembly] C 코드를 어셈블리로 분석해 보기 (0) | 2013.08.20 |