본문 바로가기
시스템 반도체/Arm

Arm calling convention ( 레지스터 사용, caller, callee, AAPCS )

by 전컴반 2022. 8. 2.
반응형

caller와 callee가 있다. 직역하면 caller는 호출한 놈이고, callee는 호출당한 놈이다.

조금 다르게 보면 caller는 main구문이고, callee는 호출 함수다. 그렇다면 main에서 레지스터를 사용하고 있을 텐데 callee 즉, 함수에서는 어떤 레지스터를 사용해야 할까??

 

Arm에서는 지정 레지스터만 사용하게 했다. 이게 AAPCS ( Procedure Call Standard for ARM Architecture )이다.

Arm CPU에는 16개의 레지스터가 있는데 이때 callee는 r0~r4 레지스터만 사용할 수 있다. 사용할 수 있다는 말은 넘겨줄 수 있는 인자를 4개의 레지스터에게만 보낼 수 있다.

그럼 4개가 넘어가면 어떻게 될까?? 이때부터는 stack을 사용한다.   

 

또 궁금한 게 있다. 그러면 함수가 return 해 주는 인자도 똑같인 4개를 사용할 수 있나? 다르다. return 인자는 r0, r1 레지스터만 사용할 수 있다. 마찬가지로 2개가 넘어가면 stack을 사용한다.

 

이게 진짜 중요하다. 값을 덮어 씌울 수도 있기 때문에 보안에도 중요하고 디버깅할 때 문제를 해결하는데 도움을 주기도 한다.

 

예를 들어보자

 

------- main.S ---------
main:
 mov r0, #5
 bl test
 -----------------------
 
 
------- test.c --------
int test(int a) {
	unsigned int c = 0;

	c = a + 10;

	return c;
}
-----------------------

 

assmbly main (caller)가 test를 호출했다고 하자. 이때 레지스터의 값들을 보자

( +mov r0, #5는 인자 int a에 5를 넣어준 것이다. 안 하면 0으로 세팅된다.)

 

1. 처음 세팅된 레지스터 값

 

2. mov r0, #5

하면 r0에 5가 들어간다.

 

3. c = a +10

앞에 명령어들에는 레지스터의 변화가 없어서 생략했다. 

더한 결과가 r3 레지스터에 들어간다.

 

4. return c

return값은 r0, r1으로만 반환되기 때문에 r0에 return 값인 15가 들어갔다. 

 

이렇든 callee는 r0-r4 레지스터만을 가지고 사용한다.

 

추가적으로 만약에 호출 인자가 2개라고 했을 때, ( 가령, int callee (int a, int b) )

mov r0, #5

mov r1, #5

bl test

하면 된다. r0로 시작했기 때문에 r1으로 이어받아야 한다. 인자를 순차적으로 받는다.

반응형

댓글