ARM의 데이터 이동명령어는 크게 3가지로 나눌 수 있습니다.
  • 한 레지스터를 이동시키는 명령어
  • 여러개의 레지스터를 이동시키는 명령어
  • Swap 명령어

 첫번재의 move single register instruction이 가장 일반적입니다. 그리고 그렇게 크게 어려운 점은 없다고 봐도 될 것입니다. 그리고 세번째로 나와 있는 스왑(SWAP)명령어는 사용자로서는 잘 사용하지 않고 다중프로세서 시스템에서 공유 데이터 관리를 위해 주로 사용됩니다.
 하지만 이 챕터. 아니 명령어를 이해하는데 가장 걸림 돌이 되는 것은 무슨 프로그래밍이든 구조든지 메모리 access가 아닐까 생각됩니다. 특히 두번째에 언급했던 mutiple register road and store는 많은 데이터를 블럭단위(연속된 메모리주소)로 이동하는데 적합하고 ARM을 더욱 효율적으로 만들었습니다.
 이 Multiple Register Road and Store를 조금 더 부연설명을 하자면 최대 16개(레지스터의 가용갯수)까지 가능합니다.

 ARM에서의 이동명령어는 모두 레지스터를 이용한 간접 주소지정모드를 사용하게 된다. 레지스터 간접주소지정 방법은 한 레지스터에 메모리 주소값을 넣어두고 그 값을 주소로 이용하여 메모리에서 데이터를 읽어서 오퍼랜드를 가져오거나 메모리에 데이터를 써서 오퍼랜드를 저장합니다. 이때 메모리 주소값이 들어가 있던 레지스터를 베이스 레지스터(Base Register)라고 합니다.

 일단 ARM에서 유일안 메모리 접근 명령어인 LDR와 STR 명령어의 예를 살펴보도록 하겠습니다.

 LDR r1,[r2] ; r1 <- memory[r2]

 이 위의 예제는 r1에 다가 저장을 하는데 r2에 있는 값이 아니라 현재 r2에는 메모리의 주소값이 저장되어 있을 겁니다. 그 주소값이 가르키는 값을 r1에다가 저장하라는 것입니다. C 언어로 이야기 하자면 포인터 정도가 될 것 같습니다. 아, 그리고 STR도 한번 살펴보고 가도록 하겠습니다.

STR r1,[r2] ; memory[r2] <- r1

 이 위의 예제는 메모리에 값을 저장하는 예 입니다. LDR의 예제와 마찬가지로 r2가 가르키는 곳에 r1값을 저장하고 있습니다.  여기서 중요한 것은 데이터의 이동방향입니다. 이것을 헤깔리지 않도록 하는것이 중요합니다.

 
 이번에는 그렇다면 위의 예제에서 어떻게 r2에 memory 주소를 넣을 수 있을지 생각해보도록 하겠습니다. 첫번째로는 프로그램의 시작위치에서 계산하는 방법이있습니다. 이것이 가능한 이유는 r15가 pc, 즉 프로그램이 시작되는 부분을 가르키기 때문에 여기서 뺄셈을 해서 사용하면 됩니다.
 하지만 이 방법은 번거롭기도 하고 사용자가 하기에는 자칫잘못했다가는 엉키는 작업입니다. 그래서 생긴 명령어가 ADR 명령어 입니다.
 원래 명령어라는 것은 CPU가 처리하는 것 입니다. 하지만 이 ADR 이라는 명령어는 CPU에 명령하는 것이 아닙니다. 바로 컴파일러에게 알려주는 것입니다. 그래서 이 ADR명령어를 슈도(pseudo)명령어, 즉 가상명령어라고 합니다. 이 ADR 명령어 사용방법을 알아보기 위해 예제를 하나 제시하겠습니다.
 
ADR r1, TABLE1 ;

 r1에 TABLE1의 주소값을 대입합니다. 사용자는 TABLE1의 주소값을 모릅니다. 하지만 ARM은 알고 있습니다. 사실 사용자는 알 필요가 없습니다. 굳이 알고 싶다면 r1을 출력하면 되지만 컴퓨터가 알아서 해주는데 굳이 TABLE1의 주소를 알 필요는 없습니다. 이렇게 사용자가 사용가능한 메모리의 주소값을 얻었습니다.

 
그럼 이제는 이 r1의 다음 주소를 알아내는 방법입니다. 이것을 base plus offset 주소지정이라고 합니다.
 다음 중 r2에 r1의 다음주소에 있는 값을  저장 하는 코드는 무엇일까요? 

  1. LDR r2,[r1,#1]
  2. LDR r2,[r1,#4]
  3. LDR r2,[r1,#16]
  4. LDR r2,[r1,#32]

일단 생각을 해보도록하자. r1의 주소가 만약 0x1000 이라고 한다면 r1,#1은 0x1001이 될것입니다. 오, 이거 그럴사 합니다. 하지만 ARM에서 사용하는 값들은 32bit의 길이로 저장됩니다. 오! 그렇다면 정답은 4번 r1,#32 가 되어 0x1032? 땡! 아닙니다. 왜냐하면 일반적으로 주소값을 사용할때는 bit단위가 아닌 byte단위를 사용하게 때문에 답은 2번 r1,#4 즉 0x1000 번지의 다음번지는 0x1004가 됩니다.

 이렇게 base plus offset주소를 지정하는데 3가지 방법이 있습니. 지금 방금 사용한 방법이 pre-indexing이라고 합니다.

 pre-indexing이란 명령어를 실행하기 전에 base 에다가 Offset을 더해 주소에 있는 값을 레지스터에 더하는 것입니다.
 그다음은 Post-indexing 입니다. post-indexing이란 pre-indexing의 반대 개념으로 base 값만으로 명령어 실행후 base 값에 offset을 더해 base에 저장합니다. 그리고는 다음 실행시 반영합니다. 즉 저장후 base 값을 update 시키는 것 입니다. 예를 들어 보겠습니다.

 LDR r0,[r1],#4 ;
 
 이렇게 하면 r0에 r1의 값을 저장 한 후 r1의 값을 그 다음주소값으로 update 시켜 줍니다. 그래서 다음 실행시 반영이 됩니다. 

 그리고 마지막으로 auto-indexing이 있습니다. auto-indexing은 두개를 합쳐놓은 것인데 일단 pre-indexing으로 계산을 한 후에 base register를 update 합니다. 다시 정리 해 보자면

pre-indexing은 update하여 주소에 있는 값을 register에 저장하고
post-indexing은 주소에 있는 값은 register에 저장 한 후 base값을 update 합니다.
auto-indexing은 update하여 주소에 있는 값을 register에 저장하고 또 base 값을 update하게 됩니다.

이 auto-indexing을 사용하는 방법은 pre-indexing의 명령어 뒤에 '!'를 넣어주면 됩니다.

 LDR r2,[r1,#4]! ;



 


  


'ARM(Advanced RISC Machine)' 카테고리의 다른 글

2.1 ARM 데이터 처리 명령어  (0) 2009.10.23
2 - ARM과 Assembly  (0) 2009.10.23
1.4 - ARM의 Instructions  (0) 2009.10.23
1.3 - ARM의 Register  (0) 2009.10.23
1.2 - ARM과 Bekeley RISC  (0) 2009.10.23

+ Recent posts