본문 바로가기
인라인 어셈블러를 사용하려면?

뭘 알아야 이해를 하지
씨 언어로 만든 프로그램에다 어셈블러 명령어를 삽입하는 것을 인라인 어셈블러라고 해요.
인라인 어셈블러를 사용하는 목적이 무엇일까요? 우선 효율적인 프로그램을 만들 수가 있어 프로그램 속도가 향상되며, 더불어 바이너리 크기를 줄일 수가 있어 메모리 절약에도 큰 도움이 된답니다.
그럼 본격적으로 예제를 살펴보도록 할게요.

인라인 어셈블러를 사용하려면 우선 g-1과 같이 선언을 하면 됩니다.
기본적인 문법을 살펴볼게요.
h-1에서 j-1까지는 어셈블러 명령어랍니다. k-1은 최종 결과값이 어디에 저장될 것인가를 지정한답니다. 연산을 하기 위해 입력할 데이터를 지정하는 부분이 l-1이며 순차적으로 i, j, x, y값이 있는데 이것은 h-1의 명령어 이후 %1, %2, %3, %4에 각각 할당 받게 된답니다. h-1에서 j-1까지 덧셈을 해서 j-1에 %0지정된 변수로 저장해서, 최종 메모리에 반영 해라는 의미로 m-1 에서 선언을 했답니다.

[인라인 어셈블러를 컴파일했을 때 생성된 명령어]
___addr/line__|code_____|label____|mnemonic________________|comment
|
14| __asm__ __volatile__ (
SR:0000037C|E51B0010 ldr r0,[r11,#-0x10] // i=1값 읽음
SR:00000380|E51B1014 ldr r1,[r11,#-0x14] // j=1값 읽음
SR:00000384|E51B2018 ldr r2,[r11,#-0x18] // x=1값 읽음
SR:00000388|E51B301C ldr r3,[r11,#-0x1C] // y=1값 읽음
SR:0000038C|E0800001 add r0,r0,r1 // i + j
SR:00000390|E0822003 add r2,r2,r3 // x + y
SR:00000394|E0803002 add r3,r0,r2 // y=(i + j)+(x+y)
SR:00000398|E50B3020 str r3,[r11,#-0x20] //최종 result 값을 "memory" 에 저장

[% 인자값에 대한 정의]

그럼 인라인 어셈블러를 사용하면 얼마나 효율적인지 확인해 보죠.


j와 x를 더해서 result 변수에 저장하는 프로그램이랍니다.
하나는 함수로 프로그램 했고, 하나는 인라인 명령어로 프로그램을 했는데 얼핏 보면 씨 함수가 더 간단하다고 생각될 수도 있지만 실제 타겟 상에서 프로그램이 실행됐을 때는 많은 성능에 차이가 있답니다.
우선 명령어 코드로 살펴봐요.

[씨 언어로 함수를 만들었을 경우]
30|int func_sub( int a, int c) {
SR:000003AC|E1A0C00D__func_sub:_mov_____r12,r13
SR:000003B0|E92DD800 stmdb r13!,{r11-r12,r14,pc}
SR:000003B4|E24CB004 sub r11,r12,#0x4
SR:000003B8|E24DD008 sub r13,r13,#0x8
SR:000003BC|E50B0010 str r0,[r11,#-0x10]
SR:000003C0|E50B1014 str r1,[r11,#-0x14]
31| result = a+c;
SR:000003C4|E59F101C ldr r1,0x3E8
SR:000003C8|E51B2010 ldr r2,[r11,#-0x10]
SR:000003CC|E51B3014 ldr r3,[r11,#-0x14]
SR:000003D0|E0823003 add r3,r2,r3
SR:000003D4|E5813000 str r3,[r1]
32| return 0;
SR:000003D8|E3A03000 mov r3,#0x0
33|}
SR:000003DC|E1A00003 mov r0,r3
SR:000003E0|E24BD00C sub r13,r11,#0x0C
SR:000003E4|E89DA800 ldmia r13,{r11,r13,pc}
SR:000003E8|30020000 dcd 0x30020000

메모리 주소를 살펴보니 000003AC ~ 000003E8까지 명령어가 있네요. 즉, 16byte 만큼 메모리를 사용했어요.

[인라인 어셈블러 명령어로 만들었을 경우]
44| __asm__ __volatile__ (
SR:00000450|E51B2014 ldr r2,[r11,#-0x14]
SR:00000454|E51B3018 ldr r3,[r11,#-0x18]
SR:00000458|E0823003 add r3,r2,r3
SR:0000045C|E59F2020 ldr r2,0x484
SR:00000460|E5823000 str r3,[r2]
SR:00000464|E51B3010 ldr r3,[r11,#-0x10]
SR:00000468|E2833001 add r3,r3,#0x1
SR:0000046C|E50B3010 str r3,[r11,#-0x10]
SR:00000470|EAFFFFF3 b 0x444
| "add %0,%1,%2 \n\t"
| :"=r" (result)
| :"r" (j), "r" (x)
| : "memory"
| );
| }
51| return 0;

메모리 주소를 살펴보니 00000450 ~ 00000470까지 명령어가 있네요. 즉, 9byte 만큼 메모리를 사용했어요.

두 개의 프로그램 모두 같은 결과이지만 메모리 사용량에서부터 차이가 나며 명령어가 많을 수록 성능은 떨어지게 마련이죠.


Linked at 친절한 임베디드 시스템 개발자.. at 2010/06/27 22:03

... sp; 305 씨 언어에서 씨 플러스플러스 함수를 콜하는 방법은? 306 인라인 어셈블러를 사용하려면? 307 소스레벨 디버깅은 어떻게 해야 하나요? &nbsp ... more

Commented by Joy at 2010/06/28 09:13
인라인함수에서 volatile option이 들어가는 걸 이제서야 알았네요..ㅡ.ㅡ;
지금껏 그냥 써왔는데...ㅠ.ㅠ 역시 무식하면 용감한거죠...
잘보고 갑니다. ^^
Commented by soto at 2010/06/28 13:39
도움이 되셨나요?
즐거운 하루 되세용~~!!
Commented by 노란두줄 at 2010/06/29 11:01

항상 잘 보고 있습니다~
다만, 코드 예제가 들어갈 때, indent가 지켜지면 좀 더 가독성이 좋은 글이 될 듯합니다 ^^/
Commented by soto at 2010/06/29 18:59
네..
조금 더 세심하게 정리해서 올리도록 할게요.
좋은 말씀 감사합니다. ^^
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.
친절한 임베디드 시스템 개발자 되기 강좌 글 전체 리스트 (링크) -



댓글





친절한 임베디드 개발자 되기 강좌 글 전체 리스트 (링크) -