임베디드랜드


----------------------------------------------------------------------
               ARM7 강좌 [12] : Instruction Set(6)
----------------------------------------------------------------------

정말 오랜만에 강좌를 쓰는군요. 생활에 여유가 좀 있어서 강좌를 시작했는
데 예상보다 강좌가 길어지고 더불어 점점 다른 일들이 생겨서 요즘에는 통
시간을 낼 수가 없었습니다.

혹... 강좌를 기다리신 분이 계시다면 죄송하다는 말씀을 드려야 겠군요.

아무래도 강좌를 빨리 정리해야겠다는 생각이 듭니다. 자꾸 늘어지니까, 저
도 부담스럽고... 읽으시는 분들에게도 폐를 끼치는 것 같아서...

남은 부분에 대해서는 최대한 핵심만 얘기하려 합니다.

사실 명령어 하나하나에 대해 일일히 설명한다는 것이... 뭐 그다지 의미있
는 일 같지도 않고, 이쯤까지 왔다면 대충 어떤 명령어들이 있는지만  파악
하시고, 나중에 필요하실 때 데이터시트 찾아보시면 될것 같아요...

정리를 해보자면... 이제 말씀드릴 명령은

        곱하기 명령(MUL,MLA),
        데이터 전송 명령(LDR, STR),
        블럭데이터 전송명령(LDM, STM) 그리고
        기타 명령(SWP, SWI)

정도 입니다. Coprocessor 명령은 생략하도록 하고, 명령이 끝나면 실전 케
이스로 간단한 예제 설명을 하나 드리려고 하고, 마지막으로 스트롱암의 스
펙 정도를 간단히 언급하겠습니다.

남은 부분이 앞으로 몇번에 걸쳐서 매듭지어질지는 해봐야 겠지만,  최대한
스피디한 진행을 하려 합니다.

차후에 기회가 다으면 MMU 부분같은 것들을 짧게 짧게 다룰 수도 있겠지요.

자... 이제 시작하겠습니다.

* 곱하기 명령(MUL, MLA)

  ARM7에서의 곱하기 명령은 크게두종류가 있습니다. 하나는 그냥  곱하는
  것이고, 다른 하나는 곱해서 더하는 것입니다. ^^ 명료하죠?

  1) MUL{cond}{S}  Rd,Rm,Rs

     cond 부분은 해당 명령의 실행 조건입니다. S 플래그는 결과가 플래그
     레지스터에 영향을 미칠지의 여부라고 계속 말씀드렸었죠?

     다음으로 레지스터 3개를 지정하도록 되어있는데, Rd는 결과가 저장될
     레지스터이고, Rm과 Rs는 곱해질 두개의 레지스터입니다. 보셨듯이 이
     명령에서는 레지스터만을 사용해야 합니다.

     Ex) MUL    R1,R2,R3       ; R1:=R2*R3

     # 참고로 곱하기의 결과가 32비트를 넘는다면, 하위 32비트만 결과 레
       지스터에 남습니다.

  2) MLA{cond}{S}  Rd,Rm,Rs,Rn

     위와 비슷합니다만, 이번에는 레지스터가 4개입니다.  단순  명료하게
     의미를 말씀드리면...

        Rd :=  Rm * Rs + Rn 의 의미입니다.


