ARM Core - 3. ARM Assembly 프로그래밍 기초 (2. ARM 어셈블리 기본 명령어 및 최적화)

2025. 3. 7. 13:28정보기술/하드웨어

2. ARM 어셈블리 기본 명령어 및 최적화


1. 데이터 이동 명령어 (MOV, LDR, STR)

1) MOV (Move) - 레지스터 간 데이터 이동

  • MOV 명령어는 즉시값(Immediate Value) 또는 레지스터 값을 다른 레지스터에 복사한다.

예제: MOV 사용

MOV R0, #10    ; R0에 10 저장
MOV R1, R0     ; R1 = R0
  • MOV R0, #10 → R0에 즉시값 10을 저장
  • MOV R1, R0 → R0 값을 R1으로 복사

2) LDR (Load) - 메모리에서 데이터 로드

  • LDR 명령어는 메모리에서 값을 읽어 레지스터에 저장한다.

예제: LDR 사용

LDR R0, =0x1000   ; R0에 주소 0x1000을 저장
LDR R1, [R0]      ; R1 = *R0 (메모리에서 값 로드)

3) STR (Store) - 데이터 저장

  • STR 명령어는 레지스터의 값을 메모리에 저장한다.

예제: STR 사용

LDR R0, =0x1000  ; R0에 메모리 주소 0x1000 저장
MOV R1, #42      ; R1 = 42
STR R1, [R0]     ; *R0 = R1 (메모리에 저장)

2. 산술 및 논리 연산 (ADD, SUB, AND, ORR, EOR)

1) ADD (덧셈) & SUB (뺄셈)

  • ADD: 두 값을 더한다.
  • SUB: 두 값을 뺀다.

예제: ADD & SUB

MOV R0, #5
MOV R1, #3
ADD R2, R0, R1  ; R2 = R0 + R1 (5 + 3 = 8)
SUB R3, R2, #2  ; R3 = R2 - 2 (8 - 2 = 6)

2) AND, ORR, EOR (비트 연산)

  • AND: 두 값의 비트 AND 연산
  • ORR: 두 값의 비트 OR 연산
  • EOR: 두 값의 비트 XOR 연산

예제: 비트 연산

MOV R0, #0b1100  ; R0 = 1100 (2진수)
MOV R1, #0b1010  ; R1 = 1010

AND R2, R0, R1   ; R2 = R0 AND R1  (1000)
ORR R3, R0, R1   ; R3 = R0 OR R1   (1110)
EOR R4, R0, R1   ; R4 = R0 XOR R1  (0110)

3. 제어 흐름 명령어 (CMP, B, BL, BX)

1) CMP (비교 연산)

  • CMP 명령어는 두 값을 비교하여 플래그(Zero, Negative 등)를 설정한다.

예제: CMP와 분기(B)

MOV R0, #10
MOV R1, #10
CMP R0, R1   ; R0 - R1 연산 수행 (결과: 0 → Z 플래그 설정)
BEQ equal    ; Z 플래그가 1이면 equal 레이블로 이동

2) BX (Branch and Exchange) - 복귀 및 모드 전환

  • BX LR함수에서 복귀할 때 사용
  • BX RnARM/Thumb 모드 전환 가능

BX를 이용한 ARM/Thumb 모드 전환

  • ARM 프로세서는 ARM 모드(32비트)와 Thumb 모드(16비트)를 지원한다.
  • BX 명령어를 사용하여 Thumb 모드로 전환할 수 있으며, LSB(Least Significant Bit, 최하위 비트)가 1이면 Thumb 모드로 전환된다.

예제: BX를 이용한 모드 전환

TST R0, #1       ; R0의 LSB가 1인지 확인
BXEQ R0          ; LSB가 0이면 ARM 모드 유지, 1이면 Thumb 모드 전환

4. 인라인 어셈블리 및 C/C++ 연동

C 또는 C++ 코드에서 인라인 어셈블리(Inline Assembly)를 사용하면 특정 연산을 최적화할 수 있다.

1) 기본 인라인 어셈블리 (GCC)

#include <stdio.h>

int main() {
    int a = 5, b = 3, result;
    __asm__("ADD %0, %1, %2" : "=r" (result) : "r" (a), "r" (b));
    printf("Result: %d\n", result);
    return 0;
}

2) 확장 인라인 어셈블리 (Extended Asm)

GCC의 확장 인라인 어셈블리는 입력/출력 제약을 명확히 지정할 수 있으며, 더 정교한 코드 최적화가 가능하다.

예제: 확장 인라인 어셈블리

#include <stdio.h>

int multiply(int a, int b) {
    int result;
    __asm__ volatile (
        "MUL %0, %1, %2\n\t"
        : "=r"(result)  // 출력 변수
        : "r"(a), "r"(b) // 입력 변수
        : "cc"  // 상태 플래그(clobber list)
    );
    return result;
}

int main() {
    int res = multiply(6, 7);
    printf("Multiplication Result: %d\n", res);
    return 0;
}
  • "=r"(result) → 출력 레지스터 (%0)
  • "r"(a), "r"(b) → 입력 레지스터 (%1, %2)
  • "cc" → CPSR(상태 레지스터) 변경 가능성 명시

5. ARM 어셈블리 최적화 기법

최적화 기법 설명
레지스터 활용 메모리 대신 레지스터 사용
루프 최적화 Unrolling(루프 전개) 적용
조건 실행 활용 분기(B) 대신 CMP + IT 사용
비트 연산 활용 MUL 대신 LSL(시프트 연산) 사용

예제: 곱셈 최적화 (LSL 활용)

MOV R1, #4
LSL R0, R1, #2  ; R0 = R1 * 4 (비트 쉬프트 사용)

6. 결론

  • MOV, LDR, STR을 이용한 데이터 이동
  • ADD, SUB, AND, ORR, EOR을 활용한 연산
  • CMP, B, BL, BX를 이용한 제어 흐름
  • BX를 활용한 ARM/Thumb 모드 전환 이해
  • GCC 확장 인라인 어셈블리 활용 가능
  • 최적화 기법(레지스터 활용, 비트 연산 등) 적용 가능

ARM 어셈블리를 사용하면 고성능, 저전력 코드 최적화가 가능하며, C/C++ 연동을 통해 효율적인 개발이 가능하다.