인라인 어셈블리

인라인 어셈블리 (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의 인라인 어셈블리 원문을 참고할 수 있어요.