어셈블리 call & jmp 명령의 차이 / 스택 메모리를 이용한 인자 전달 / reverse.asm 지역변수 사용해서 표현하는 실습에 대해서 정리한다.
1. call & jmp 명령의 차이
- 해당 주소의 명령을 실행
- 해당 주소를 eip 레지스터에 저장 ( call 명령의 경우 )
차이점:
- jmp 명령어는 해당 주소를 바로 이동
- call 명령어는 스택에 데이터를 저장하고 이동( 복귀할 주소를 push 해서 스택에 저장 )
* eip 레지스터에는 다음에 실행할 명령어의 주소가 들어있다.
2. 스택 메모리를 이용한 인자 전달
- 함수는 프롤로그와 에필로그로 구분하기 때문에 main도 함수이므로 적용해줘야 한다.
[ 어셈블리 코드 - func.asm ]
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 ; prologue
mov esp, 4
mov eax, dword [ebp+8]
mov dword [ebp-4], eax
mov edx, dword [ebp+12]
add dword [ebp-4], edx ; sum = a+b;
mov eax, [ebp-4] ; return sum;
leave ; mov esp, ebp ; pop ebp
ret ; pop eip ; epilogue
main:
push ebp
mov ebp, esp ; prologue
sub esp, 12
mov dword [ebp-4], 10 ; int a = 10;
mov dword [ebp-8], 20 ; int b = 20;
mov dword [ebp-12], 0 ; int sum = 0;
push dword [ebp-8]
push dword [ebp-4]
call sum ; push eip ; jmp addr
add esp, 8
mov [ebp-12], eax ; ret = sum(a,b);
push dword [ebp-12]
push prompt_sum
call printf
add esp, 8
xor eax, eax ; return 0;
leave
ret ; epilogue
! C Calling Convenction
- C 호출 규약에 따른 내용
1. callee-saved register
- 콜리가 사용하기 전에 반드시 백업해야 하는 레지스터, 콜러는 사용 가능 ( 스택 메모리에 백업 )
- ebp, esi, edi, ebx
2. caller-saved register
- 콜러가 사용하기 전에 반드시 백업해야 하는 레지스터, 콜리는 사용 가능
- eax, ecx, edx
[실습]
- 지난번에 작성했던 reverse.asm 코드를 지역변수를 사용해서 동작하도록 수정
( 모든 변수는 스택 메모리를 사용 )
[ C언어 코드 ]
char buffer[1024];
int len = 0;
int i = 0;
int main() {
gets ( buffer );
while( buffer[len] != '\0' ) {
len++;
}
len--;
for( i = len; i >= 0; i-- ) {
printf("%c", buffer[i]);
}
printf("\n");
return 0;
}
[ 어셈블리 코드 ]
extern printf
extern gets
section .data
print_chr db '%c', 00
print_new db 10, 00
section .text
global main
main:
push ebp
mov ebp, esp ; prologue;
sub esp, 1028
lea eax, [ebp-1024]
push eax
call gets ; gets( buffer );
mov dword [ebp-1028], 0 ; int len = 0;
while:
mov edx, dword [ebp-1028]
cmp byte [ebp-1024+edx], 0
jz while_end ; buffer[len] != 0;
inc dword [ebp-1028] ; len++;
jmp while
while_end:
dec dword [ebp-1028] ; len--;
for:
cmp dword [ebp-1028], 0
jl end ; i >= 0;
mov edx, dword [ebp-1028]; i = len;
mov eax, [ebp-1024+edx]
push eax
push print_chr
call printf ; printf("%c", buffer[i]);
dec dword [ebp-1028] ; i--;
jmp for
end:
push print_new
call printf ; printf("\n");
leave
ret ; epilogue
'프로그래밍 > SYSTEM HACKING' 카테고리의 다른 글
[SYSTEM HACKING] 시스템 콜 실습 ( mymkdir, mycat, myshell ) (0) | 2017.11.02 |
---|---|
[SYSTEM HACKING] main 함수의 인자 / 시스템 프로그래밍( 시스템 콜 ) (0) | 2017.11.01 |
[SYSTEM HACKING] 실행중인 프로세스의 전체 메모리 구조 / 스택에서 사용되는 레지스터 / 어셈블리에서 함수 (0) | 2017.10.26 |
[SYSTEM HACKING] 어셈블리 반복문( jmp ) (0) | 2017.10.24 |
[SYSTEM HACKING] 어셈블리 분기문( compare<cmp>, jump<jmp> ) (0) | 2017.10.23 |
댓글