ARM7 강좌 [9] : Instruction Set (3)

 


  지난번 강좌를 쓰고 나서 이것저것 생각을 해봤는데, 내용이 좀 어렵지 않았나 싶네요. 명령 코드를 가지고 접근하는 방식은 디지털 쪽의 기초 지식과 어셈블리에 대한 보편적인 지식을 갖고 접근하는 방법이어서, 혹 그런 기본지식이 없으신 분들에게는 딱딱하고 어렵게 느껴졌을지도 모른다는 생각을 혼자(?) 했습니다.


  강좌에 대한 피드백이 없어서. 그냥 나름대로 생각하고 쓰고 있는데요. 이럴 경우엔 좀 어렵던지. 방향이 틀린 것 같다 라는 식의 의견을 들을 수 있다면 강좌의 방향을 정하는데 도움이 될 것 같다는 생각을 했습니다.


  그간 강좌를 보시고 ARM에 관한 몇 가지 질문들을 주신 분들이 계신데요. 될 수 있으면 답변을 해드리려고 노력중이고, 또 그렇게 함으로써 보람도 느낄 수 있는 것 같습니다.


  제 email 주소는 zartoven@secsm.org입니다. 강좌에 관련된 의견이나 질문이 있으신 분들은 해당 주소로 질문을 주세요. 제가 어떤 사람인지에 대해서도 말씀을 못 드렸는데, 모 전자회사에서 RTOS 업무를 담당하고 있습니다. 아직까지는 주로 pSOS 관련업무를 하고 있고요. 처음에는 pSOS관련 강좌를 운영해 볼까 생각도 해 봤지만, 과연 얼마나 많은 분들이 pSOS를 사용 하실지 의문이 들어서 포기했습니다. 관련해서 제가 알려드릴 부분이 있다면 아는 한도 내에서 최대한 노력해 보겠습니다.


  오늘은 안하던 사설을 길게 늘어놓았군요. 아무래도 지난 강좌에 다루었던 내용이 좀 부실했던 것 같아서, 오늘은 좀 다른 접근 방식으로 명령에 대한 내용을 다루려고 합니다. 자, 그럼 시작하겠습니다.


  오늘 다룰 내용은 주로 "The ARM RISC Chip. A Programmer's Guide"라는 책의 내용을 위주로 하겠습니다.


