뭘 알아야 이해를 하지
임베디드 시스템은 예전부터 대부분 씨 언어를 사용해서 프로그램을 만들어 왔답니다. 최근 들어 시피유, 메모리, 배터리 등 기술이 점점 발달하면서 씨 언어 하나만 사용하지 않고 씨 플러스 플러스언어나 자바 언어까지 사용해서 프로그램을 개발한답니다. 앞에서 잠깐 암 어셈블러에서 씨 언어 메인 함수 콜 하는 방법을 알아 봤어요. 암 어셈블러에서 씨 언어 메인 함수 콜하는 방법은 그리 어렵지 않았답니다.
암 어셈블러에서 씨 언어 메인 함수 콜하는 방법이랍니다.
예제를 살펴보겠습니다.
[암 어셈블러에서 씨 언어 메인 함수 호출]
Startup.s 파일에서 .global main(b-1)이라고 선언을 해 주고 main(g-1)으로 call하면 됩니다. 간단하죠. 여기서 주의하셔야 할 내용은 대소문자랍니다. Startup.s 파일의 두 군데(b-1,g-1)에서 대소문자를 썩어서 사용했다면 main.c에서 main함수 이름도 Startup.s 파일에서 지정한 이름과 동일하게 작성을 해야 하죠.
그럼 이제부터는 씨 언어에서 씨 플러스플러스 함수를 콜하는 방법에 대해 알아 보려고 해요. 그 전에 잠깐 살펴보야 될 내용이 씨 언어와 씨 플러스플러스 언어와의 차이점에 조금 아셔야 해요. 그래야 씨 언어에서 씨 플러스 플러스 함수 콜을 자유롭게 할 수가 있답니다.
씨 플러스플러스의 강점은 계층(class)을 이용할 수 있다는 점입니다. 즉, 모듈과 캡슐화가 잘 되어진 언어라는 거죠.
예제를 살펴봐요.
객체와 객체의 실체에 대해 알아보아요.
soto_struct(f-2), c_plus_plus(m-4)는 객체이고, 객체의 실체는 int star;(b-2), cpp_data(c-2); 이랍니다. soto_struct에는 데이타와 함수까지 모두 포함되어 있네요. 이렇게 데이타와 함수를 포함하는 방식은 private와 public가 있어요. private의 경우는 객체의 외부에서는 참조할 수 없어요. 하지만 public의 경우는 객체의 외부에서 참조할 수가 있답니다.
c_plus_plus.cpp_data=10;
soto_struct.han();
soto_struct.byul_func();
class안의 두 함수 void han(void); (d-2) , void byul_func(void); (e-2)는 프로토타입이라고 해요. 이렇게 선언된 함수 자체를 정의(g-2, i-2)할 수가 있답니다. 여기서 one_class의 멤버 함수임을 나타낼 때 스코프 해상도 연사자(scope resolution operator)인 "::"을 사용한답니다.
간단하게 씨 플러스플러스를 살펴봤으니 씨 언어와 연결을 해 보도록 하죠.
a-3와 같이 외부 함수임을 선언하고, b-3와 같이 콜 해 주면 우선 프로그램 상에서는 끝났어요. 다음으로 해 줘야 될 사항이 makefile에서 수정을 해 주셔야 해요.
우선 main.c는 arm-elf-gcc를 사용하면 되지만 cpp_func.cpp는 arm-elf-c++을 사용해야 되죠.
[컴파일 실행]
./sources/main.c:15: undefined reference to `extern_func'
collect2: ld returned 1 exit status
make: *** [general.elf] Error 1
정상적으로 컴파일이 되지 않고 에러가 발생했는데 왜 그를까요? 정말 `extern_func' 함수가 정의되지 않아서 그럴까요?
문제의 해답을 찾기 위해서는 다음과 같이 컴파일을 해 보세요.
CMD> arm-elf-gcc -S main.c
CMD> arm-elf-c++ -S cpp_func.cpp
컴파일이 되고 나면 main.s, cpp_func.s 라는 파일이 만들어진답니다. -S라는 옵션은 어셈블리어 파일로 만들어 준답니다. 두 개의 파일에서 extern_func를 찾아보면 서로의 이름이 다르다는 것을 알수가 있어요.
main.s --> bl extern_func
cpp_func.s --> _Z11extern_funcv:
이유는 서로의 컴파일러가 다르다보니 레이블 생성도 다르게 생성된답니다. 이 문제를 해결하기 위해서는 컴파일러를 통일 할 필요가 있어요. arm-elf-c++은 일반 씨 언어 컴파일도 가능하니 makefile에서 ARMCC = $(PRE)-c++ 부분만 수정하고 다시 컴파일을 하면 된답니다.
CMD> make
arm-elf-size general.elf
text data bss dec hex filename
1060 52 8 1120 460 general.elf
이왕 씨 언어에서 씨 플러스 플러스 함수 콜하는 방법을 알아 봤으니 어셈블러에서 어셈블러 함수 콜하는 것과 씨 플러스플러스 언어에서 씨 언어 함수 콜하는 방법까지 모두 알아보도록 할께요.
어셈블러에서 어셈블러 함수 콜하는 방법을 소개할께요.
Startup.s 파일에서는 mmulib.s 파일에 있는 레이블 이름만 콜(a-4)하면 되고, mmulib.s 파일에서는 레이블 이름을 선언(b-4)해 주고, 레이블 지정(c-4)한 다음 내용 내용을 작성하면 됩니다.
이제 makefile을 살펴보죠.
마지막으로 씨 플러스플러스에서 씨 함수를 콜하는 방법을 알아보죠.
a-5와 같이 외부 함수를 선언하고, b-5에서 c 함수를 콜해주면 우선 프로그램 상에서는 끝났어요. 다음으로 해 줘야 될 사항이 makefile에서 수정을 해 주셔야 해요.
위에 있는 예제도 보시다 시피 컴파일을 하면 에러가 발생합니다. 그래서 이번의 경우는 cpp_fucn.cpp파일이 c_func.c파일의 함수를 못 찾으니 c_func.c파일이름을 c_func.cpp 파일이름으로 바꿔서 컴파일을 하면 되요.
댓글