http://yris.thoth.kr/?mid=blog&document_srl=291453 를 보면서 간단한 헬로월드 코드를 나름 정리해봤습니다.
#include <stdio.h>
int main()
{
printf("Hello World!n");
return 0;
}
push ebp // ebp 는 함수 호출시 그 순간의 esp 를 저장하고 있다가 함수가
// 리턴하기 직전에 다시 esp 에 값을 되돌려주어 스택이
// 깨지지 않도록 한다. <<- stack frame 기법
// push : 스택에 저장 명령
mov ebp,esp // ebp 에 esp(스택메모리주소를 가리킴) 를 저장
sub esp,0C0h // sub 는 캐리를 포함하지 않은 뺄셈
// Carry는 덧셈, 뺄셈, 곱셈, 나눗셈들에서 32bit (혹은 8bit)연산 도중에 그것을
// 초과할 경우 Carry가 발생한 것을 저장하기 위한 공간
// 0c0h : 사용 스택 크기 , 192 바이트를 잡음.
// 스택은 위에서 아래로 자라므로 sub(뺄셈) 임.
// ebx, esi, edi 사용 후 복원을 위해 스택에 저장
push ebx // ebx : ds 세그먼트안의 데이터(데이터세그먼트주소)를 가리키는 포인터
push esi // esi : 문자열 연산에 대한 소스 포인터, 메모리 복사에 사용
push edi // edi : 문자열 연산에 대한 목적지 포인터, 메모리 복사에 사용
lea edi,[ebp-0C0h] // lea : 메모리의 오프셋값을 레지스터로 로드하는 명령
// edi 에 ebp-0c0h 주소값 (스택이 더 자랄 경우 시작점) 저장
mov ecx,30h // ecx 에 30h 넣음. ecx 는 반복 카운터로 수행시마다 1씩 감소
mov eax,0CCCCCCCCh // eax 레지스터(보통 리턴값을 담음)을 0CCCCCCCCh로 초기화
rep stos dword ptr es:[edi] // rep : 이후에 나오는 명령을 cx가 0이 될때까지 반복
// stos : al 또는 ax 를 es:di 가 지시하는 메모리에 저장
// eax 의 값(0ccccccch) 을 edi 로 복사 30h 만큼 반복.
mov esi,esp // esi 에 스택메모리 주소를 담는다.
push offset string "Hello World!n" (41573Ch) // 헬로월드 문자열 오프셋을 푸시, 프린트함수의 인자로.
// char *buf = "Hello World!n" 같이 하고 buf를 넘기면
// 데이터 세그먼트의 문자열을 가리키는 주소를 변수 buf 에 mov 하고
// 이것을 넘김
call dword ptr [__imp__printf (4182BCh)] // 함수호출
add esp,4 // add : 캐리 없는 덧셈
// 함수 호출을 위해서 push 했던 데이터가 호출 후엔 더이상 필요가 없다. // pop 을 안하는 이유는 pop 이 add 에 비해 오버헤드가 크고
// 이경우 그냥 버리는 데이터 이기 때문.. 값이 필요하다면 pop 해야함.
// 함수를 실행을 위해 늘어난 스택을 보정하기 위해 add 를 하는 것임
// printf 는 cdecl 호출 규약을 따르므로 main 에서 스택을 정리함
cmp esi,esp // 위에서 esi 에 esp 를 담아 놨었음
// cmp : 두개의 오퍼랜드를 비교한다.
// esi 가 크면 SF 를 0으로 ebp 가 작으면 1로
// 같으면 ZF 를 1로 설정
call @ILT+310(__RTC_CheckEsp) (41113Bh) // 런타임 체크 호출, esp 유효성 확인
xor eax,eax // 0을 만드는 방법.
// mov eax, 0 은 5바이트나 먹어버림.
// 0을 만드는 방법에는 MOV r1,0 XOR r1,r1 SUB r1,r1 AND r1,0
// 들이 있음
pop edi
pop esi
pop ebx // 스택에 백업 떠놓은 edi , esi, ebx 레지스터값 복원
add esp,0C0h // esp 도 스택잡았던 오프셋만큼 더해서 복원
cmp ebp,esp // 함수 들가기전 스택 주소 저장했던 ebp 와
// 함수 탈출 시점에서 스택 주소 esp 비교
call @ILT+310(__RTC_CheckEsp) (41113Bh) // 런타임 체크 esp 유효성 확인
mov esp,ebp // ebp 를 esp 로 옮겨 스택 되돌림
pop ebp // ebp 를 꺼내어 이전으로 복원
ret // 리턴
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 커널 스터디 관련 Q&A 게시판 입니다. [5] | woos | 2016.04.09 | 2197 |
125 | 커널7차(x86) B 분들 메일 확인해보세요. [5] | 배병일 | 2010.05.02 | 2750 |
124 | [5월8일] 스터디 참석 여부 댓글로~^^ [3] | 나무꾼 | 2010.05.02 | 1955 |
123 | 5월 1일 스터디 내용 및, 진행방향 [2] | 최문규 | 2010.05.02 | 2981 |
122 | 스터디 존속 여부 [2] | 이재훈 | 2010.05.01 | 1959 |
121 | as86(1) - Linux man page 입니다. | 김민석 | 2010.04.30 | 36679 |
120 | as86 어셈으로 부팅 코드 관련 문서 입니다. | 김민석 | 2010.04.30 | 6114 |
119 | 컥; 저번에 이 문서도 빼먹었네요; | 최문규 | 2010.04.30 | 3459 |
118 | 어떻게 공부하셨나요?? [3] | 김이현 | 2010.04.30 | 2879 |
117 | 제임스몰리의 커널개발 튜토리얼 [1] | 배병일 | 2010.04.30 | 2833 |
116 | 도움이 될만한 사이트 | 배병일 | 2010.04.29 | 2851 |
115 | Windows NT 에서의 시스템 콜 [3] | 박한범 | 2010.04.27 | 2245 |
114 | 4월 24일 스터디 내용 [2] | 최문규 | 2010.04.26 | 2711 |
113 | OS커널의 구조와 원리 책 목차 [1] | 배병일 | 2010.04.26 | 3272 |
» | Hello World! [1] | 배병일 | 2010.04.21 | 5069 |
111 | g어셈블러, n어셈블러 관련 차이점 | 배병일 | 2010.04.20 | 3010 |
110 | 소스올리실때의 팁(?!) [2] | 최문규 | 2010.04.19 | 2863 |
109 | 커널 동기화 | 배병일 | 2010.04.19 | 3661 |
108 | IA-32 Register 기본 [1] | 배병일 | 2010.04.19 | 2701 |
107 | do_fork(), sys_clone()... 분석-수정본 [7] | 최문규 | 2010.04.18 | 10837 |
106 | 4월 17일 스터디 Issue list | 김두균 | 2010.04.18 | 2757 |
.
C++ 책들에 보면 인자로 구조체 넘길 경우 임시 객체 문제로 참조형태로 넘기라고 하는데,
디어셈한 코드를 보면
struct Cuss
{
double one;
double two;
char* pchr;
bool bFlag;
};
구조체를 인자로 받는
void GetVal(Cuss param); 과
void GetRef(Cuss ¶m); 이 있다고 할 때
GetVal(Cuss param) 은
sub esp,18h
mov eax,esp // sub , mov : 새로운 지역 스택으로 들어섰음.
mov ecx,dword ptr [css (417178h)] // 새로이 지역스택으로 복사하는 것을 볼 수 있음.
mov dword ptr [eax],ecx
mov edx,dword ptr [css+4 (41717Ch)]
mov dword ptr [eax+4],edx
mov ecx,dword ptr [css+8 (417180h)]
mov dword ptr [eax+8],ecx
mov edx,dword ptr [css+0Ch (417184h)]
mov dword ptr [eax+0Ch],edx
mov ecx,dword ptr [css+10h (417188h)]
mov dword ptr [eax+10h],ecx
mov edx,dword ptr [css+14h (41718Ch)]
mov dword ptr [eax+14h],edx
call GetValue (4111D1h)
add esp,18h
반면
GetRef 는 푸시하고 호출 끝.
push offset css (417178h)
call GetRef (4111CCh)
add esp,4
그리고 함수들에 __stdcall 지시자를 붙여주면
push offset css (417178h)
call GetRef (4111D6h)
로 스택 정리 부분이 main 에 없음.