인라인 어셈블리
인라인 어셈블리 (Inline assembly)
대부분은 C 코드만으로 충분하지만, 특정 CPU의 명령을 직접 써야 하는 아주 낮은 수준의 상황이 있어요. 그럴 때 C 프로그램 안에 어셈블리 언어 소스 코드를 직접 끼워 넣는 게 가능한데, 그게 인라인 어셈블리예요. 보통 asm 키워드로 시작해요.
출처: cppreference
본문
인라인 어셈블리(보통 asm 키워드가 도입)는 C 프로그램 안에 어셈블리 언어 소스 코드를 임베드할 수 있는 능력을 줘요.
C++과 달리 C에서 인라인 어셈블리는 **확장(extension)**으로 취급돼요. 조건부 지원(conditionally supported)이고 구현-정의(implementation-defined)라서, 없을 수도 있고 구현이 제공한다 해도 고정된 의미가 없어요.
문법
asm ( string_literal ) ; |
참고: 이 섹션은 인라인 어셈블리 전문가용 문법(GCC 확장)에 대한 설명으로 보완될 수 있어요. GCC 확장 asm은 Intel, IBM, Sun(v12 이후) 등에서 지원되므로, 그 확장 문법에 대한 정리는 cppreference의 원문 참고를 권해요.
설명
이런 형태의 인라인 어셈블리 문법은 C++ 표준에서도 받아들여지며, C++에서는 asm-declaration이라고 불러요. string_literal은 보통 어셈블리 언어로 작성된 짧은 프로그램인데, 이 선언이 실행될 때마다 그 프로그램이 실행돼요. C 컴파일러마다 asm-declaration에 대한 규칙과, 주변 C 코드와의 상호작용에 대한 관례가 크게 달라요.
asm-declaration은 블록 안(함수 본문이나 다른 복합문)에 나타날 수 있고, 다른 모든 선언처럼 블록 바깥에도 나타날 수 있어요.
주의
MSVC는 ARM과 x64 프로세서에서 인라인 어셈블리를 지원하지 않으며, x86 프로세서에서는 __asm이 도입하는 형태만 지원해요.
GCC나 Clang으로 ISO C 모드에서 컴파일할 때(예: -std=c11 옵션), asm 대신 __asm__을 써야 해요.
예시
GCC 컴파일러가 제공하는 두 가지 형태의 인라인 어셈블리 문법을 보여주는 코드예요. 이 프로그램은 Linux의 x86-64 플랫폼에서만 올바르게 동작해요. 참고로 "표준 인라인 어셈블리"도 C 표준에서는 확장으로 취급돼요.
#include <stdio.h>
extern int func(void);
// the definition of func is written in assembly language
__asm__(".globl func\n\t"
".type func, @function\n\t"
"func:\n\t"
".cfi_startproc\n\t"
"movl $7, %eax\n\t"
"ret\n\t"
".cfi_endproc");
int main(void)
{
int n = func();
// gcc's extended inline assembly
__asm__ ("leal (%0,%0,4),%0"
: "=r" (n)
: "0" (n));
printf("7*5 = %d\n", n);
fflush(stdout); // flush is intentional
// standard inline assembly in C++
__asm__ ("movq $60, %rax\n\t" // the exit syscall number on Linux
"movq $2, %rdi\n\t" // this program returns 2
"syscall");
}
출력:
7*5 = 35
여기서 먼저 func의 정의가 순수 어셈블리(movl $7, %eax + ret)로 쓰여 7을 반환하고, 그다음 GCC 확장 asm(leal (%0,%0,4),%0)이 그 값 7을 5배로 만들어 35가 출력되는 흐름이에요. 마지막의 표준 인라인 어셈블리는 리눅스 exit syscall로 프로그램을 종료시키죠.
더 알아보기
- C++의 인라인 어셈블리(
asm선언)는 C++ 언어 문서에서 볼 수 있어요. - GCC 확장 asm의 자세한 문법은 GCC 문서를 참고하면 좋아요.
- cppreference의 인라인 어셈블리 원문을 참고할 수 있어요.