ARMv8 A64 Quick Reference

ARMv8부터 새로 추가된 64비트 명령어 집합 A64(AArch64 상태에서 실행)는 기존 32비트 ARM/Thumb(A32/T32)과 문법이 상당히 다르다. 레지스터 이름, 조건 코드, 주소 지정 방식을 매번 ARM 공식 문서에서 찾아보기는 번거롭기 때문에, 자주 찾아보게 되는 항목만 골라 표로 정리해둔다. 세부 레지스터 구조는 이미 다룬 ARMv8 Registers, AArch64 레지스터 글로, ARM32 명령어 집합은 ARM Instruction Set 글로 넘기고, 이 글에서는 A64 고유의 니모닉 규칙·조건 코드·주소 지정 모드·자주 쓰는 명령어를 표로 정리한다.

니모닉 구성 규칙

A64 니모닉은 <name>{<subtype>} <container> 형태로 구성된다. 연산 이름과 서브타입은 니모닉이, 크기는 레지스터 이름이 나타낸다. 예를 들어 LDRSW는 Load(연산) + Signed Word(서브타입) 조합이다.

구분기호의미
정수 컨테이너W32비트 정수
X64비트 정수
SIMD/FP 컨테이너B8비트 스칼라
H16비트 스칼라 · half-precision
S32비트 스칼라 · single-precision
D64비트 스칼라 · double-precision
Q128비트 스칼라
Load/Store 서브타입B / SBbyte / signed byte
H / SHhalfword / signed halfword
W / SWword / signed word

레지스터 표기법 요약

범용 레지스터는 0~30번까지 Xn(64비트)/Wn(32비트)으로 부르고, 31번은 문맥에 따라 이름이 바뀐다. 상세 설명은 위 링크 글에서 다루므로 여기서는 표기만 정리한다.

의미32비트64비트
범용 레지스터 (0~30)WnXn
Zero 레지스터 (31번, 읽으면 0 / 쓰면 버림)WZRXZR
스택 포인터 (31번, base/일부 산술 연산에서만)WSPSP

X30은 아키텍처상 이름이 정해져 있지 않지만 관례적으로 링크 레지스터(LR, 함수 호출 시 복귀 주소)로 쓰인다. PC는 아예 이름이 있는 레지스터로 취급되지 않아 데이터 처리·load 명령의 destination이 될 수 없고, ADR/ADRP·리터럴 로드·분기 명령에서만 암묵적으로 읽힌다.

조건 코드

코드의미(정수)플래그 조건
EQ같음Z==1
NE다름Z==0
HS / CS부호 없음 크거나 같음 (carry set)C==1
LO / CC부호 없음 작음 (carry clear)C==0
MI음수N==1
PL양수 또는 0N==0
VS오버플로우 발생V==1
VC오버플로우 없음V==0
HI부호 없음 큼C==1 && Z==0
LS부호 없음 작거나 같음!(C==1 && Z==0)
GE부호 있음 크거나 같음N==V
LT부호 있음 작음N!=V
GT부호 있음 큼Z==0 && N==V
LE부호 있음 작거나 같음!(Z==0 && N==V)
AL / NV항상 참

ARM32와 달리 조건은 니모닉에 바로 붙지 않고 .으로 구분한다(예: B.EQ). 조건 플래그를 갱신하는 명령은 대신 S 접미사로 구분한다(예: ADDS).

주소 지정 모드

