Skip to the content.

ASR 명령어 (Arithmetic Shift Right)

Summary

정의: 레지스터 값을 오른쪽으로 시프트하되, 부호 비트(최상위 비트)를 유지하며 빈 자리를 채우는 산술 시프트 명령어. 부호 있는(signed) 정수의 나눗셈이나 부호 유지 시프트 연산에 사용됨.


기본 문법

ASR Xd, Xn, #shift        // 즉치값만큼 시프트
ASR Xd, Xn, Xm             // 레지스터 값만큼 시프트
ASRV Xd, Xn, Xm             // ASR의 정식 명칭 (레지스터 버전), 어셈블러가 ASR로 자동 변환

32비트 버전: ASR Wd, Wn, #shift 형태로 동일하게 사용 가능.


LSR과의 핵심 차이 — 부호 처리

명령어 정식 명칭 빈 자리 채움 방식 용도
LSR Logical Shift Right 항상 0으로 채움 부호 없는(unsigned) 값
ASR Arithmetic Shift Right 부호 비트(N) 로 채움 부호 있는(signed) 값

예시 비교 (8비트 기준 단순화):

값: 0b10000000 (signed로는 -128, unsigned로는 128)

LSR #1 → 0b01000000  (64)         // 무조건 0으로 채움
ASR #1 → 0b11000000  (-64)         // 부호비트(1) 유지하며 채움

판단 기준: 데이터가 부호 있는 정수(signed)일 때는 반드시 ASR을 써야 함. LSR을 잘못 사용하면 음수 값의 부호가 깨져 완전히 다른 결과가 나옴.


“ASL”에 대하여 — 존재하지 않는 이유

결론부터: ARM64에는 ASL이라는 독립 니모닉이 존재하지 않음. 이는 설계 원리상 당연한 결과임.

이유:

정리:

방향 부호 없는 부호 있는
왼쪽 LSL LSL (동일)
오른쪽 LSR ASR (별도)

오른쪽 시프트에서만 LSR/ASR이 분리되는 비대칭 구조이며, 이 때문에 “ASL”이라는 대응 명령어가 애초에 필요 없어 존재하지 않는 것임.


ASR과 나눗셈의 관계

중요한 실전 활용: ASR #n은 부호 있는 정수를 2^n으로 나누는 연산과 (거의) 동일함.

asr x0, x0, #1     // x0 = x0 / 2  (signed, 산술적으로 근사)
asr x0, x0, #3     // x0 = x0 / 8  (signed)

주의할 함정: 음수를 나눌 때 ASR은 내림(floor) 방향으로 반올림하지만, C언어의 정수 나눗셈은 0 방향(truncation) 으로 반올림함. 즉:

-7 / 2 (C언어 기준) = -3   (0 방향으로 자름)
-7 asr 1 (산술 시프트)  = -4   (음의 무한대 방향으로 내림)

결과적 영향: 컴파일러가 signed 나눗셈을 최적화할 때 단순히 ASR만 쓰지 않고, 음수 보정을 위한 추가 명령어(ADD, CSEL 등)를 함께 생성하는 경우가 많음. 순수 ASR 단독으로는 C언어의 정수 나눗셈 의미론을 완벽히 재현하지 못하기 때문임.


예제 코드

.global _start
.align 2

.text
_start:
    mov x0, #-16          // x0 = -16 (signed)

    asr x1, x0, #2          // x1 = -16 asr 2 = -4  (부호 유지)
    lsr x2, x0, #2          // x2 = -16 lsr 2 = 매우 큰 양수 (부호 깨짐, unsigned 해석)

    mov x0, #0
    mov x16, #1
    svc #0x80

비교 결과 설명: 동일한 -16 값에 대해 ASR은 부호를 유지하여 -4라는 올바른 산술 결과를 내지만, LSR-16을 unsigned 64비트 값(매우 큰 양수)으로 취급하여 전혀 다른 결과를 만듦. 이 차이가 ASR과 LSR을 구분해서 써야 하는 근본적 이유임.


Shifted Register 형태로도 자주 활용됨

ASR은 단독 명령어보다 다른 명령어의 shift operand로 결합되어 더 자주 관찰됨:

add x0, x1, x2, asr #3     // x2를 산술 시프트 후 x1과 덧셈
sub x0, x1, x2, asr #1

이런 결합형 사용 때문에 ASR 단독 명령어 형태보다 다른 산술 명령어의 부속 옵션으로 등장하는 빈도가 더 높은 편임.