16진수의 무작위 숫자에 대하여 1이 몇개인지 숫자를 carry하도록 하는 Assembly 코드입니다.


[Assembly code]

main NOP

       MOV r4, #32 //r432(0x20)의 값을 저장합니다.

       LDR r1, RANNUM //r1RANNUM의 값을 LOAD합니다.

       MOV r0, r4 //r4의 값을 r0에 저장하여 r0에는 32의값이 들어갑니다.

       MOV r3, #0 //r30의 값으로 초기화합니다.

LOOP MOV r2, r1, LSR #31 

/* r1의 값(0x04882C2A)31bit만큼 LSR연산하여 r2에 그 값을 저장 합니다. 위 연산을 거치게되면 r20또는 1의 값이 저장됩니다. */

       CMP r2, #1 //r2의 값과 1을 비교하여, 만약 같다면 아래 ADDEQ로 분기하여 r3 1을 더하여 줍니다.

       IT EQ

       ADDEQ r3, r3, #1

       MOV r1, r1, LSL #1 //이제, r1LSL 1bit만큼 shift하여 저장합니다.

       SUBS r0, r0, #1 //r0에서 1의값을 뺍니다.

       BNE LOOP

EXIT B EXIT

       DATA

RANNUM DCD 0x04882C2A

       END



다음은 IAR Embedded Workbench 툴에서 Assembly 코드로 직접 돌려본 후 분석하는 부분입니다.

보드를 선택하는 부분에서 ARM 계열의 Cortex-m3라는 보드를 선택하였습니다.


1. 초기화면입니다.


 

2. r1DATA RANNUMLOAD된 모습입니다.


3. r1을 왼쪽으로 shift 1bit만큼 해준 화면입니다.


 

4. r0의 값(32)에서 1만큼빼주어 31이 된 화면입니다.

 

5. r1의 값을 31bit만큼 오른쪽으로 shift해준 값을 r2에 저장합니다.


6. 만약, r2의 값이 1이라면, r3의 값에 1을 더해줍니다.


  7. 그리고 r1의 값을 다시 1bit만큼 왼쪽으로 shift해줍니다.


8. 이렇게 r0에 저장된 32번만큼 LOOP를 돌아서 r0의 값이 0이되면, exit됩니다.


WRITTEN BY
SiriusJ

,

다음은 16진수의 무작위 숫자에 대하여 짝수인지, 홀수인지를 파악하는 Assembly code입니다.


main NOP

       NUM EQU 10

       LDR r1, =RANNUM //r1RANNUM의 주소를 Load합니다.

       MOV r6, #NUM //r6은 총 10개의 숫자들의 개수를 가리킵니다.

       LDRB r5, [r1] //r5r1의 값을 저장합니다.

       MOV r2, #0 //r2는 홀수를 세는 count, 0으로 초기화합니다.

       MOV r3, #0 //r3는 짝수를 세는 count, 0으로 초기화합니다.

       LDRB r5, [r1], #1 //r5가 다음 r1을 가리키도록 합니다.

LOOP MOV r0, r5, LSL #31 

/* r5의 값을 31bit만큼 shift left하여 맨 뒤의 bit값만 저장합니다. 홀수라면 0x10000000이될것이고, 짝수라면 0x00000000일것입니다. */

       MOV r7, r0, LSR #31 

//다시 r7의 값을 31bit만큼 right shift시키면, 0x00000001(홀수), 0x00000000(짝수) 가 됩니다.

       CMP r7, #1 //이제, r7을 비교합니다.

       ITE EQ

       ADDEQ r2, r2, #1 //만약 같다면, 홀수의 카운트를 늘려주고, 다르다면 짝수의 카운트를 늘려줍니다.

       ADDNE r3, r3, #1

       LDRB r5, [r1], #1 //r5가 다음 r1값을 가리키도록 설정합니다.

       SUBS r6, r6, #1 //한번 수행할때마다 Num의 값을 1씩 줄여줍니다.

       BNE LOOP

EXIT B EXIT

       DATA

RANNUM DCB 0x10, 0x3, 0x23, 0x20, 0x43, 0x7, 0x21, 0x56, 0x67, 0x36

