from palette import colorful_colors

[마이크로프로세서] ARM 명령어 모음 + 지시어, flag register 본문

EE 학부과목/마이크로프로세서

[마이크로프로세서] ARM 명령어 모음 + 지시어, flag register

colorful-palette 2023. 4. 19. 12:13

해당 포스팅은 RISC계열 명령어중 ARM 명령어들을 정리한 포스팅입니다.

 

1. 기본 명령어(move, load, store)

MOV Rm or Op2 : register값(Rm) 혹은 immediate value (Op2) 값을 레지스터로 복사

예시:
MOV R2 #25   ; 25를 R2 레지스터에 넣는다
MOV R2 #0x87 ; 16진수 87을 R2 레지스터에 넣는다

 

LDR Rd [Rx] : (Rx레지스터의 값)에 해당하는 주소에 있는 값을 Rd로 불러온다. 

 

STR Rx [Rd]: Rx값을 (Rd레지스터 값)에 해당하는 메모리 주소에 저장한다.

 

1-2. 추가적인 load, store instruction:

LDRB / LDRH Rd [Rx] : (Rx레지스터의 값)에 해당하는 주소에서 1byte / 2byte만 해당하는 값을 Rd로 불러온다. 나머지 비트는 0으로 채운다.

 

STRB / STRH Rx [Rd]: Rx값을(1byte / 2byte크기의  값) Rd레지스터의 값에 해당하는 주소에 저장한다. 나머지 주소엔 그대로 데이터를 보존한다.

 

1-3. Sign Extention:

LDRSB/ LDRSH Rd [Rx] : Rx레지스터의 값 (1byte/ 2byte 크기다)에 해당하는 주소에 있는 값을 Rd로 불러오고 sign을 유지한다. 

 

2. CPSR (flag register)

연산자 뒤에 S를 붙이면 (예시: ADDS) 업데이트되는 레지스터 비트다. (1또는 0 표시)

N: 연산 결과값이 음수면 1이 된다.

Z: 연산 결과값이 0이면 1이 된다.

C: unsigned 연산에서 올림수가 발생할때, carry가 발생할때 1이 된다.

V: signed 연산에서 엉뚱한 값이 나올때, overflow가 발생할때 1이 된다. (예시: 음 + 음 = 양, 양 + 양 = 음)

 

3. Arithmetic Instruction(산술 연산자)

※OP2에는 register가 올 수도 있고 immediate value가 올 수도 있다

 

ADD Rd Rn OP2:  register값(Rn) + Op2값을 Rd에 넣는다

 

SUB Rd Rn OP2: register값(Rn) - Op2값을 Rd에 넣는다

 

ADC Rd, Rn, Op2: Rn값 + OP2값 + C를 Rd에 넣는다.

ADD와 연동해서 보통 큰 자릿수의 덧셈을 할때 많이 이용한다. 예를 들어 이전에 ADD에서 올림수가 발생해서 C가 1이 되었다면 ADC를 계산할때 1을 추가로 더해주는 것이다. (레지스터끼리의 올림수 개념)

 

SBC Rd, Rn, Op2: Rn값 - Op2값 -1 + C를 Rd에 넣는다. 

SUB와 연동해서 보통 큰 자릿수의 뺄셈을 할때 많이 이용한다. 예를 들어 이전에 SUB에서 A - B를 할때 A>=B면 C가 1이고 빌림수가 발생하지 않는 대신, A<B면 C가 0이고 빌림수가 발생하게 된다. SBC는 이러한 빌림수를 의식해 -1을 빼주는 것이라고 생각하면 된다.

 

RSB Rd, Rn, Op2: SUB와 반대방향이다. Op2 - Rn 값을 Rd에 저장한다.

 

RSC Rd, Rn, Op2: SBC와 반대방향이다. Op2 - Rn - 1 + C 값을 Rd에 저장한다. 

 

MUL Rd, Rn, Rm : Rn값과 Rm값을 곱한 값을 Rd에 저장한다. 32bit보다 작은 결과가 나올때 사용한다.

 

UMULL RdLo, RdHi, Rn, Rm: Rn값과 Rm값을 곱한 값을 RdHi와 RdLo에 나눠서 저장한다. 32bit보다 큰 결과가 나올때 사용한다.

 

SMULL RdLo, RdHi, Rn, Rm: Rn값과 Rm값을 곱한 값을 RdHi와 RdLo에 나눠서 저장한다. 32bit보다 큰 결과가 나올때 사용한다. 단 이때 Rn값과 Rm값을 Signed로 생각하고 연산한다.

 

4. Logic Instruction(논리 연산자)

AND Rd, Rn, Op2: Rd에는 Rn과 Op2가 bit and한 결과가 저장된다. 주로 비트 마스킹 연산시 쓴다.

 

ORR Rd, Rn, Op2: Rd에는 Rn과 Op2가 bit or한 결과가 저장된다. 주로 원하는 비트들을 set할때 쓴다.

EOR Rd, Rn, Op2: Rd에는 Rn과 Op2가 bit or한 결과가 저장된다. 주로 원하는 비트들을 토글(1과 0 변경)할때 쓴다.

 

BIC Rd, Rn, Op2: Rd에는 Op2를 1의 보수로 취하고 Rn과 and한 값이 들어간다. 주로 원하는 비트들을 clear할때 쓴다.

 

MVN Rd, Op2: Rd에는 Op2의 1의 보수를 취한 값을 저장된다. 

 

5. Rotate and Baarrel Shifter (순환, 시프트 연산자)

5-1. logical shift: 

LSL Op2 : Op2 bit만큼 왼쪽으로 shift한다.

 

