자~ARM에 대해서 앞으로 쭉쭉 같이 공부 해 나가도록 합시다.
ARM processor에만 치우치기 보다는 전반적인 기본 원리, 배경상식, 등등 기초지식이 없는 사람들도 보고 감이 올수 있도록 같이...왜냐면 나도 ARM을 공부하는 중이므로, 아주 조금;;-_-;;
임베디드에 관심 있는 사람들이라면, 당연히 알고 있어야 할 칩, 썬칩도 아니고 ARM칩에 대해서..나 요새 심히 이상스럽다..
먼저 하드웨어 프로그래밍이다 보니, 어쩔수 없이 C코딩과 더불어 어셈블리 코드가 들어갈 수 밖에 없다. 물론 어셈블리 코드로 모두다 짜야 하는건 아니지만, 최소한 어셈블리 코드를 보고 이해할 수 있어야 한다.
어셈블리 부터 설명하고 싶지만, 사실은 지금 나도 배우는 단계에 있으므로....예를 들면 이러한 코드를 해석 할 수 있어야 한다.
<<ARM ASSEMBLY-C CONNECTION>>
<C code>..........If else statement
int min(int x, int y) {
if (x < y)
return x;
else
return y;
}
<ASM>
min:
cmp r0, r1
movge r0, r1
bx lr
------------------ or
min:
cmp r0, r1
bxlt lr
mov r0, r1
bx lr
------------------
여기서---> 첫벗째 3줄짜리 어셈코드와 두번째 4줄짜리 코드에 대해 어떤 코드가 더 좋은코드인가?
<C code>..........While statement
int div2(int x) {
int count = 0;
while(x) {
count++;
x = x >>1;
}
return count;
}
<ASM>
div2:
mov r3, #0
cmp r0, #0
beq .L8
.L9:
movs r0, r0, asr #1
add r3, r3, #1
bne .L9
.L8:
mov r0, r3
bx lr
--------------------------
<C Code> .......Do-While
int dowhile(int x, int y) {
do {
x = x - y;
} while( x > y);
return x;
}
<ASM>
dowhile:
.L41:
sub r0, r0, r1
cmp r1, r0
blt .L41
bx lr
-----------------------------
<C code>.....For
int div2for(int x) {
int count;
for(count = 0; x; count++)
x = x >>1;
return count;
}
<ASM>
div2for:
mov r3, #0
cmp r0, #0
beq .L16
.L17:
movs r0, r0, asr #1
add r3, r3, #1
bne .L17
.L16
mov r0, r3
bx lr
-------------------------------
<C code> .......For-CONTINUE
int forcontinue(int x) {
int count;
for (count = 0; x; count++) {
if( x == ocunt)
continue;
x = x -1;
}
return count;
}
<ASM>
forcontinue:
mov r3, #0
cmp r0, #0
bxeq lr
.L32:
cmp r0, r3
beq .L33
sub r0, r0, #1
.L33:
add r3, r3, #1
cmp r0, #0
bne .L32
mov r0, r3
bx lr
----------------------------
<C code>.......For-Break
int forbreak (int x) {
int count;
for (count = 0; x; count++) {
if (x == 3)
break;
x = x -1;
}
return count;
}
<ASM>
forbreak:
mov r3, #0
cmp r0, #0
bxeq lr
.L35
cmp r0, #3
beq .L36
sub r0, r0, #1
add r3, r3, #1
cmp r0, #0
bne .L35
.L36
mov r0, r3
bx lr
-----------------------
<C code >.....Switch
int switchtest(int x) {
switch (x) {
case 3:
return 1; break;
case 5:
return 2; break;
default:
return 3;
}
}
<ASM>
switchtest:
cmp r0, #3
beq .L103
cmp r0, #5
beq .L105
b .L110
.L103:
mov r0, #1
b .L111
.L105:
mov r0, #2
b .L111
.L110:
mov r0, #3
.L111:
bx lr
-------------------------
이제는 구조체에 해당하는 코드..
<C code>
Struct {
int real;
int imag;
} c;
int i;
int test(int j) {
c.real = i;
c.imag = j;
return i + j;
}
<ASM>
test:
mov r2, r0
ldr r3, .L3
ldr r0, [r3, #0]
ldr r3, l3+4
stmia r3, {r0, r2}
add r0, r0, r2
bx lr
.L4:
.align 2
.L3:
.word i
.word c
.size test, .-test
.comm c, 8, 4
.comm i, 4, 4
------------------------------
이제는 함수호출에 대한 코드
<C code >
int inc(int i) {
return i+1;
}
int simple(int i) {
return i + inc(i);
}
<ASM>
inc:
add r0, r0, #1
bx lr
simple:
stmfd sp!, {r4, lr}
mov r4, r0
bl inc
add r0, r4, r0
ldmfd sp!, {r4, pc}
----------------------------------
이번엔 배열에 해당하는 코드
<C code>
void swap(int v[], int k) {
int tmp;
tmp = v[k];
v[k] = v[k+1];
v[k+1] = tmp;
}
<ASM>
swap:
mov r1, r1, asl #2
add r2, r1, r0
ldr ip, [r1, r0]
ldr r3, [r2, #4]
str r3, [r1, r0]
str ip, [r2, #4]
bx lr
-----------------------------------
자 이번엔 마지막으로다가 포인터
<C code>
clear (int *array, int size) {
int *p;
for (p = &array[0]; p < &array[size]; p++)
*p = 0;
}
<ASM>
clear:
add r3, r0, r1, asl #2
cmp r0, r3
bxcs lr
mov r2, #0
.L31:
str r2, [r0], #4
cmp r0, r3
bcc .L31
bx lr
---------------------------------------
---------------------------------------
여기 있는 어셈코드는 ARM용 이다. 뭐 다른거랑 비슷비슷 하겠지만서도 차이점도 분명이 있을것이다(추측). 일단 위에 있는 코드를 해석해 보자.....
일단 ARM칩에는 r0~ r15 까지의 레지스터와 그 이외 cpsr이라는 레지스터도 제공한다.
r13, r14, r15는 거의 관용적으로 (conventional) 용도가 정해져 있다. r13은 스택포인터(sp), r14는 링크레지스터(lr), r15는 프로그램카운터(pc).이다.. 용도야 다들 아실테고 , r14같은 경우는 서브루틴 호출시 리턴어드레스를 저장한다고 생각하면 된다. 보통 우리가 손쉽게 많이 이용하는 레지스터는 r0~ r4까지 많이 쓰는것 같다..(나의 생각임...). 위의 코드를 잘보면, #x 같은게 있는데 저게 맨뒤의 레지스터를 먼저 Arithmetic logic unit에 보내기 전에 Barrel shifter에서 처리 하기 위함인데, ARM 아케텍쳐 자체가 그렇다. 퍼포먼스 땜시... 아 일단 ARM에 관심이 있다면, 책을 사든지, 인터넷에서 매터리얼을 구하기 바란다.
출처 : 동우 홈페이지
+
C코드에서 어셈코드로 데이터를 공유하는 방법은
인수1번은 r0으로, 인수 2번은 r1로, 인수 3번은 r2로 옮겨지는 것 같다.
음...