[컴퓨터구조] ARM 명령어 정리
Undergraduate lectures

[컴퓨터구조] ARM 명령어 정리

이 글은 필자가 직접 학교 수업(조동섭 교수님의 '컴퓨터 구조')을 듣고 정리한 글입니다. 

ARM 명령어는 총 3가지로 분류하여 설명된다. 이는 모두 어셈블리 언어를 통하여 작성되므로, 명령어를 숙지하는 것은 필수적이다. 검색하기 위해서라면 Ctrl+F를 눌러서 바로 접속하도록 하는 것을 추천한다.

- Data Transfer Instruction: 데이터를 로딩하고, 저장하는 과정에서 쓰이는 명령어를 뜻한다.

- Data Processing Instruction: 데이터의 값을 계산하고, 논리적인 계산이나, 값 복사, 비교, 비트 옮기기와 관련된 모든 명령어를 일컫는다.

- Control Flow Instruction: Branch와 같은 조건문을 처리할 때 어떤 명령어를 이용하여 접근하는지 알려준다.

+ 추가적으로 공부에 도움이 될 응용 코드들을 넣어놓았다.

 

시작하기 전에 개인적으로 헷갈렸던 부분 정리

  • 1. r0,r1 등등 r이 붙는 단어들은 register를 뜻하며, 뒤의 숫자는 register 32개 중 몇 번째인지를 의미한다. 각각의 register는 자신의 역할을 가지고 있기에 특정 register가 나오는 것은 그 명령에 관여를 하는 register라고 생각하면 된다.
  • 2. 명령어가 수행되는 것을 보면(명령어 설명을 보면) =을 기준으로 좌항과 우항이 나뉘어져있다. 이는 우항이 좌항값에 들어가고, 우항의 값들은 변함이 없다. 예를 들어 r0 = r1+r2이면, r1+r2값이 r0에 들어갈 뿐, r1과 r2의 값은 변하지 않는다.
  • 3. register나 data memory값들이 아닌 N,Z,C,V는 CPSR(Program Status Register)라는 다른 register값들이 정하는 것으로, comparison이나 계산 코드에서 자주 쓰인다.
  • 4. 코드 자체는 32bit로 0~31까지로 naming 되어있다. 31~0으로 코드 네이밍 된것을 주의하자! address들은 모두 4씩 증가되는 형태로 쓰인다.

 


1. Data Transfer Instruction

 

명령어 명령어 설명
LDR r0, [r1] r0 = mem[r1] 즉, 오른쪽에서 왼쪽 방향 대입
STR r0, [r1] mem[r1] = r0 즉, 왼쪽에서 오른쪽 방향 대입

ADDRESSING MODE 응용 | BASE-PLUS-OFFSET ADDRESSING

명령어  
LDR r0, [r1, #4] r0 = mem[r1+4]                               Pre-indexed Addressing
LDR r0, [r1, #4]! r0 = mem[r1+4]  이후에 r1 = r1+4       Auto-indexing(!은 "같이 변한다"의미)
LDR r0, [r1], #4 r0 = mem[r1] 이후에 r1 = r1+4           Post-indexed Addressing([]은 "적용"의미)
명령어 {} 순서대로 계산
LDMIA r1, {r0,r2,r5} Increment After 적용만!
LDMIA r1!, {r0,r2,r5} Increment After 적용 후 포인터 증가
LDMIB r1!, {r0,r2,r5} Increment Before 포인터 증가후에 적용(IA와 시작점 다름)
LDMDA r1!, {r0,r2,r5} Decrement After 적용 후 포인터 감소
LDMDB  r1!, {r0,r2,r5} Decrement Before 포인터 감소후에 적용(DA와 시작점 다름)

 


2. Data Processing Instruction

1) 수 계산

명령어 명령어 설명
ADD r0, r1, r2 r0 = r1+r2
ADC r0, r1, r2 r0 = r1 +r2+C
SUB r0, r1, r2 r0 = r1-r2
SBC r0, r1, r2 r0 = r1-r2+C-1
RSB r0, r1, r2 r0 =r2-r1
RSC r0, r1, r2 r0 =r2-r1+C-1
MUL r0, r1, r2 r0 =r1*r2
MLA r0, r1, r2, r3 r0 = r1*r2 + r3

+ register 값 말고도 다양한 값들이 적용가능하다.

ADD r3, r3, #1           ;r3 = r3+1

ADD r3, r2, r1, LSL #3    ;r3 = r2+2^3*r1  즉, r3+r1의 값이 아닌 2의 세제곱(LSL #3)을 r1에 곱한 값을 대입한다. LSL은 4)를 참고

 

2) 논리(Logical) 계산

