컴퓨터공부

ARM에서 ASM과 C연결

achivenKakao 2007. 3. 19. 18:08

자~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로 옮겨지는 것 같다.

음...