먼저, 포스팅에서 진행 되는 IAR Embedded Workbench버전이 예전 버전이라 지금 버전과 많이 달라진 것 같습니다.
다만 분석하는 부분은 같을 거라는 예상에서 올려봅니다.
먼저 아래의 C코드를 수행하고 Line-by-Line으로 Register와 Disassembly 창의 결과를 분석하는 부분을 살펴보겠습니다.
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창에서는 address가 0x40인 부분을 실행하기 때문에 PC(program counter)는 다음에 실행할 0x42를 가르키게 됩니다. 그리고 SP(stack pointer)는 0x08만큼 감소하여 2번과 같은 그림이 나오게 됩니다.
2. Disassembly의 창에서 ‘MOVS R0, #2’ -> ‘2’의 값을 레지스터 R0에 저장을 다음에 Step Over하게 되면 수행하게됩니다. Register창의 PC는 다음에 수행할 address주소인 0x42를 가르키게 됩니다.
3. 오른쪽 Register창에 보다시피 R0에 2가 저장되었고, PC는 다음에 실행할 0x44를 가리키게 됩니다.
Disassembly창에서는 ‘MOVS R4, #4’ 에 따라서 다음번에 레지스터 R4에 ‘4’의 값을 저장하게 됩니다.
4. Register창에서는 레지스터 R4에 4의 값이 저장되었고, PC는 0x46을 가리킵니다.
Disassembly창에서는 다음번에 ‘MOVS R1, R4’에 따라서 레지스터 R4의 값을 레지스터 R1에 저장하게 됩니다.
5. Register창에서 보다시피 레지스터 R4의 값이 레지스터 R1로 저장되었습니다. PC는 0x48 을 가리킵니다.
Disassembly창에서 보면 다음에 수행할 ‘BL xfunc’ 는 계산된 위치의 서브루틴을 호출하게 되는데,
즉, xfunc로 branch(분기)하고, 수행 시 Link Register에 다음번에 수행할 PC(0x48)+4의 값을 대입하게 됩니다.
다음으로 Step into를 클릭하여 xfunc함수 내로 이동합니다.
6. Register창을 보면, PC는 0x58을 가리키고, 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 번지로 이동하였으므로 PC는 0x4C를 가리킵니다.
Disassembly창에서는 다음에 레지스터 R4의 값을 레지스터 R1의 값에 저장하게 합니다.
9. Register창 : PC에서 다음 번지 주소인 0x4E를 가리킵니다.
Disassembly창 : ‘BL yfunc’ 는 yfunc로 branch(분기)하고 LR 레지스터에 PC(0x4E)+4의 값을 저장하게 됩니다.
Step into를 클릭하여 yfunc로 이동하게 됩니다.
10. Register창 : Disassembly창의 address에 따라 0x5C를 가리키고, Link Register에 PC(0x4E)+4의 값을 저장하여 ‘0x53’이 되었고, 왜 0x52가 아닌지는 위에서(Little-endian, Big-endian) 설명하였습니다.
Disassembly창 : ‘PUSH {R7, LR}’ ->Link Register 와 레지스터 R7을 stack에 담게 됩니다.
11. Register창 : SP는 0x08만큼 줄었고, PC는 다음 번지주소 0x5e를 가리킵니다.
Disassembly창 : 다음번에 ‘BL xfunc’ 에 의해 xfunc으로 branch(분기)하게 됩니다.
12. Register창 : LR은 PC(0x5E)+4인 값으로 0x63이 나오게 되며, PC는 xfunc의 다음번지 주소인 0x58을 가리킵니다.
Disassembly창 : ‘MULS R0, R1, R0’ => R0와 R1의 값을 곱하여 R0에 저장합니다.
13. Register창 : R0에 0x20이 대입되었는데 그 이유로는, R0(8) X R1(4) = 32 인데, 16진수형태이므로 0x20으로 나타내어지게 됩니다. PC는 물론 다음 주소인 0x5A를 나타냅니다.
Disassembly창 : ‘BX LR’ -> return의 의미. LR이 가리키는 address로 이동하게 됩니다.
14. Register창 : PC가 다음번지주소 0x62를 가리킵니다.
Disassembly창 : 다음번에 R1과 PC의 값을 꺼내게 됩니다.
15. Register창 : R1의 값은 pop으로 꺼내졌으므로 0이 되고, SP도 0x08만큼 다시 증가하게 됩니다.
PC는 yfunc을 빠져나와, 다음번지 0x52를 가리킵니다.
Disassembly창 : MOVS R4, R0 -> R0의 값을 R4에 저장합니다.
16. Register창 : R4가 20으로 저장되어졌고, PC는 다음번지 0x54를 가리킵니다.
Disassembly창 : R0 레지스터에 ‘0’의 값을 저장합니다.
17. Register창 : R0에 0이 저장되었고, PC는 다음번지 0x56을 가리킵니다.
Disassembly창 : PC와 결과값 레지스터 R4(0x20)의 값을 pop으로 꺼내게 됩니다.
18. Register창 : R4의 값은 꺼내졌으므로 0이 되고, SP는 또한 0x08만큼 증가하여 원래의 값이 되고, PC는 0x76을 가리키게 됩니다.
Disassembly창 : ‘BL exit’ ->exit로 분기하고, PC의 값에 +4를 더한값을 LR에 저장합니다. 프로그램이 exit로 분기하며 끝났다고 볼 수 있습니다.