2017. 10. 27. 20:01ㆍSystemHacking/Assembly
C언어 코드를 어셈블리코드로 표현하자
[ C언어 코드 ]
int sum( int a, int b ){ int sum = 0 ; sum = a + b ; return sum ; } int main(){ int a = 10; int b = 20; int ret = 0;
ret = sum(a,b); printf("Sum : %d\n",ret ); return 0 ; } |
[ 어셈블리 코드 ]
extern printf section .data prompt_hex: db '0x%08x',10,00 prompt_int: db '%d',10,00 prompt_sum: db 'Sum is : %d',10,00 section .text global main sum: push ebp mov ebp, esp ; function prologue sub esp, 4 ; 지역변수 공간 확보 , 스택공간을 활용안하니까 현재 함수에서는 없어도 된다 mov eax, dword [ebp+8] ; eax = 20 add eax, dword [ebp+12] ; eax = eax + 10 ; function epilogue leave ; mov esp, ebp 할당해줬던 공간 회수 ; pop ebp ebp <= saved ebp ret ; pop eip 다음 실행 할 명령어의 주소를 꺼내온다 ; sum 을 호출하기 전의 ebp를 얻고, 순서대로 명령어가 실행된다 main: push ebp mov ebp, esp sub esp, 12 ; function prologue 지역변수 공간을 12byte 확보한다 mov dword [ebp-4], 10 ; a = 10 mov dword [ebp-8], 20 ; b = 20 mov dword [ebp-12], 0 ; ret = 0 스택의 지역변수 공간에 변수들 저장한다 push dword [ebp-8] push dword [ebp-4] ; 저장해 두었던 변수들을 스택에 push, pop으로 변수들을 꺼내서 사용할거다 call sum ; push eip + jmp sum , 원래 다음 실행할 명령어의 주소를 push 하고, 이동한다 mov dword [ebp-12], eax ; ret = sum , eax레지스터에는 sum레이블에서 계산한 값이 들어있다 push dword [ebp-12] push prompt_sum call printf ; printf("sum is: %d \n",ret ); xor eax, eax ; return 0
; epilogue leave ; mov esp, ebp 할당했던 지역변수 공간을 회수한다 ; pop ebp 기존의 ebp위치로 돌아온다 ret
|
[ 스택 메모리 구조 ] - 그림을 참고해서 코드를 보면 이해하기 쉽다
스택 메모리 모습 | 어셈블리 코드 |
[ sum ] saved ebp |
[sum 함수] push ebp |
return address ( saved eip ) | [main 함수] call sum ( = push eip + jmp sum ) |
[ main ] 10 | [main 함수] push dword [ebp-4] |
[ main ] 20 |
[main 함수] push dword [ebp-8] |
[ main ] ebp-12 |
[main 함수] mov dword [ebp-12] ,20 |
[ main ] ebp-8 |
[main 함수] mov dword [ebp-8] ,10 |
[ main ] ebp-4 |
[main 함수] mov dword [ebp-4] ,0 |
[ main ] saved ebp |
[main 함수] push ebp |
# 스택 메모리는 함수가 실행될 때 변수가 저장될 공간을 확보해서 고정된 크기를 가지게 된다 ( function prologue sub esp,12 부분 )
# 스택 메모리는 4byte씩 메모리가 쌓이게 된다
# push 스택 메모리에 데이터를 집어 넣는다
# pop 스택 메모리에서 꺼내온다 ( pop ebx => esp가 가리키고 있는 스택 ( 즉, 제일 위에 있는 데이터 ) 을 가지고 와서 ebx에 저장한다 )
# leave와 ret은 함수가 끝나면 항상 있어야 하는 함수의 에필로그 부분이다
# 어셈블리에서는 함수라는 개념이 없다. 즉, sum( 인자1, 인자2 ) => x, 직접 코드를 작성하고 컴파일러가 그 코드를 읽도록 이동시켜야한다
[ leave 명령어 ]
mov esp, ebp ; sub esp,12 로 지역변수에게 할당했던 공간을 회수해준다
pop ebp ; 저장해두었던 함수 실행 전의 ebp(base pointer) 를 가져와 ebp를 원래상태로 돌려준다
[ ret 명령어 ]
; call 명령어를 사용할 때 push eip 되었던 스택을 가져오는 명령어이다
[ call 명령어 ]
push eip ; 다음 실행할 명령어를 스택에 넣어준다 .( 쉽게 말하면, 함수 호출 call 명령 바로 아래 코드 ! )
jmp [ 레이블 ] ; 실행시킬 함수의 주소로 이동한다
'SystemHacking > Assembly' 카테고리의 다른 글
[11] 어셈블리 argc, argv 이해하기 (0) | 2017.10.30 |
---|---|
[10] 어셈블리 스택메모리를 이용한 변수 저장 및 사용 (0) | 2017.10.27 |
프로세스의 메모리 구조 ( + ESP, EBP ) (0) | 2017.10.25 |
[8] 어셈블리 반복문 연습 (0) | 2017.10.24 |
[7] 어셈블리 분기문 ( if, switch ) +cmp, jmp (1) | 2017.10.23 |