LSR Op2 : Op2 bit만큼 오른쪽으로 shift한다.

 

5-2. Arithmetic shift:

ASR Op2 : Op2 bit만큼 오른쪽으로 shift하지만 부호를 유지한다. 예를 들어 MSB가 1(음수)이었다면 오른쪽으로 shift해도 1이 계속 추가로 붙는다. 산술로 오른쪽 shift는 나누기 2를 하는 것과 같다.

 

5-3. Rotation:

ROR Op2: Op2 bit만큼 오른쪽으로 밀어낸 비트를 다시 앞에 붙이고, 그 비트는 C에 임시로 저장한다.

 

RRX Op2 bit만큼 오른쪽으로 순환하므로 ROR과 비슷하지만, C를 거쳐서 순환한다. 즉 레지스터 32bit + C 1bit = 33bit로 이용이 가능하다. 

 

※ 일반적인 MOV, ORR, AND, ... 도 명령어에 4bit의 rotation에 해당하는 비트가 있기 때문에 rotationd을 할 수 있다!

명령어 , Rn, Op2, Rotategkf 비트를 적어주면 된다.

예시: 
MOV R0, #0xFF, #2 ; 0xFF를 오른쪽으로 2bit shift한 값을 R0로 이동한다.
예시2: 
ORR R1, R1, #0x43, #24 ; 0x43을 오른족으로 24bit 이동한 값과 R1을 or 연산한 값을 R1에 저장한다.

 

 

 

6. Branch, Loop (분기 연산자) 

조건문과 반복문에 사용되는 B 계열 연산자다.

A와 B가 있다면 A와 B의 크기를 서로 비교해서 branch(분기)한다. 

 

6-1. conditional branch: (flag register의 값들을 보고 조건적으로 분기한다)

BCS 또는 BHS:   A>=B , C= 1일때 branch한다.

 

BCC 또는 BLO:   A<B , C= 0일때 branch한다.

 

BEQ:   A=B ,   Z= 1일때 branch한다.

 

BNE:   A!=B , Z= 0일때 branch한다.

 

BLS:   A<=B , C= 0 이거나 Z = 1일때 branch한다.

 

BHI:   A>B , C= 1이고 Z=0일때 branch한다.

 

CMP Rd, Op2: 마찬가지로 Rd와 Op2만 비교하지만, SUB등과 달리 추가적인 레지스터 저장 없이 flag register만 업데이트한다.(S를 안 붙여도 flag register가 업데이트된다.) 

 

 

6-2. unconditional branch: (무조건 분기)

B offset : 타겟주소로 이동한다. 타겟주소의 주소는 offset에 담은 주소 x 4  + fetch에 있는 PC주소이다.

(x 4를 하는 이유는 명령어는 4씩 증가하므로 뒤에 00이 붙어 x4를 한 것과 같고, fetch에 있는 PC주소를 더하는 이유는 파이프라인때문에 B가 실행될때 가져오는 PC주소는 fetch에 있기 때문)

예시1:
'B 0x00000002' 명령어의 주소가 0x00000004일때: 
이동하는 주소 = 0x00000002 x 4 + 0x 0000000C= 0x00000014
(0x00000004가 excute될때 fetch되는 명령어의 주소는 2단계 더 뒤인(4x2) 0x0000000C니깐)

예시2:
'B 0xFFFFFFFC'명령어의 주소가 0x 00000010일때:
이동하는 주소 = -4(0x FFFFFFFC는 -4) x 4 + 0x00000018 = -0x10 + 0x00000018 =  0x00000008
(0x00000010가 exectue될때 fetch되는 되는 명령어의 주소는 2단계 더 뒤인(4x2) 0x00000018이니깐)

 

BX Rn: Rn으로 바로 분기

 

BL  subroutine: Link register에 되돌아올 주소를 저장하고 sobroutine으로 떠난다. Bx LR로 다시 돌아온다.  

 

 

7. Asembler Directives(지시어)

아래의 3개의 지시어는 실제 메모리 공간에 저장되는 코드는 아니다. 그냥 어셈블리어에게 해당 라인(들)은 어떻게 쓸거다! ~ 명령하는 것.

 

AREA: 일정한 메모리 공간을 어떻게 쓸건지 약속한다. 데이터 저장 공간으로 쓸건지, 명령어로 쓸건지, ...

(예시: AREA MY_ASM_PROG1, CODE, READONLY ; 다음 AREA 명령이 나올때까지 해당 공간을 code(명령어), readonly로 쓰겠다는 뜻)

 

EQU: costant한 변수를 지정시 사용한다. C에서 #define과 비슷하다.

(예시: DATA1 EQU 0x39 ; 0x39를 DATA1이라는 이름으로 쓴다는 뜻.)

 

RN: 레지스터의 이름을 지정할때 사용한다.

(예시: VAL1 RN R1 ; R1 레지스터를 앞으로 VAL1이라고 부르겠다는 뜻)

 

7-1. Asembler Data Allocation Directives

DCB: 해당 주소 포함 1byte 지정해서 사용한다는 뜻

 

DCW: 해당 주소 포함 2byte 지정해서 사용한다는 뜻

 

DCD: 해당 주소 포함 4byte 지정해서 사용한다는 뜻.

예시:
label의 주소가 0x10 이라고 할때:
label DCB 5, 6, 7 ; 5는 0x10, 6은 0x11, 7은 0x12로 저장된다.

 

SPACE: 원하는만큼 공간을 띄운다

 

AlIGEN: 다음 2byte 혹은 4byte공간을 이어붙인다.

예시: 
ALIGN 2 ; 현재주소와 다음주소, 총 2byte공간을 할당한다. SPACE 1과 의미가 같다.