1) MOV{cond}{S} Rd,Op2

   

   Assembler에서 가장 기본적으로 사용되는 데이터 전송명령입니다. 해당 명령은 8086에서의 MOV, Z80이나 196에서의 LD 명령과 같은 역할을 합니다. 다만 차이라면 ARM7에서의 MOV는 그 Target이 되는 부분이 항상 레지스터라는 점입니다.


   예를 들어 8086에서는 MOV AX,[BX] 의 형태와 MOV AX, BX와 같은 명령의 형태를 같은 MOV명령을 통해 해결합니다만, ARM에서의 MOV는 후자의 것만을 의미합니다. 즉, 레지스터나 Immediate 값 같은 것들을 레지스터에 넣는 명령입니다.


   전자의 경우와 같이 외부 메모리를 액세스하는 명령은 따로 있고, 분류 자체를 다르게 합니다.


   제목에 써놓은 것은 MOV명령의 형식인데요. {cond}부분은 지난번 말씀드렸던 실행 조건을 제한하는 옵션입니다. ARM7에서는 모든 명령어에 해당 옵션을 적용시킬 수 있다고 말씀드렸습니다. 구체적으로는 EQ, NE, 등등의 2자 짜리 접미사 형태이고, 해당 조건에 맞도록 플래그 레지스터가 설정이 되어 있어야 MOV명령이 수행됩니다.


   {S}옵션은 해당 명령의 결과가 플래그 레지스터에 영향을 미칠지 여부를 결정하는 옵션입니다. ARM에서의 MOV는 Data Processing 명령으로 분류되어 Rd에 들어가는 값에 따라 플래그 레지스터가 영향을 받을 수 있습니다.


   하지만, 특별히 사용되는 경우가 있습니다. 좀 어려울지 모르겠지만, Target 레지스터가 PC인 경우 S옵션을 사용하면, Exception모드에서 보통 상태로 빠져 나오는 역할을 하게됩니다. 지금 다루기는 좀 그렇고요. 강좌의 마지막쯤 해서 한꺼번에 다시 다루겠습니다. 지금은 그러려니 하시길 바랍니다.


   Rd는 Target이 되는 레지스터입니다. MOV명령의 Target은 항상 레지스터이어야 합니다. 물론 MOV 뿐만이 아니라 Data Processing 명령으로 분류된 모든 명령들(지난 강좌에서 언급했던)이 다 그렇습니다.


   Op2는 MOV명령에 의해 Rd로 들어갈 내용을 가리키는 오퍼랜드입니다. 지난 강좌에서 이것저것 복잡하게 말씀드렸었는데요, Op2 부분에는 단순히 레지스터가 들어갈 수도 있고, 어떤 immediate값이 들어갈 수도 있고, 또 Shift 오퍼레이션을 가한 레지스터 내용이 들어갈 수도 있습니다.  예제를 통해 확인하시길 바랍니다.


   Ex1) MOV     r0,r1

        : 단순히 r0:=r1을 하는 명령입니다.


   Ex2) MOV     r0,#0

        : r0에 상수 0을 넣는 명령입니다. ARM에서는 196에서와 같이 상수에는 #을 붙여서 사용합니다. 또 진법 표현은 C에서의 방법을 사용합니다. 즉 MOV   r0,#0x30 이런 식으로 사용할 수도 있습니다. 혹은 &를 붙여서 16진수를 나타낼 수도 있습니다.


   Ex3) MOV     r0,#0xfc000003

        : r0에 상수 값 0xfc000003 을 넣는 명령입니다. 지난 강좌에서 말씀드렸지만 해당 값은 8비트 값 0xFF를 32비트로 확장하고 오른쪽으로 두 번 Rotate 시킨 값입니다. 그래서 에러가 나지 않는 것이지요.


   Ex4) MOV     r0,r1,LSL #1

        : 이 명령은 r0:= r1 <<1 을 수행하는 명령입니다. LSL은 logical Shift Left를 의미하는 키워드이고, Op2 부분에 위와 같은 형식으로 올 수 있습니다.


   Ex5) MOV     r0,r1,LSR r2

        : 이 명령은 r0:=r1 >> r2 에 해당하는 명령이고, LSR은 Logical Shift Right를 의미합니다.


   Ex6) MOV     r0,r0,ASR #24

        : 이 명령은 r0:=r0 >> 24 를 의미합니다. ASR은 Arithmetic Shift Right를 의미하며 LSR과의 차이는 최 상위 비트가 1인 경우 새로 계속 해당 비트 값을 유지시킨다는 것입니다.


   Ex7) MOVS    r0,r1,LSR #1    : C(flag) := r1[0]

        MOVCC   r0, #10         : if C=0 then r0:=10

        MOVCS   r0, #11         : if C=1 then r0:=11


   Ex8) MOVS    r0,r4           : if r4=0 then r0=0

        MOVNE   r0,#1           : else r0=1

        

        첫 번째 명령에서 r4값을 r0로 넣을 때 {S}옵션에 따라서 플래그 레지스터 값이 변화합니다. 다음 명령에서 NE 조건을 사용했기 때문에, 참고로 NE는 Not Equal, Z플래그가 0일 경우입니다., r4값이 0이었다면 NE는 False가 되어 두 번째 명령을 수행하지 않습니다. 결과적으로는 r0에 0이 들어간 셈이지요. 만약 r4가 0이 아니었다면 두 번째 명령이 수행되어서 r0에는 1이 들어갑니다.


  오늘 강좌는 이것으로 정리하려 합니다. 다음에 뵙겠습니다.

+ Recent posts