Inline ASM Constraint 완전 정리표

이 글에서는 Linux 커널 기준으로 자주 사용하는 inline asm constraint를 정리한다.

GCC + Clang 공통 기준으로, 특히 Clang에서 주의해야 할 포인트를 포함한다.

1. 기본 구조

asm volatile (
    "asm template"
    : output operands
    : input operands
    : clobber list
);

구조는 항상 4파트다.

파트역할
template실제 asm 코드
outputsC ← asm
inputsC → asm
clobber깨지는 레지스터/상태

2. 출력 Operand 제약 (Output Constraints)

제약의미Clang 주의
"=r"레지스터에 출력가장 기본
"=m"메모리에 출력메모리 barrier 필요
"=&r"early-clobber입력보다 먼저 덮어씀
"+r"read/write (입출력 겸용)tied operand 대체용
"=a"특정 레지스터 (x86 eax)아키텍처 의존

가장 중요한 것: =r vs +r

=r

  • write-only
  • 입력과 같은 변수면 "0" 필요

+r

  • read + write
  • 같은 레지스터 사용을 가장 안전하게 표현
  • Clang 포팅 시 80%는 이걸로 해결

3. 입력 Operand 제약 (Input Constraints)

제약의미
"r"레지스터
"m"메모리
"i"즉시값 (컴파일 타임 상수)
"0"0번 output과 같은 레지스터
"1"1번 output과 같은 레지스터
"g"register or memory
"a"특정 레지스터

Tied Operand

: "=r"(val)
: "0"(val)

의미:

input이 0번째 output과 같은 레지스터 사용

Clang에서는 이것보다 +r이 더 안전하다.

4. Early-Clobber (=&r)

이건 매우 중요하다.

언제 필요한가?

asm이 출력 레지스터를
입력 읽기 전에 덮어쓸 때

asm volatile(
    "mul %2"
    : "=&r"(res)
    : "0"(a), "r"(b)
);

Clang은 early-clobber 누락을 더 잘 잡는다.

5. Clobber List 정리

: /* outputs */
: /* inputs */
: "memory", "cc"
clobber의미
"memory"메모리 상태 변경
"cc"condition code 변경
"rax"특정 레지스터 변경

memory clobber의 중요성

Clang은 최적화가 공격적이다.

GCC에서 되던 코드도
memory clobber가 없으면 reorder될 수 있다.

asm volatile("" ::: "memory");

= full barrier 효과

6. 자주 쓰이는 레지스터 제약 (아키텍처별)

x86

제약레지스터
"a"rax
"b"rbx
"c"rcx
"d"rdx
"S"rsi
"D"rdi

ARM64

제약의미
"r"x0-x30
"w"SIMD/FP reg
"Q"메모리 operand
"I"small immediate

ARM64는 Clang에서 IAS 영향 많이 받는다.

7. GCC에서 되지만 Clang에서 깨지는 대표 패턴

잘못된 tied operand

asm volatile("..."
             : "=r"(val)
             : "0"(val));

권장

asm volatile("..."
             : "+r"(val));

memory clobber 누락

asm volatile("mov %0, %%cr3" : : "r"(val));

수정

asm volatile("mov %0, %%cr3"
             :
             : "r"(val)
             : "memory");

early-clobber 누락

asm("mul %2"
    : "=r"(res)
    : "0"(a), "r"(b));

수정

asm("mul %2"
    : "=&r"(res)
    : "0"(a), "r"(b));

8. constraint 선택 가이드 (실전용)

상황추천
단순 계산"+r"
write-only output"=r"
입력과 같은 레지스터 필요"+r"
output이 먼저 덮어씀"=&r"
메모리 접근"m" + "memory"
CPU flag 변경"cc"

9. 커널 포팅 전략

벤더 커널 Clang 전환 시:

  1. "0" 패턴 → +r 우선 검토
  2. asm 에러 → early-clobber 의심
  3. 이상 동작 → memory clobber 확인
  4. ARM64 → IAS 문제 먼저 의심

10. 핵심 요약

Clang 포팅의 90%는 여기서 끝난다:

  • +r 적극 사용
  • early-clobber 정확히 지정
  • memory clobber 명확히 작성
  • tied operand 남용 금지

참조:

답글 남기기