GAS 는 GCC 가 사용하는 GNU 어셈블러이다.
GCC 를 찾은 곳과 같은 장소에 있다. 패키지 binutils 안에 패키징되어 있다.
최신의 GAS 버젼은 HJLu 에서 구할 수 있다. url 은 다음과 같다 : ftp://ftp.varesearch.com/pub/support/hjl/binutils/.
GAS 가 원래 32-bit 의 유닉스 컴파일러를 지원하도록 처음에 고안되었기 때문에, GAS 는 표준 AT&T 문법을 사용한다. 표준 AT&T 문법은 m68k 어셈블러의 문법과 상당히 유사하다. 현재 UNIX 계열 어셈블리의 표준 문법이기도 하다. 이 문법은 Intel 문법에 비해서 좋지도 않고, 나쁘지도 않다. 단지 다를 뿐이다. 여러분들이 그것을 사용해보게 되면, 인텔 문법에 비해 좀더 많은 규칙이 있음 을 알게 될 것이다.
아래에 GAS 문법의 주요 사항들을 나열하겠다.
레지스터의 이름은 %문자로 시작한다. 그래서, 레지스터를 표기할 때 다음처럼 표시한다 : %eax, %dl 등등.. 이렇게 하는 것은 외부의 C 등에서 정의된 심볼을 아무런 혼란 없이 곧바로 어셈블리 소스에 포함시키는 것을 가능하게 해 준다.
오퍼랜드의 순서가, 소스가 먼저 오고, 데스티네이션이 뒤에 온다. 인텔의 문법과는 반대이다. 그래서, 인텔의 문법으로 쓴 문장이 mov eax,edx 과 같다면, GAS 의 문법으로는 mov %edx,%eax 과 같이 쓴다. (edx 레지스터의 내용을 eax 레지스터로 옮겨라...는 뜻)
오퍼랜드의 크기가 인스트럭션의 접미어로 붙는다. 가능한 접미어는 b 는 바이트를(8-bit), w 는 워드를(16-bit) l 는 long 형을(32-bit) 나타내는 접미어이다. 예를 들자면, 바로 앞 단락에서 언급한 인스트럭션의 올바른 문법은 movl %edx,%eax 가 되어야 한다. 그러나, GAS 는 엄격하게 AT&T 문법의 규칙을 준수할 것을 요구하지 않는다. 그래서, 오퍼랜드의 크기를 나타내는 접미어는 오퍼랜드로 쓰인 레지스터의 이름으로부터 오퍼랜드의 크기를 유추할 수 있을 경우에는 생략해도 된다. 또한 그렇지 않을 경우라고 하더라도, 32-bit 의 크기를 가졌다고 가정한 상태에서 동작한다(경고 메세지를 뿌린다)
오퍼랜드에 레지스터가 아니라 상수 등을 사용할 때에는 그 오퍼랜드 앞에 $ 의 접두어를 붙여준다. 즉, addl $5,%eax 은, %eax 레지스터에 long 형 숫자 5 를 넣으라는 뜻이다.
오퍼랜드에 접두어가 없을 경우에는 그것이 메모리 주소라는 것을 의미한다. 그래서, movl $foo,%eax 은 변수 foo 의 주소 를 레지스터 %eax 에 넣으라는 뜻이 된다. 그러나, movl foo,%eax 은 변수 foo 의 값을 %eax 레지스터에 넣으라는 뜻이다.
인덱싱이나 간접 주소지정 방식은 인덱스 레지스터를 이용하거나 간접 메모리 주소의 번지를 괄호 안에 넣음으로써 표현되어진다. 예를 들어, testb $0x80,17(%ebp) 과 같은 표현은 %ebp 가 가리키는 메모리 번지에서 17번째 오프셋에 있는 바이트 값의 최상위 비트를 테스트하라는 말이 된다.
주의 : AT&T 문법을 이용한 어셈블리 소스코드와 인텔의 문법을 이용한 소스 코드 간에 서로 변환을 시켜 주는 프로그램은 거의 없다.(few programs)
Note: There are few programs which may help you to convert source code between AT&T and Intel assembler syntaxes; some of the are capable of performing conversion in both directions.
GAS 는 패키지에 TeXinfo 형식으로 된 매우 이해하기 쉬운 문서를 가지고 있다. .info 페이지 형식으로 Emacs 등에서 브라우징 할 수도 있다. 파일명은 gas.doc 이거나 as.doc 일 것이다. 의심의 여지 없이 최고의 문서는 소스코드 자체이다.
다시한번, 리눅스의 소스가 최상의 예제임을 상기하라. linux/arch/i386/ 디렉토리 아래에서 kernel/*.S, boot/compressed/*.S, mathemu/*.S. 과 같은 파일을 열어서 읽어 보아라. 최고의 예제이다.
만약 여러분이 언어를 하나 고안하고 있거나, 쓰레드 패키지를 프로그래밍하고 있다면, 다른 언어( OCaml, Gforth, etc.) 나 스레드 패키지들 (QuickThreads, MIT pthreads, LinuxThreads, etc) 을 살펴 보기를 원할 것이다. 그리고, 살펴 보면 된다!!!
마지막으로, 단지, C 프로그램을 어셈블리로 컴파일 하기만을 원한다면, 단지, 여러분이 원하는 인스트럭션의 종류와 문법만 알면 될 것이다. 위에서 여러분이 정말 어셈블리 프로그래밍이 필요한가를 판단하도록 돕는 섹션을 보도록 하라 : See section Do you need assembly? above.
binutils 2.10 부터 GAS 는 인텔 계열의 문법 또한 지원한다. .intel_syntax 지시어를 이용하여 활성화 시킨다.
Binutils (2.9.1.0.25+) 이후의 버젼부터는 i386 계열의 컴퓨터들에서 16비트 모드(레지스터와 주소지정방식)를 완벽하게 지원한다. 어셈블리 코드에서 16비트와 32비트 모드를 전환할 때는 .code16 과 .code32 지시자를 사용하면 된다.
또한, 몇몇 사람들(oskit 의 저자들도 포함)이 사용했던 깔끔한 트릭이 있는데, 그것은 GCC 로 하여금 16 비트 리얼모드용의 코드를 생성하도록 강제하는 것인데, 인라인 어셈블리 문장인 asm(".code16\n") 을 씀으로써 그렇게 했다. 그 문장을 사용하면, GCC 는 여전히 32비트의 주소지정 방식을 사용한 코드를 생산하지만, GAS 가 적당한 32비트의 접두어를 붙여준다.
GAS 에는 얼마의 매크로와 관련된 기능도 포함되어 있다. 자세한 내용은 texinfo 문서를 보라. 매크로에 더하여, GCC 는 .s 확장자의 파일을 GAS 에 바로 보내여야 할 순수한 어셈블리 로 인식하는데, 또한, .S 의 확장자를 가지는 파일은 GAS 로 넘기지 전에 먼저 CPP 를 거친 후에 넘겨야 할 파일로 인식한다. 계속 말하는 것이지만, 리눅스의 소스를 예제삼아 보라.
GAS 는 또한, GASP (GAS Preprocessor) 를 가지고 있는데, GASP 가 하는 일은 일반적인 매크로어셈블리의 트릭을 GAS 에 더해주는 것이다. GASP 는 GNU binutils 패키지 안에 GAS 와 더불어서 배포된다. GASP 는 CPP 나 m4 유틸리티처럼 필터로써 동작한다. 자세한 것은 저자가 잘 모르겠으나, texinfo 형식의 문서가 따라오므로, 문서를 참조하기 바란다. 저자에겐 GAS 와 GASP 의 조합이 일반적인 macro-assembler 처럼 느껴졌다.