ADRP
Summary
정의: PC 기준 상대주소를 페이지(4KB) 단위로 계산하여 레지스터에 로드하는 명령어. “Address of Page”의 약자임.
핵심 개념:
- ADR이 정확한 바이트 단위 주소를 계산하는 반면, ADRP는 4KB 페이지의 시작 주소만 계산함
- 결과 레지스터에는 하위 12비트가 0으로 마스킹된 페이지 정렬 주소가 저장됨
- 따라서 페이지 내부의 정확한 오프셋은 별도로 더해줘야 함 (보통
ADD명령어 사용)
왜 ADR만으로는 부족한가
범위 비교:
| 명령어 | 인코딩 단위 | 범위 |
|---|---|---|
| ADR | 바이트 단위 (21비트 offset) | ±1MB |
| ADRP | 페이지 단위 (21비트 offset, 각 페이지=4KB) | ±4GB |
계산 근거:
ADRP offset 21비트 × 페이지 크기 4KB(2^12)
= 2^21 × 2^12
= 2^33 바이트
= 약 ±4GB
동일한 21비트 offset을 쓰지만, 단위가 “바이트”가 아니라 “페이지”이기 때문에 4096배 더 넓은 범위를 커버함. 이게 ADR과 ADRP의 근본적 차이임.
ADRP + ADD 조합 패턴
동작 원리:
ADRP로 목표 주소가 속한 페이지의 시작 주소를 레지스터에 로드ADD로 페이지 내 정확한 오프셋(하위 12비트)을 더해 최종 주소 완성
예시:
adrp x0, message@PAGE // message가 속한 4KB 페이지 시작 주소 로드
add x0, x0, message@PAGEOFF // 페이지 내 오프셋 더해 정확한 주소 완성
macOS 표기법 참고:
@PAGE: 페이지 시작 주소 부분 지정 (ADRP용)@PAGEOFF: 페이지 내 오프셋 부분 지정 (ADD용)- 링커가 어셈블 시점에 이 값들을 실제 주소로 채워넣음
이전 ADR 논의와의 연결
지난 설명에서 언급한 대로, 실전 코드에서 .text(코드)와 .data(데이터) 섹션은 대부분 1MB 이상 떨어져 배치됨. 이 거리는 ADR의 범위를 초과하지만 ADRP의 ±4GB 범위 안에는 충분히 들어옴.
결론적 판단 기준:
- 로컬 함수 내부 라벨 참조 → ADR로 충분
- 전역 변수, 문자열 상수, 타 섹션 심볼 참조 → ADRP+ADD가 사실상 표준
이 때문에 Clang이 생성한 실제 어셈블리에서는 ADR보다 ADRP+ADD 조합이 압도적으로 자주 관찰됨.