종류Immediate OffsetRegister OffsetExtended Register Offset
단순 레지스터(exclusive)[base{,#0}]
Offset[base{,#imm}][base,Xm{,LSL #imm}][base,Wm,(S|U)XTW {#imm}]
Pre-indexed[base,#imm]!
Post-indexed[base],#imm
PC-relative (literal)label

immediate offset의 비트 폭과 스케일링 방식은 명령어 종류마다 다르다.

비트 수부호스케일링Writeback대상
0exclusive / acquire / release
7signedscaled옵션register pair (LDP/STP)
9signedunscaled옵션single register (LDUR/STUR 등)
12unsignedscaled없음single register (LDR/STR)

scaled offset은 접근 크기의 배수로 인코딩되므로, 실제 바이트 오프셋 범위는 접근 크기(byte/half/word/double)에 따라 달라진다. Pre/post-indexed 형태는 register offset과 함께 쓸 수 없다.

자주 쓰는 명령어 빠른 참조

분류명령어동작
데이터 이동MOV Xd, Xn레지스터 이동 (ORR Xd,XZR,Xn의 alias)
MOVZ Xt, #imm{,LSL #pos}16비트 즉치값을 지정 위치에 넣고 나머지는 0
MOVK Xt, #imm{,LSL #pos}16비트 즉치값을 지정 위치에 넣고 나머지는 유지
MOVN Xt, #imm{,LSL #pos}16비트 즉치값을 넣고 비트반전
산술ADD/SUB Xd, Xn, Xm{,shift}덧셈/뺄셈
ADDS/SUBS연산 후 조건 플래그 갱신
CMP Xn, Xm비교 (SUBS XZR,Xn,Xm의 alias)
CMN Xn, Xm음수 비교 (ADDS XZR,Xn,Xm의 alias)
NEG Xd, Xm부호 반전 (SUB Xd,XZR,Xm의 alias)
논리/시프트AND / ORR / EOR Xd, Xn, Xm비트 AND/OR/XOR
MVN Xd, Xm비트 반전 (ORN Xd,XZR,Xm의 alias)
TST Xn, Xm비트 테스트 (ANDS XZR,Xn,Xm의 alias)
LSL / LSR / ASR / ROR Xd, Xn, #imm|Xm논리/산술 시프트, 회전
BIC Xd, Xn, XmXn AND NOT(Xm)
곱셈/나눗셈MUL Xd, Xn, Xm곱셈 (MADD Xd,Xn,Xm,XZR의 alias)
MADD / MSUB Xd, Xn, Xm, Xa곱셈-누산 / 곱셈-감산
SDIV / UDIV Xd, Xn, Xm부호 있는/없는 나눗셈 (0으로 나누면 결과 0, trap 없음)
MSUB로 나머지 계산remainder = 피제수 – (몫 × 제수)
Load/StoreLDR/STR Xt, addr레지스터 하나 로드/스토어
LDP/STP Xt1, Xt2, addr레지스터 쌍 로드/스토어 (ARM32의 LDM/STM/PUSH/POP 대체)
LDUR/STUR Xt, [base,#simm9]unscaled 9비트 offset 명시
LDXR/STXRexclusive load/store (락 구현용)
LDAR/STLRload-acquire / store-release (메모리 배리어 내장)
제어 흐름B label / BL label무조건 분기 / 분기+링크(X30에 복귀주소 저장)
BR Xm / BLR Xm레지스터로 분기 / 분기+링크
RET {Xm}서브루틴 복귀 (기본 X30)
B.cond label조건부 분기 (±1MiB)
CBZ / CBNZ Xn, labelXn이 0이면/아니면 분기
TBZ / TBNZ Xn, #bit, label특정 비트가 0이면/아니면 분기 (±32KiB)
SVC #immEL1(시스템)을 대상으로 예외 발생 (시스템 콜)

AArch32 → AArch64 명령어 대응표

ARM32(A32/T32) NEON·VFP 코드를 A64로 옮길 때 자주 찾게 되는 대응 관계만 추려봤다. 전체 대응표는 ARM 공식 문서 5.7.23절에 있다.

AArch32AArch64 (정수)AArch64 (부동소수점)
VADDADDFADD
VSUBSUBFSUB
VMULMUL (PMUL 포함)FMUL
VABSABSFABS
VNEGNEGFNEG
VAND / VORR / VEORAND / ORR / EOR
VMVNMVN (=NOT의 alias)
VCEQCMEQFCMEQ
VDUPDUP
VTSTCMTST
VTBL / VTBXTBL / TBX
VLD1..4 / VST1..4LD1..4 / ST1..4
VLDM / VLDRLDP / LDR
VSTM / VSTRSTP / STR
VCVT.s32.f32 (round to zero 고정)FCVTZS (그 외 FCVTAS/FCVTMS/FCVTNS/FCVTPS로 반올림 방향 지정 가능)

주의사항

  • 같은 연산이라도 32비트/64비트 형태는 서로 다른 opcode다. Wn에 쓰면 대응하는 Xn의 상위 32비트는 항상 0으로 채워진다(반대로 Wn을 읽을 때는 상위 32비트가 그냥 무시된다).
  • A64에는 ARM32/Thumb의 IT 블록 같은 조건부 실행이 없다. 조건부로 동작하는 것은 B.cond 계열 분기와 CSEL/CSINC/CCMP 같은 소수의 conditional data processing 명령뿐이다.
  • LDM/STM/PUSH/POP이 A64에는 없다. 여러 레지스터를 한 번에 옮길 때는 LDP/STP로 두 개씩 묶어서 처리한다.
  • PC는 이름 있는 레지스터가 아니라서 데이터 처리 명령이나 load 명령의 destination으로 쓸 수 없다. PC 상대 주소가 필요하면 ADR/ADRP나 리터럴 로드를 써야 한다.
  • 나눗셈 명령(SDIV/UDIV)은 0으로 나누면 예외 없이 결과가 0이 된다. 나머지 연산 명령은 따로 없고 MSUB로 직접 계산해야 한다.

마무리

A64는 ARM32와 니모닉 이름은 비슷해 보여도 조건부 실행 축소, LDM/STM 폐지, 32/64비트 opcode 분리처럼 세부 규칙이 다른 부분이 많다. 이 글에 정리한 조건 코드·주소 지정 모드·명령어 빠른 참조 표를 어셈블리 코드를 읽거나 인라인 asm을 작성할 때 1차 참고 자료로 쓰고, 레지스터 구조나 특정 명령어의 정확한 동작이 필요하면 위에서 링크한 상세 글과 ARM 공식 문서를 함께 확인하면 된다.

참고

답글 남기기