tmxklab
ARM Assembly 정리 (기초) 본문
1. ARM(Advanced RISC Machine)
- 임베디드 기기에 주로 사용되는 RISC 프로세서
- 모바일 기기 또는 IoT 디바이스에도 사용됨
- 저전력을 사용하도록 설계됨
1) Register
r0 ~ r15까지 총 16개의 범용 레지스터를 가지고 있으며 다음 3가지의 레지스터는 특수 용도로 사용된다.
- r13(SP, Stack Pointer) : 스택의 주소를 저장하는 레지스터, ESP와 비슷한 역할, 현재 Stack을 어디까지 쌓아 두었는지 가리킴
- r14(LR, Link Register) : 함수 호출시 되돌아갈 함수의 주소가 저장되는 레지스터, 함수 호출 전 LR에 리턴 주소 저장하고 branch(jump)
- r15(PC, Program Conuter) : 현재 어디를 수행하고 있는지 가리키는 레지스터, EIP와 비슷한 역할, 현재 Instruction을 Fetch해 온 위치를 가리키고 있음(실행하는 위치가 아니라 Fetch해온 위치를 가리킴)
- SPSR(Saved Program STatus Register) : CPSR값을 저장해두는 역할로 CPSR을 backup할 때 사용됨
- CPSR(Current Program Status Register) : 연산결과, IRQ, 동작모드 등을 저장해두는 역할을 하는 상태 레지스터
① N(Negative) : 연산결과가 마이너스인 경우 set
② Z(Zero) : 연산결과가 0인 경우 set
③ C(Carry) : 연산결과에 자리 올림이 발생한 경우 set
④ V(oVerflow) : 연산 결과가 overflow가 발생하였을 때 set
⑤ T(sTate bit) : ARM mode인지 Thumb mode인지 나타내는 field
⑥ M 0~4(Mode bits) : 현재 SVC인지, UND인지, ABT인지 등을 나타냄, 현재 CPU의 상태를 나타냄
2) Thumb mode, ARM mode
ARM에서 사용되는 2가지 모드인 Thumb mode와 ARM mode가 존재한다. ARM mode는 32bit RISC machine이고 Thumb mode는 ARM mode의 반쪽짜리인 16bit RISC machine이다.
32bit ARM을 만들어 냈을 당시, 임베디드 계열에서 16bit가 대세였다. 결국 ARM사에서 16bit bus line을 가진 Memory에서도 효율적으로 사용할 수 있도록 ARM명령어들을 16bit로 압축한 명령어 set을 발표하게 된다. 그것이 바로 Thumb mode이다.
2-1) Thumb mode - 16bit
- register : r0 ~ r7(8개)
2-2) ARM mode - 32bit
- register : r0 ~ r15(16개)
2. ARM Assembly
1) 데이터 처리 명령어
1-1) 산술연산
- ADD(Addition)
- ADD <dest>, <op1>, <op2> → dest = op1 + op2
- ADC(Addition with Carry)
- ADC <dest>, <op1>, <op2> → dest = op1 + op2 + carry
- SUB(Subtraction)
- SUB <dest>, <op1>, <op2> → dest = op1 = op2
- SBC(Subtraction with Carry)
- SBC <dest>, <op1>, <op2> → dest = op1 - op2 - !carry
- RSB(Reverse Subtraction)
- RSB <dest>, <op1>, <op2> → dest = op2 - op1
- RSC(Reverse Subtraction with Carry)
- RSC <dest>, <op1>, <op2> → dest = op2 - op1 - !carry
1-2) 논리 연산
- AND(Logical AND)
- AND <dest>, <op1>, <op2> → dest = op1 AND op2
- ORR(Logical OR)
- ORR <dest>, <op1>, <op2> → dest = op1 OR op2
- EOR(Logical XOR)
- EOR <dest>, <op1>, <op2> → dest = op1 XOR op2
- BIC(Bit Clear)
- BIC <dest>, <op1>, <op2> → dest = op1 AND (!op2)
1-3) Register 값 저장
- MOV(Move)
- MOV <dest>, <op1> → dest = op1
- MVN(Move Negative)
- MVN <dest>, <op1> → dest = !op1
1-4) 비교 연산
- CMP(Compare)
- CMP <op1>, <op2> → status = op1 - op2
- 추가 설명 : "op1 - op2"의 결과를 Status flag에 반영
- CMN(Compare Negative)
- CMN <op1>, <op2> → status = op1 - ( -op2) = op1 + op2
- 추가 설명 : "op1 + op2"의 결과를 Status flag에 반영
- TST(Test bits)
- TST <op1>, <op2> → Status = op1 AND op2
- 추가 설명 : "op1 AND op2"의 결과를 Status flag에 반영
- TEQ(Test Equivalence)
- TEQ <op1>, <op2> → Status = op1 XOR op2
- 추가 설명 : "op1 XOR op2"의 결과를 Status flag에 반영
2) 분기(branch) 명령어
- B(Branch)
- B label
- 추가 설명 1 : label이 있는 주소로 분기
- 추가 설명 2 : b r0와 같이 분기 주소로 레지스터 사용 x
- ex)
- B addr → jmp addr
- B . → 무한 루프( .은 제자리를 의미)
- BL(Branch with Link)
-
BL label
-
추가 설명 1 : 다음 명령의 주소를 LR에 저장하고 label의 주소로 분기
-
추가 설명 2 : bl r0와 같이 분기 주소로 레지스터 사용 x
-
추가 설명 3 : B와 달리 복귀한 주소 값을 R14(LR)에 저장
-
서브루틴 호출(BL label)
① 복귀할 주소를 R14(LR)에 저장
② 서브루틴의 주소를 R15(PC)에 저장
-
서브루틴 복귀(BX LR)
① R14(LR)의 값을 R15(PC)에 저장하여 복귀
-
3) 메모리 접근 명령어
- LDR(Load) : 메모리 → 레지스터(Load to Register)
- ex)
- ldr r0, [r1] : r1의 값을 주소로 참조하여 r0에 저장
- ldr r0, [r1], #4 : r1의 값을 주소로 참조하여 r0에 저장하고 r1에 4를 더함
- ex)
- STR(Store) : 레지스터 → 메모리(Store to Memory)
- ex)
- str r0, [r1] : r0의 값을 r1의 값을 주소로 참조하여 저장
- str r0, [r1], #4 : r0의 값을 r1의 값을 주소로 참조하여 저장하고 r1에 4를 더함
- ex)
4) 상태 플래그
- N : 연산 결과가 음의 값을 가질 경우 → Set 1
- Z : 연산 결과가 Zero인 경우 → Set 1
- C : 연산 결과가 Carry를 가질 경우 → Set 1
- V : 연산 결과 Overflow가 발생한 경우 → Set 1
+) 기타 ARM Assembly 명령어를 찾고 싶을 때 다음 링크를 참고하자
3. 참고자료
'Security > 02 Reversing' 카테고리의 다른 글
EAT(Export Address Table) (0) | 2021.08.06 |
---|---|
IAT(Import Address Table) (0) | 2021.08.04 |
RVA to RAW (0) | 2021.08.04 |
Window API 관련 (0) | 2021.04.18 |
[리버싱] 어셈블리어 설명 및 종류 (0) | 2020.02.03 |