اسمبلر داخلی
معرفی
Wave의 인라인 어셈블리는 asm { ... } 블록으로 작성합니다.
Wave 코드 안에서 레지스터, 메모리, 시스템 호출 경로를 직접 제어할 수 있습니다.
현재 지원 타깃:
- Linux
x86_64 - Linux
aarch64 - macOS (Darwin)
arm64 - freestanding
x86_64 - freestanding
aarch64 - freestanding
riscv64
Windows와 32비트 타깃은 아직 지원하지 않습니다.
기본 형태
asm은 문(statement) 으로도, 식(expression) 으로도 사용할 수 있습니다.
asm {
"instruction"
in("constraint_or_reg") value
out("constraint_or_reg") target
clobber("item")
}
구성 요소:
- 문자열 줄: 실제 어셈블리 명령어
in(...): 입력 오퍼랜드out(...): 출력 오퍼랜드clobber(...): 파괴되는 레지스터/상태/메모리 힌트
asm 문 (Statement)
반환값이 없어도 되는 경우 일반 문장으로 사용합니다.
var ret: i64 = 0;
asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret
}
out(...)은 여러 개를 둘 수 있습니다.
asm 식 (Expression)
값을 직접 생성하는 식으로 사용할 수 있습니다.
var result: i64 = asm {
"mov rax, 123"
out("rax") result
};
주의:
asm식은 정확히 1개의out(...)만 허용합니다.
in(...) / out(...) 제약식
in("..."), out("...")의 문자열은 다음 둘 중 하나입니다.
- 구체 레지스터
- 예:
"rax","rdi","x0","w1","a0","t0","x10"
- 제약 클래스(constraint class)
- 예:
"r","m","rm"
예시:
in("r") &buf
out("rax") ret
출력 대상(out(...) target)은 현재 구현 기준으로 다음 패턴을 권장합니다.
- 변수:
out("rax") ret - 포인터 역참조:
out("rax") deref p
clobber(...)
clobber(...)는 한 번에 여러 항목을 받을 수 있고, 여러 번 써도 됩니다.
asm {
"xor rax, rax"
clobber("rax")
clobber("rcx", "rdx")
clobber("memory")
}
주요 항목:
- 레지스터:
"rax","x0"등 - 특수:
"memory","cc"(타깃별 내부 정규화)
컴파일러는 보수적 안전 모드에서 기본 clobber를 자동으로 추가합니다.
(memory, flags/cc 계열 등; RISC-V freestanding에서는 주로 memory)
오퍼랜드 자리표시자 ($0, $1, ...)
명령 문자열 안에서 오퍼랜드를 참조할 때 $N을 사용합니다.
asm {
"mov QWORD PTR [$0], 777"
in("r") &buf
clobber("memory")
}
참고:
%0스타일을 써도 내부적으로$0스타일로 변환됩니다.