* Single Data Transfer (LDR, STR)

  해당 명령은 레지스터와 외부 메모리와의 데이터 전송을 담당하는 명령입
  니다. 무척 사용빈도가 높은 명령입니다. 86에서는 MOV하나로 레지스터간
  의 데이터 전송과, 외부메모리와의 데이터 전송의 두가지 목적으로  사용
  하지만, ARM7 에서는 구분이 되어있습니다.

  즉, MOV명령은 레지스터간의 전송명령으로 분류도  데이터  처리명령으로
  분류되고, 데이터 전송명령으로는 LDR과 STR이 있습니다.

  여기에 사용되는 옵션이 많은데요, 우선, LDR은 로드라는 의미이므로  외
  부 메모리로부터 레지스터로 데이터를 읽어오는 명령이고, STR은  반대의
  기능을 하는 명령입니다.

  - 명령 형식

  LDR{cond}{B}  Rd, address{!}          Rd:= contents of address

  LDR{cond}{B}  Rd, =expression         Rd:= expression

  STR{cond}{B}  Rd, address{!}          contents of address := Rd

  LDR과 STR은 Single Data 전송 명령입니다. 비슷한 명령으로 LDM,  STM은
  여러개의 레지스터 내용을 전송할 수 있는 명령입니다.  이밖에  SWP라는
  스왑 명령이 있는데, 해당 5개의 명령만이 외부  메모리와  레지스터간의
  전송을 가능하게 하는 명령입니다.

  LDR과 STR의 경우 전송 단위를 바이트, 혹은 워드(32Bit)단위로 수행  할
  수 있습니다. 바이트 단위 전송의경우 해당 레지스터의 어떤 부분이  사
  용될지의 여부는 해당 프로세서의 Endian 에 달려 있습니다. 또, 워드 전
  송 명령을 사용할 경우, 메모리 어드레스는 Word align이 되어야 합니다.

  다음 표는 LDR과 STR에서 사용하는 전송 모드를 나타낸 것입니다.

  --------------------------------------------------------------------
   Mode                 Effective address               Indexing
  --------------------------------------------------------------------
  [Rn]                  Rn                       none
  [Rn,+- expression]    Rn +- expression                Pre-indexed
  [Rn,+- Rm]            Rn +- Rm                        Pre-indexed
  [Rn,+- Rm, shift cnt] Rn+-(Rm shifted by cnt)         Pre-indexed
  [Rn],+-expression     Rn                              Post-indexed
  [Rn],+-Rm             Rn                              Post-indexed
  [Rn],+-Rm,shift cnt   Rn                              Post-indexed
  --------------------------------------------------------------------

      # Rn : base 주소를 가지고 있는 레지스터
        Rm : r15를 제외한 레지스터(옵셋), 부호값 사용
        expression : -4095 - +4096 범위의 Immediate 값(12Bit)
        shift : LSL, LSR, ASR, ROR, RRX
        cnt : 1..31 사이의 값.

  상당히 복잡한 내용입니다. 표에서 Mode 부분이 실제 어셈블러에서 사용하
  는 명령의 형식이라고 보시면 됩니다. 각 모드별로 예제를 들어서  설명하
  도록 하죠.

  1) Pre-Indexed Addressing Mode

    이 모드에서는 Rn을 베이스주소로 사용합니다. 여기에  더해서  옵셋을
    지정하거나, 혹은 지정하지 않을 수 있습니다. 옵셋을 사용할  경우에는
    해당 옵셋을 베이스 주소에서 더하도록 하거나 뺄 수 있는데, 위의 표에
    서 +, - 기호가 그것을 의미합니다.

    옵셋은 부호가 있는 12Bit Immediate값을 사용하거나 레지스터를 지정해
    서 해당 레지스터의 내용으로 사용할 수 있습니다. 또한 레지스터를  옵
    셋으로 사용하는 경우에는 Shift 시켜서 적용시킬 수 있습니다. 관련 내
    용을 다시 확인하고 싶으신 분들은 데이터 전송명령의 오퍼랜드 2 에 대
    한 설명을 다시 확인하시길 바랍니다.

    Ex) LDR     r0,[r1]         ; r1을 베이스로 사용하고 옵셋은  지정하
                                  지 않는 형태입니다. r0에 r1을  번지로
                                  하는 워드(4바이트)를 읽어드립니다.

        LDR     r0,[r1,#132]    ; 이번에는 옵셋으로 132를 지정한 형태입
                                  니다.

        STR     r0,[r1,r2]      ; 베이스는 r1, 옵셋은 r2를 사용한  형태
                  입니다. 즉 *(r1+r2)=r0 와 같은 의미..

        LDR     r0,[r1,r2,LSL #2] ; 베이스 r1, 옵셋은 r2<<2 의 형태.

    이번에는 Write-Back 기능에 대해서 알아보겠습니다. LDR명령의 경우 옵
    션으로 Write-Back 을 지정할 수 있는데, 지정할 경우 원래 베이스에 옵
    셋을 더한 값을 다시 베이스 레지스터로 넣는 기능을 합니다. 제 생각에
    는 이 기능이 C에서 ++와 같은 의미라 생각되는데요... 글세 쓰기  나름
    이겠지요. 다음은 예제입니다.

    Ex)
        1:              LDR     r0,=table_end
        2:              LDR     r1,=table
        3:
        4:              MOV     r2,#0
        5:loop          STR     r2,[r0,#-4]!
        6:
        7:              ADD     r2,r2,#1
        8:              CMP     r0,r1
        9:              BNE     loop
        10:
        11:             ...
        12:
        13:             ALIGN
        14:table        %       table_length*4
        15:table_end

      예제가 좀 길군요. 주의해서 보실 부분은 5번 라인입니다. 해당 명령
      은 STR    r2,[r0,#-4]! 이죠... r2를 r0를 베이스로 삼고  옵셋으로
      -4값을 사용했군요. r0가 가리키는 포인터가 실제 버퍼로 사용할  공
      간이 끝난 바로 다음을 가리키고 있으므로 -4를 하면 마지막 워드 엔
      트리 포인트가 됩니다. 그리고 주의하실점은 ! 를 사용한 것인데요..
      이것이 바로 Write-Back기능입니다. 위의 설명에 나와있듯이  베이스
      값(여기서는 r0가 되겠군요...)을 갱신하는 것인데요...

      예를 들어 1000번지부터 2개의 entry를 가정한다면, table은 1000 이
      될 것이고 table_end는 1008 번지가 될 것입니다. 이때  STR명령에서
      1008을 베이스로 -4를 옵셋으로 설정했으므로 실제로 r2값은 1004 번
      지부터 4바이트에 기록이 될 것입니다. 이후 Write-Back 옵션이 적용
      되어 해당 명령이 끝나면 r0값은 1004로 (1008-4) 바뀌게 됩니다.

      참... 여기서 Pre-Index Mode이기 때문에 실제 주소를 구할 때  옵셋
      을 먼저 빼 주었군요... 아무쪼록 이해 하셨기를 바라며... 다음으로
      넘어가렵니다.

  2) Post-Indexed Addressing Mode

    Post인덱스 모드의 경우에는 Pre인덱스 모드에 비해 Effective Address
    는 항상 Rn, 즉 베이스 어드레스를 나타내는 레지스터의 값입니다.  그
    리고 한가지 주의하실 점은 Post인덱스 모드의 경우엔 따로 !를 사용하
    지 않더라도 디폴트로 Write-Back 모드가 사용됩니다. 그렇겠죠?  Post
    인데 Write-Back이 안된다면... 옵셋을 사용할 이유가 없군요...

    Ex) LDR     r0,[r1],r2      ; 대괄호의 사용이 Pre 인덱스의  경우와
                                  다릅니다. 실제 수행되는 것은  r0에다
                                  r1을 주소로 하여 값을 읽어오고  다시
                                  r1에는 r2를 더해주는 일을 합니다.

        STR     r0,[r1],#20     ; [r1]:=r0, r1:=r1+20

        1:              LDR     r0,=table
        2:              LDR     r1,=table_end
        3:
        4:              MOV     r2,#0
        5:loop          STR     r2,[r0], #4
        6:
        7:              ADD     r2,r2,#1
        8: CMP     r0,r1
        9:              BNE     loop
        10:
        11:             ...
        12:
        13:             ALIGN
        14:table        %       table_length*4
        15:table_end

        마지막 예제는 위에서 나왔던 예제와 비슷하니 잘  분석해  보시길
        바랍니다.

  3) Relative Addressing Mode

    해당 Addressing 모드는 어셈블러가 적절히 지원하여 변환해 주는 모드
    라고 생각하시면 됩니다.

    Ex)         LDR     r5,ThreeCubed
  ...

     ThreeCubed DCD     27

     위와 같은 경우 실제로는 LDR r5,[PC,#constant] 형태의 코드로  번역
     해 줍니다. 즉 PC를 베이스로 삼아서 코드를 만드는  것이지요.  만약
     해당 심볼이 지정하는 범위가 너무 커서 상수로 지정할 수 없다면  어
     셈블을 할 때 에러를 내게 됩니다.

     또 많이 사용되는 표현으로 다음과 같은 표현이 있습니다.

     Ex)        LDR     r0,=0x12345678

     사실은 위의 예에서도 사용했었는데요... 이 경우 어셈블러가 해당 상
     수값을 특정 공간에 모아서 삽입 해 주고 (이공간을 Literal Pool이라
     하는군요) 역시 마찬가지로 PC를 베이스로 해서 명령코드를 만듭니다.



자.. 오늘은 이만 쓰렵니다. 사실 열두번째 강좌는 쓰기시작한지 몇 주만에
끝내게 되는군요... 중간중간 계속 일이 생겨서. 미뤄두고 있다가,  메일로
강좌를 재촉하시는 분들이 계셔서..(흑.. 감동)

암튼.. 다음강좌에 뵙도록 하겠습니다.

2007/10/19 - [임베디드/ARM] - ARM7 강좌 [11] : Instruction Set(5) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [10] : Instruction Set(4) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [9] : Instruction Set(3) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [8] : Instruction Set(2) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [7] : Instruction Set(1) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [6] : Exception(2) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [5] : Exception(1) (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [4] : 레지스터 (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 [3] : ARM7의 구조 (출처 : 디지털 동호회)
2007/10/19 - [임베디드/ARM] - ARM7 강좌 2 개요 (출처 : 디지털 동호회)
Posted by suvisor