정보보안5 (10,11) - call, 스택메모리의 함수표현
1. call & jmp 명령의 차이
- 공통점 : 해당 주소의 명령을 실행한다. ( 해당 주소를 eip 레지스터에 저장 )
! cpu 는 eip 레지스터를 통해 실행할 명령어를 찾는다.
- 차이점 : jmp 명령어는 해당 주소로 바로 이동하지만, call 명령어는 스택에 데이터를 저장하고 이동한다. (call명령어는 복귀할 주소를 저장한다!)
아래 예제는 다음 c언어 코드를 어셈블리로 표현한 것이다.
int sum (int a, int b){
int sum = 0;
a + b = sum;
return sum;
}
int main(void) {
int a = 10;
int b = 20;
int sum = 0;
sum = sum(a, b);
printf("%d \n", sum);
return 0;
}
[ 함수의 인자를 전달하는 방법 ]
1. 레지스터를 이용한 전달 : fastcall (64bit)
2. 공유 메모리를 이용한 전달
3. 스택 메모리를 이용한 전달 : 이것을 이용.
여기서 중요하게 보아야 할 것은 함수 호출에 있어서 스택메모리의 상황이다. 다음의 그림과 같이 보자.
최초 main ebp 부터 시작해서 12byte공간을 할당하고 push 2번을통해서 a와 b의 인자를 넘겨주고 call을 한 것을 볼 수 있다. 그리고 sum함수에서 다시 prologue와 leave,ret을 통해 메모리를 사용하고 도로 반환했고, sum func에서의 ebp에서 ebp+8 ebp+12에 접근하여 함수 인자값을 가져다 쓰는 것을 확인할 수 있다. 그리고 ret로 eip를 pop하면서 메인함수의 call함수 이 후의 스택으로 돌아온다. 그리고 return 하는 값을 eax에 저장하는 것을 확인할 수 있다.
2. 스택 메모리를 이용한 인자 전달
윈도우는 callee가 사용한 스택메모리 정리
리눅스는 caller가 사용한 스택메모리 정리
! C Calling Convention
- C 호출 규약에 따른 내용
1. callee-saved register
- ebp, esi, edi, ebx 백업을 하고 써야함(피호출자 책임)
2. caller-saved register
- eax, ecx, edx (호출자 책임)
[실습]
- 지난번에 작성했던 loop.asm 코드를 지역변수를 사용해서 동작하도록 수정
(모든 변수는 스택 메모리를 사용)
저번에 했던 return 문을 스택메모리를 이용하여 표현하면 다음과같다.