nemo의 이야기
어셈블리 함수 본문
함수 프롤로그(prologue)
- 이전 사용되던 ebp를 보전(저장) : saved ebp
- 함수에서 사용하는 메모리를 할당 : esp
ex)
push ebp => 새로운 기준
mov ebp, esp
sub esp, 4 => 4byte 공간 확보
함수 에필로그(epilogue)
- 할당된 메모리를 정리(회수) : esp 포이터를 높은 쪽으로 옮긴다.
- 저장해놨던 ebp를 복구
- 이전 명령어로 복귀
ex)
leave -> mov esp, ebp => 정리
pop ebp
ret -> pop eip => 다음 실행할 명령어 주소
함수를 이용한 어셈블리 프로그램 예제를 만들어 보자
C언어
void myprint()
{
printf("call myprint");
}
int main(){
myprint();
}
main:
push ebp
mov ebp, esp
call myprint jmp : 해당 함수로 가서 끝난다.
call: 함수를 실행하고 다시 되돌아온다.
- push eip
- jmp myprint
push print_msg2 => 복귀 주소
call printf
leave
ret
myprint:
push ebp
mov ebp, esp
push print_msg
call printf
leave leave가 있어야 되돌아간다.
ret
다음으로 사칙연산을 하는 함수 프로그램을 어셈블리어로 만들어 보자
int sum()
{
int a = 10;
int b = 20;
int sum = 0;
sum = a + b;
return sum;
}
-------------------------------------------
sum:
push ebp
mov ebp, esp
sub esp, 12
mov dword [ebp-4], 10
mov dword [ebp-8], 20
mov dword [ebp-12], 0
mov eax, [ebp-4]
add eax, [ebp-8]
mov [ebp-12], eax
mov eax, [ebp-12] => 공용 라이브러리 주소를 써도된다.
leave
ret
main:
push ebp
mov ebp, esp
call sum
push eax
push print_int
call printf
leave
ret
인자값 : 메모리, 레지스터, 스택을 사용할 수 있다.
int sum(int a, int b) a = 10, b = 20
{
int sum = 0;
sum = a + b;
return sum;
}
stack 구조를 살펴보면 ebp를 기준으로 인자, return 주소를 확인 할 수 있다.
saveed ebp
return address ebp + 4 leave(까지 메모리 회수)
a ebp +8 => sp포인터는 여기로 온다.
b ebp +12
sum:
push ebp
mov ebp, esp
sub esp, 4
mov eax, [ebp+8]
add eax, [ebp+12]
mov [ebp-4], eax
mov eax, [ebp-4]
leave
ret
main:
push ebp
mov ebp, esp
push 20 => b
push 10 => a
call sum
add esp, 8 => 인자를 사용한 만큼 더 해준다. (원상복구)
push eax
push print_int
call printf
leave
ret
'Information security > System security' 카테고리의 다른 글
시스템 콜(System call) (0) | 2017.08.16 |
---|---|
argc, argv에 이해 (0) | 2017.08.14 |
메모리 구조 (0) | 2017.08.11 |
어셈블리어 기초 (0) | 2017.08.10 |
실행 환경 구축 및 어셈블리 (0) | 2017.08.09 |