[C] 인라인 어셈블리 사용 in gcc

[원본 링크]

다른건 모르겠는데 일단 gcc에서 asm 구문은 다음과 같은 형식을 가진다.

asm
(
    "어셈블리 구문;"
    "어셈블리 구문2;"
    "어셈블리 구문3"...
    : "출력변수 명시"(변수), "출력 명시2"(변수2)...
    : "입력변수 명시"(변수), "입력 명시2"(변수2)...
    : "사용 레지스터 명시"
)

어셈블리 구문에는 말 그대로 어셈블리 명령어를 쓰면 된다. 유의할점은, eax같은 범용레지스터엔 %를 두개 붙여서 %%eax로 표시해야한단거다. 포맷문자때문이다.

출력변수에는 쓰기 작업의 대상이 될 C 프로그램의 변수를 명시한다.
비슷하게 입력변수는 읽기전용 변수를 명시한다.

그리고 마지막 부분에는 어셈 구문에서 eax 같은 특수 레지스터를 사용했을 경우, 그걸 명시해서 충돌을 방지하도록 한다. 여긴 % 하나만 붙여도 되고, 여러개일 경우 문자열 내에서 콤마로 구문한다.

from이라는 정수형 변수의 값을 to라는 변수로 이동시키는 간단한 인라인 구문을 작성해보도록 하겠다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#include <stdio.h>
#include <stdlib.h>

int main()
{
int from = 1234;
int to;

     asm volatile
     (
"mov %0, %1;"
          : "=r"(to) //to는 출력변수. 0번 레지스터
          : "r"(from) //from은 입력변수. 1번
     );

printf("음 %d", to);
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

출력문부터 보자.
: "=r"(to)
출력변수로는 to를 지정했고, 문자열 표현식에는 "=r"라고 쓰여있다. =은 쓰기작업을 할 수 있다는 뜻이고, r은 일반 레지스터에 할당한다는 뜻이다.
이 둘 말고도 표현이 되게 많은데, 맨 아래 참조 링크를 찾아보길 바란다.

여튼 이렇게 할당한 변수는 어셈 구문에서 선언한 순서대로 %0, %1, ...로 가져다 쓸 수 있다. 여분 레지스터에 알아서 잘 깔아주는것같다.
여기선 to가 %0에 할당된다.

: "r"(from)
입력문도 비슷하다. r은 일반 레지스터에 두란 뜻이고, 아무것도 없으면 읽기전용이란거다.
여기서 from은 %1에 할당된다.

여기선 특수 레지스터들을 쓰지 않아서 맨 아래에 있어야할 레지스터 명시 부분이 없다.

그다음에 어셈 명령문을 봐보자
"mov %0, %1;"
이건 뭐 별거없다.
아까 넣어뒀던 %1(from)값을 %0(to)에 집어넣으란 뜻이다.

설명은 다 됐으니 이제 한번 돌려보자.
실행환경은 리눅스에, 아마 32비트일거다. image

image 그럼 이렇게 잘 나올것이다.
아 그리고 나는 asm 옆에다 volatile 키워드를 붙였는데, 이건 저 어셈구문을 제멋대로 최적화하지 말고 그대로 붙이라는 뜻이다.
컴파일러가 막 고치게 냅두다보면 버그도 날수있고 목적한 것과 다른 코드가 나올 수도 있다고 한다.

응용하면 함수도 막 갖다쓸수있다. image

image



참고
https://www.joinc.co.kr/w/Site/Embedded/Documents/LinuxKernelStudyForSystemenginer/app3.basic.html