//임의의 무작위 수들 10가지 (0x10, 0x3, 0x23, 0x20, 0x43, 0x7, 0x21, 0x56, 0x67, 0x36)

       END 



다음은 IAR Embedded Workbench 툴에서 Assembly 코드로 직접 돌려본 후 분석하는 부분입니다.

보드를 선택하는 부분에서 ARM 계열의 Cortex-m3라는 보드를 선택하였습니다.


1. 초기화면입니다.


 2. R1에는 RANNUM의 주소값이, R6에는 총 NUM갯수인 10의 값(A), R2,R3는 각각 0으로 초기화된 화면입니다.


 3. 처음 R531bit만큼 shift해주어 r0에 저장하고, 다시 31bit만큼 shift해주면 0x00000000이 됩니다. 0x10은 짝수이기 때문에 0x00000000으로 되어, 0의 값이 R7에 저장됩니다. 다음으로 CMP를 이용하여 r71을 비교합니다.


 4. 0x10은 짝수이므로, R31을 더하여줍니다.


 5. 한번 시행되었을 때마다, R6에서 1씩 횟수(count)를 줄여줍니다.


6. 홀수일때의 모습입니다. R0에는 shift left된 모습이 저장되어있고, R2count되어 1더하여진 모습을 확인할 수 있습니다.


 7. 종료되었을 때의 화면으로, 총 홀수가 6, 짝수가 4개 있음을 확인할 수 있습니다.


WRITTEN BY
SiriusJ

,

다음은 4x4행렬의 곱셈을 Assembly 로 구현한 부분입니다.


[Assembly Code]

main NOP

       MOVS r9, #4 //r9count 하기위해 4를 저장합니다.

       MOV r10, #0x80

//r100x80번지 memorystore하기위해 해당번지(0x80)로 설정해둡니다.

 

//r1ARRAY1, r2ARRAY2의 주소를 가리키고, r3, r4에 각각 1, 2의 값이 저장되게 합니다.

       LDR r1, =ARRAY1

       LDR r2, =ARRAY2

       LDRB r3, [r1], #1

       LDRB r4, [r2], #1

LOOP1 CMP r9, #1

       MOVS r0, #4 //r0LOOP2에서 각 4번씩 count하기위해 4를 저장합니다.

       BL LOOP2

       LDR r2, =ARRAY2 //r2LOOP2를 돌면, 값이 변하므로, 다시 ARRAY2를 가리키게합니다.

       LDRB r4, [r2], #1

       LDRB r3, [r1], #1 //r1의 값을 ARRAY10x1에서 0x2load합니다.

       SUBS r9, r9, #1 //r9count값을 1 빼줍니다.

       BNE LOOP1

EXIT B EXIT

LOOP2 CMP r0, #1 //r0LOOP24번 수행하도록 비교합니다.

       MOVS r5, #0 //r5,r6은 아래 STMIA를 거치면 값이변하므로, 초기화합니다.

       MOVS r6, #0

       SMLAL r5, r6, r3, r4 //r3,r4의 값을 곱한후, r5,r6에 더하여줍니다.

       STMIA r10!, {r5,r6} //r5,r6의 값을 memory r10번지(0x80)store시킵니다.

       LDRB r4, [r2], #1 //r2의 값을 바꿔가며, r3r4를 곱해줍니다.

       SUBS r0, r0, #1 //r0의 카운트를 1 줄여줍니다.

       BNE LOOP2

       MOV pc, r14

       DATA

ARRAY1 DCB 0x1, 0x2, 0x3, 0x4

ARRAY2 DCB 0x2, 0x3, 0x4, 0x5

       END



다음은 IAR Embedded Workbench 툴에서 Assembly 코드로 직접 돌려본 후 분석하는 부분입니다.

보드를 선택하는 부분에서 ARM 계열의 Cortex-m3라는 보드를 선택하였습니다.


1. 처음 돌렸을때의 화면입니다. 아래 memory영역을 보면 ARRAY1, ARRAY2의 값이 memory 해당주소에 저장되있음을 확인할 수 있습니다.


 

2. 오른쪽 register창 에서, R1,R2의 값을 주소를 저장하고, R3,R4에는 각각 ARRAY1, ARRAY2의 값이 들어감을 확인할 수 있습니다또한 r9에는 count하기위한 값 ‘4’, r10에는 0x80번지가 저장됩니다.