명령어 명령어 설명
AND r0, r1, r2 r0 = r1 AND r2
ORR r0, r1, r2 r0 = r1 OR r2
EOR r0, r1, r2 r0 = r1 NOR r2
BIC r0, r1, r2 r0 = r1 AND ~r2

- 출제 문제 형식 

r1 = 0x11111111   r2 = 0x01100101 

BIC r0, r1, r2                           AND r0, r1, r2                                        ORR r0, r1, r2                             EOR r0, r1, r2

 

3) 값 옮기기

명령어 명령어 설명
MOV r0, r1 r0 = r1      ;r1 값이 r0값으로 들어간다.
MVN r0, r1 r0 =~r1     ;r1의 보수 값이 r0값으로 들어간다.

 

4) 비교하기

이 명령어들은 r1, r2값을 세팅하는 것이 아닌, CPSR의 값들을 세팅한다.

CPSR은 N, Z, C,V 등등으로 나뉘며, 그 중 대표적인 Z는 zero의 여부, C는 carry의 여부, V는 overflow의 여부를 확인한다. 이들은 계산문제에서 계산 값의 상태를 적용할 때에 특히나 많이 사용된다.

명령어 명령어 설명
CMP r1, r2 set (N,Z,C and V) on r1-r2     ;r1-r2의 값을 비교, 즉 r1의 값이 r2보다 큰지 확인
CMN r1, r2 set (N,Z,C and V) on r1+r2   ;r1+r2의 값을 비교, 즉 r1의 값이 -r2의 값보다 큰지 확인
TST r1, r2 set (N,Z,C and V) on r1 AND r2    ;r1 AND r2의 값을 비교
TEQ r1, r2 set (N,Z,C and V) on r1 XOR r2     ;r1 XOR r2의 값을 비교

 

5) 비트 옮기기

위에서 말했던 32bit의 코드를 shift하는 방식을 뜻하며 총 

https://www.blackvoxel.com/view.php?node=1594 의 자료를 참고하였다.

LSL은 logical shift left로 31~0의 순으로 정렬된 코드 중 제시된 값만큼 왼쪽으로 밀어내며 비어있는 코드는 0으로 처리하고, (ASL은 arithmetic shift left로 동일하게 작용된다.)

LSR은 logical shift right로 31~0의 순으로 정렬된 코드 중 제시된 값만큼 오른쪽으로 밀어내며 비어있는 코드는 0으로 처리, (ASR은 arithmetic shift right은 왼쪽에 비어있는 코드를 모두 1로 처리!!)

ROR은 rotate right로 오른쪽으로 밀어서 나온 값들을 왼쪽에 비어있는 칸들에 다 삽입하는 방식이다.(ROL은 왼쪽으로 미는 것으로 동일하게 작용된다.)

 

- 적용방식: 코드 자체로 쓰이지 않고 다른 코드들 사이에 끼어들어간다.

ex. ADD r5, r5, r3, LSL r2    ;r5 = r5 + r3*(2^r2) 

 


3. Control Flow Instruction(Branch Instructions)

명령어  
B Branch: PC = label
BL Branch and link: PC = label  & (label이후 코드가 끝난후 돌아오기 LR = BL)
BX Branck and exchange
BLX Branch with link and exchange

 

 


도움이 될 응용코드들

 

1. 62bit code계산하기(r1, r0)와 (r3, r2)로 각각 이루어진 64 bit codes)

ADDS r2, r2, r0              ;앞의 32bit수인 r2와 r0의 값을 계산(이 와중에 계산에서 나오는 carry값 확인)

ADC r3, r3, r1                ;위에서 나온 올림수인 carry를 바탕으로 뒤의 32bit수인 r3와 r1의 값을 계산

 

2. 2의 제곱수가 아닌 수 계산 ex. 35, 7...

ex. 35를 계산하려 할 때

SOL 1.

MUL r3, r0, r1      ; r3 = r0 * r1(=35,미리 적용되어있어야함)

SOL 2. 35 = 5*7(5를 곱한 후 후에 7을 곱하기

ADD r0, r0, r0, LSL #2             ; r0 = r0 + r0*4 = 5*r0

RSB r0, r0, r0, LSL #3              ; r0 = - r0 + r0 * 8 = 7*r0

 

오타나 오류는 댓글로 남겨주세요!! 감사합니다:)