티스토리 뷰
AVR용 어플리케이션을 개발하는 프로그래머라면 대부분 C언어를 주로 사용할 것이다. AVR이외에 ARM이나 다른 CPU를 가지고 개발할 때는, 특히 리눅스를 포팅하거나 boot code를 만들때에는 C언어 뿐만 아니라 어셈블 프로그램도 같이 개발 하여야 한다.
하나의 컴퓨터 언어를 사용하여 개발 할때는 전혀 고려 대상이 아니었지만, 서로 다른 언어를 사용하여 프로그램을 개발할 때에는 각각의 언어에서 사용하는 함수와 변수, 입력 인자(input argument)와 리턴 값을 어떤식으로 전달할 것인지 미리 약속을 하여야 한다.
이러한 약속을 ABI(Application Binary Interface)라고 하고, 특히 임베디드 시스템에서 사용하는 약속을 EABI(Embedded Application Binary Interface)라고 한다.
ABI는 처음 들어보는 경우는 있겠지만 API(Application Programming Interface)는 들어 본적이 있을 것이다. 비슷하게 보이긴 하지만 두개는 근본적인 차이가 있다.
API는 소스코드 레벨에서의 약속을 정해 놓은 것이다. 예를 들면 memcpy()라는 함수가 있다. 이 함수는 어느 한 영역의 메모리를 다른 영역으로 복사를 하기 위하여 사용한다.
void *memcpy(void *dest, const void *src, size_t n);
위에 보이는 것이 memcpy함수의 함수 원형이다. Input argument는 dest주소, src주소, 복사할 데이터 크기를 알려주도록 되어 있다. 리턴값으로 나오는 것은 dest 주소값을 돌려준다. 이렇게 어떤 함수를 사용하기 위한 방법을 약속하는 것을 API라고 한다.
이와는 다르게 EABI는 첫번째 argument는 어떤 레지스터를 이용하고, 두번째 argument는 그 다음 레지스터를 사용하고 등등 CPU 아키텍쳐에 의존적인 약속을 정해 놓는 것이다.
예를 들면 ARM 아키텍쳐는 r0부터 input argument용으로 할당한다. 리턴값 역시 r0를 이용하여 돌려준다.
C언어와 어셈블러를 같이 사용하는 경우에 이러한 약속을 서로 지켜야 정상적인 프로그램이 동작된다.
AVR CPU에서의 ABI는 이미 입문편 인터럽트에서 약간 설명한 적이 있다. 이번글에서는 그 외에 나머지에 대해서 설명하도록 하겠다.
위의 표는 이미 인터럽트글에서 설명하였다.
C와 어셈블 코드간의 parameter 전달은 r25 ~ r8까지 사용하도록 되어 있다. 리턴값은 리턴되는 크기에 따라 r25 ~ r18까지 사용할 수 있다.
여러 바이트 값을 전달할때 바이트 순서와 레지스터간의 관계를 설명한것이다. 만약 1바이트 값이 argument로 들어가면 r24를 통해서 전달되고, 2바이트 값이면 r25,r24를 사용한다. 앞의 글에서 설명했듯이 AVR은 little-endian 방식을 사용하므로 r24에 낮은 주소값이 들어가고 r25에 높은 주소에 들어있는 값이 전달된다.
AVR의 경우에는 이정도만 알고 있어도 되지만 다른 CPU를 사용할 때는 그 CPU 제조사에 제공하는 ABI문서를 꼼꼼히 분석하여 프로그램하여야 한다.
'심화' 카테고리의 다른 글
포인터(Pointer) - 개념 (0) | 2016.07.02 |
---|---|
random 함수 (4) | 2016.06.12 |
엔디안(Endian) (0) | 2016.04.23 |
변수는 여기에! (6) | 2016.04.23 |
변수는 어디에? (1) | 2016.04.20 |