3. LOOP2 내 에서 한번 수행했을 때입니다. r01줄었고, R31이고, R42를 수행하고 난 뒤인 3의 값을 가진 모습입니다. R5에는 R3(1) X R4(2)일때의 값인 2를 저장하고 있습니다. R108만큼 증가한 값을 가집니다.


4. LOOP1를 두 번째 돌기 직전의 화면으로, R0은 다시 4로 초기화되어있고R3의 값은 1일 때 R4(2,3,4,5)4번 곱한 후, 증가한 2의 값이 되어있습니다R9LOOP11번 돌았으므로 1만큼 감소한 3을 나타냅니다.


5. 아래 메모리를 확인하면, 0x80번지 메모리부터 차례로 R3XR4를 한 값들이 저장되어있음을 확인할 수 있습니다. LOOP13번 수행했을 때입니다.

1x2=2, 1x3=3, 1x4=4, 1x5=5 // 2x2=4, 2x3=6, 2x4=8, 2x5=A // 3x2=6, 3x3=9, 3x4=C, 3x5=F


 

6. 종료되었을때의 화면입니다. R0=0, R9=0으로 전부 카운트되었음을 확인할 수 있고아래 메모리에서도 값들이 전부 저장되었음을 확인할 수 있습니다.


WRITTEN BY
SiriusJ

,

먼저, 포스팅에서 진행 되는 IAR Embedded Workbench버전이 예전 버전이라 지금 버전과 많이 달라진 것 같습니다.

다만 분석하는 부분은 같을 거라는 예상에서 올려봅니다.

먼저 아래의 C코드를 수행하고 Line-by-Line으로 RegisterDisassembly 창의 결과를 분석하는 부분을 살펴보겠습니다.

int main() {

  int a = 2;

  int b = 4;

  a = xfunc(a, b);

  b = yfunc(a, b);


  return 0;

}

int xfunc(int a, int b) {

  return a*b;

}

int yfunc(int a, int b) {

  return xfunc(a, b);

} 


1. 먼저, Register창에서는 PC(Program counter)는 다음에 실행할 address를 임시로 저장합니. 지금은 main함수를 실행하기 위해 0x40을 가리키고 있고 Disassembly창에서 초록으로 표시된 부분은 다음에 수행할 부분을 표시한 상태입니. ( 현재 수행된 상태가 아니라는 것에 주의합니다. )

다음으로 수행할 부분은 PUSH {R4, LR}으로, Link Register(LR)R4레지스터를 stack에 저장하라는 명령입니. 현재 보이는 화면에서 Step Over 하게되면 Disassembly창에서는 address0x40인 부분을 실행하기 때문에 PC(program counter)는 다음에 실행할 0x42를 가르키게 됩니. 그리고 SP(stack pointer)0x08만큼 감소하여 2번과 같은 그림이 나오게 됩니다.


2. Disassembly의 창에서 ‘MOVS R0, #2’ -> ‘2’의 값을 레지스터 R0에 저장을 다음에 Step Over하게 되면 수행하게됩니다. Register창의 PC는 다음에 수행할 address주소인 0x42를 가르키게 됩니다.


3. 오른쪽 Register창에 보다시피 R02가 저장되었고, PC는 다음에 실행할 0x44를 가리키게 됩니다.

Disassembly창에서는 ‘MOVS R4, #4’ 에 따라서 다음번에 레지스터 R4‘4’의 값을 저장하게 됩니다.


4. Register창에서는 레지스터 R44의 값이 저장되었고, PC0x46을 가리킵니.

Disassembly창에서는 다음번에 ‘MOVS R1, R4’에 따라서 레지스터 R4의 값을 레지스터 R1에 저장하게 됩니.


5. Register창에서 보다시피 레지스터 R4의 값이 레지스터 R1로 저장되었습니다. PC0x48 을 가리킵니다.

Disassembly창에서 보면 다음에 수행할 ‘BL xfunc’ 는 계산된 위치의 서브루틴을 호출하게 되는데,

