C 내 연 어 셈 블 리
4099 단어 어 셈 블 리
in/out
명령 은 반드시 어 셈 블 리 로 써 야 한다.C 언어 는 간결 하고 읽 기 쉬 우 며 규모 가 큰 코드 를 조직 하기 쉽 고 어 셈 블 리 효율 이 높 으 며 특수 명령 을 쓸 때 반드시 어 셈 블 리 를 사용 해 야 한다. 이 두 가지 장점 을 모두 차지 하기 위해
gcc
은 확장 문법 을 제공 하여 C 코드 에서 내 연 어 셈 블 리 (Inline Assembly) 를 사용 할 수 있다.가장 간단 한 형식 은 __asm__("assembly code");
, 예 를 들 어 __asm__("nop");
이다. , nop
이 명령 은 아무것도 하지 않 고 CPU 로 하여 금 명령 실행 주 기 를 공전 하 게 할 뿐이다.여러 개의 어 셈 블 리 명령 을 실행 해 야 한다 면
\t
으로 각 명령 을 분리 해 야 한다. 예 를 들 어:__asm__("movl $1, %eax
\t"
"movl $4, %ebx
\t"
"int $0x80");
보통 C 코드 의 내 연 어 셈 블 리 는 C 의 변수 와 연결 되 어야 하 며 완전한 내 연 어 셈 블 리 형식 을 사용 해 야 합 니 다.
__asm__(assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
이 형식 은 네 부분 으로 구성 되 어 있 으 며, 첫 번 째 부분 은 어 셈 블 리 명령 입 니 다. 위의 예 와 마찬가지 로 두 번 째 부분 과 세 번 째 부분 은 제약 조건 입 니 다. 두 번 째 부분 은 어 셈 블 리 명령 의 연산 결 과 를 어떤 C 작업 수 에 출력 해 야 하 는 지, C 작업 수 는 왼쪽 값 표현 식 이 어야 합 니 다. 세 번 째 부분 은 어 셈 블 리 명령 이 어떤 C 작업 수 에서 입력 해 야 하 는 지 를 표시 합 니 다.네 번 째 부분 은 어 셈 블 리 명령 에서 수 정 된 레지스터 목록 으로 컴 파일 러 의 어떤 레지스터 의 값 이 이
__asm__
문 구 를 실행 할 때 변 하 는 지 알려 줍 니 다.뒤의 세 부분 은 모두 선택 할 수 있 고 있 으 면 작성 하고 없 으 면 비 워 서 :
번 만 쓴다.예 를 들 면:예. 19.6. 인 라인 어 셈 블 리
#include <stdio.h>
int main()
{
int a = 10, b;
__asm__("movl %1, %%eax
\t"
"movl %%eax, %0
\t"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);
printf("Result: %d, %d
", a, b);
return 0;
}
이 프로그램 은 변수
a
의 값 을 b
에 부여 합 니 다."r"(a)
지시 컴 파일 러 는 레지스터 저장 변수 a
의 값 을 할당 하고 어 셈 블 리 명령 의 입력, 즉 명령 중의 %1
(제약 조건 의 순서에 따라 b
은 %0
, a
은 1%
에 대응 하 는 것) 에 대해 %1
이 어떤 레지스터 를 대표 하 는 지 는 컴 파일 러 가 스스로 결정 한다.어 셈 블 리 명령 은 먼저 %1
이 대표 하 는 레지스터 의 값 을 eax
(%1
과 같은 자리 표시 자 를 구분 하기 위해 eax
앞 에 %
호 두 개 를 추가 하 라 고 요구) 에 전달 한 다음 에 eax
의 값 을 %0
이 대표 하 는 레지스터 에 다시 전달 하 라."=r"(b)
은 %0
이 대표 하 는 레지스터 의 값 을 변수 b
에 출력 하 는 것 을 나타 낸다.이 두 명령 을 실행 하 는 과정 에서 레지스터 eax
의 값 이 바 뀌 었 기 때문에 "%eax"
을 네 번 째 부분 에 쓰 고 컴 파일 러 에 게 이 __asm__
문 구 를 실행 할 때 eax
을 고 쳐 야 하 므 로 이 기간 에 eax
으로 다른 값 을 저장 하지 말 라 고 알려 주 었 다.우 리 는 이 프로그램의 어 셈 블 리 결 과 를 살 펴 보 자.
__asm__("movl %1, %%eax
\t"
80483dc: 8b 55 f8 mov -0x8(%ebp),%edx
80483df: 89 d0 mov %edx,%eax
80483e1: 89 c2 mov %eax,%edx
80483e3: 89 55 f4 mov %edx,-0xc(%ebp)
"movl %%eax, %0
\t"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);
이 를 통 해 알 수 있 듯 이
%0
과 %1
은 모두 edx
레지스터 를 대표 한다. 먼저 변수 a
(ebp-8
에 있 는 위치) 의 값 을 edx
에 전달 한 다음 에 내 연 된 어 셈 블 리 의 두 가지 명령 을 집행 한 다음 에 edx
의 값 을 b
(ebp-12
에 있 는 위치) 에 전달한다.내 연 어 셈 블 리 에 관 해 이렇게 많은 것 을 소개 하 는데, 이 책 은 깊이 토론 하지 않 는 다.