, xfuncbranch(분기)하고, 수행 시 Link Register에 다음번에 수행할 PC(0x48)+4의 값을 대입하게 됩니다.

다음으로 Step into를 클릭하여 xfunc함수 내로 이동합니다.


6. Register창을 보면, PC0x58을 가리키고, LR 레지스터에 PC(0x48)+4의 값을 대입한 값(0x4D)이 나오게 됩니. (계산대로라면 PC(0x48)+4를 하면 0x4C가 되어야하지만, little-endian big-endian 관계에 의하여 0x4D LR 레지스터에 저장됨)

Disassembly창에서 ‘MULS R0, R1, R0’ 은 레지스터 R1에 저장된 값과 레지스터 R0에 저장된 값을 곱한 후 R0에 저장하라는 명령입니. 다음으로 Step Into를 클릭하여 이동합니.


7. Register창에서 PC는 다음 address주소인 0x5A를 가리킵니다.

Disassembly창에서 ‘BX LR’ return; 의 의미이며, xfunc을 빠져나와 LR에 저장된 주소(0x4D)로 이동합니다.


 

 8. Register창은 위에서 LR 번지로 이동하였으므로 PC0x4C를 가리킵니다.

Disassembly창에서는 다음에 레지스터 R4의 값을 레지스터 R1의 값에 저장하게 합니다.

9. Register: PC에서 다음 번지 주소인 0x4E를 가리킵니다.

Disassembly: ‘BL yfunc’ yfuncbranch(분기)하고 LR 레지스터에 PC(0x4E)+4의 값을 저장하게 됩니다.

Step into를 클릭하여 yfunc로 이동하게 됩니다.


10. Register: Disassembly창의 address에 따라 0x5C를 가리키고, Link RegisterPC(0x4E)+4의 값을 저장하여 ‘0x53’이 되었고, 0x52가 아닌지는 위에서(Little-endian, Big-endian) 설명하였습니다.

Disassembly: ‘PUSH {R7, LR}’ ->Link Register 와 레지스터 R7stack에 담게 됩니다.


11. Register: SP0x08만큼 줄었고, PC는 다음 번지주소 0x5e를 가리킵니.

Disassembly: 다음번에 ‘BL xfunc’ 에 의해 xfunc으로 branch(분기)하게 됩니.


12. Register: LRPC(0x5E)+4인 값으로 0x63이 나오게 되며, PCxfunc의 다음번지 주소인 0x58을 가리킵니다.

  Disassembly: ‘MULS R0, R1, R0’ => R0R1의 값을 곱하여 R0에 저장합니다.

 

 

13. Register: R00x20이 대입되었는데 그 이유로는, R0(8) X R1(4) = 32 인데, 16진수형태이므로 0x20으로 나타내어지게 됩니. PC는 물론 다음 주소인 0x5A를 나타냅니다.

Disassembly: ‘BX LR’ -> return의 의미. LR이 가리키는 address로 이동하게 됩니다.


14.  Register: PC가 다음번지주소 0x62를 가리킵니다.

Disassembly: 다음번에 R1PC의 값을 꺼내게 됩니다. 


15. Register: R1의 값은 pop으로 꺼내졌으므로 0이 되고, SP0x08만큼 다시 증가하게 됩니다.

PCyfunc을 빠져나와, 다음번지 0x52를 가리킵니.

Disassembly: MOVS R4, R0 -> R0의 값을 R4에 저장합니.


16. Register: R420으로 저장되어졌고, PC는 다음번지 0x54를 가리킵니다.

Disassembly: R0 레지스터에 ‘0’의 값을 저장합니다.


17. Register: R00이 저장되었고, PC는 다음번지 0x56을 가리킵니.

Disassembly: PC와 결과값 레지스터 R4(0x20)의 값을 pop으로 꺼내게 됩니.

18. Register: R4의 값은 꺼내졌으므로 0이 되고, SP는 또한 0x08만큼 증가하여 원래의 값이 되고PC0x76을 가리키게 됩니다.

Disassembly: ‘BL exit’ ->exit로 분기하고, PC의 값에 +4를 더한값을 LR에 저장합니. 프로그램이 exit로 분기하며 끝났다고 볼 수 있습니다.



WRITTEN BY
SiriusJ

,