기본 형식
가장 큰 차이점은 operands의 순서이다.
Intel-syntax가 mnemonic destination, source 인데 반해, AT&T Syntax의 일반적인 형식은 다음과 같다.
mnemonic source, destination
레지스터
모든 IA-32 아키텍처의 레지스터 이름은 앞에 ‘%’가 붙는다.
mov %ax, %bx
위의 예제는 16비트 레지스터 AX로부터의 값을 16비트 레지스터 BX로 옮긴다.
상수 값
모든 상수 값들은 앞에 ‘$’가 붙는다.
mov $100, %bx
mov $A, %al
메모리 주소지정
AT&T 문법에서 메모리는 다음 방식으로 참조된다.
segment-override:signed-offset (base,index,scale)
일부는 생략 가능하다.
%es:100 (%eax,%ebx,2)
offset과 scale은 앞에 ‘$’가 붙으면 안된다.
GAS memory operand NASM memory operand
------------------ -------------------
100 [100]
%es:100 [es:100]
(%eax) [eax]
(%eax,%ebx) [eax+ebx]
(%ecx,%ebx,2) [ecx+ebx*2]
(,%ebx,2) [ebx*2]
-10(%eax) [eax-10]
%ds:-10(%ebp) [ds:ebp-10]
예제
mov %ax, 100
mov %eax, -100(%eax)
첫번째 예제는 ax 레지스터의 값을 (기본인) data segment 레지스터의 offset 100으로 옮기는 것이다.
두번째 예제는 eax 레지스터의 값을 [eax-100]으로 옮기는 것이다.
Operand 크기
상수 값을 메모리로 옮길 때, size-of-transfer나 operand-size를 지정할 필요가 있다. 다음 예제에서는 transfer size는 없고, 값 10을 메모리 offset 100으로 옮기는 것만 지정되어 있다.
mov $10, 100
NASM에서는 캐스팅 키워드 byte / word / dword 등을 붙여서 이를 한다. AT&T 문법에서는 이를 instruction에 suffix b/w/l을 붙여서 한다. 예를 들면 다음은 byte 값 10을 [ea:eax] 위치로 옮긴다
movb $10, %es:(%eax)
다음은 long 값 10을 같은 위치로 옮긴다.
movl $10, %es:(%eax)
아래도 그 예제들이다.
movl $100, %ebx
pushl %eax
popw %ax
제어를 넘기는 Instructions
jmp, call, ret 같은 instruction들은 프로그램의 한 곳에서 다른 곳으로 제어를 넘긴다. 이는 같은 코드 세그먼트 (near) 로 또는 다른 코드 세그먼트 (far) 로 제어를 넘길 수 있다. 가능한 브랜치 주소 지정 타입은 relative offset (label), register, memory oerand, 그리고 segment-offset pointers이다.
Relative offsets은 아래처럼 labels을 사용한다.
label1:
.
.
jmp label1
Register나 memory operands를 사용하는 브랜치 주소 지정은 ‘*’를 앞에 붙여야만 한다. “far” 제어 넘김을 지정하기 위해서는 ‘ljmp’, ‘lcall’ 등과 같이 ‘l’을 앞에 붙여야 한다. 다음이 그 예제이다.
GAS syntax NASM syntax
========== ===========
jmp *100 jmp near [100]
call *100 call near [100]
jmp *%eax jmp near eax
jmp *%ecx call near ecx
jmp *(%eax) jmp near [eax]
call *(%ebx) call near [ebx]
ljmp *100 jmp far [100]
lcall *100 call far [100]
ljmp *(%eax) jmp far [eax]
lcall *(%ebx) call far [ebx]
ret retn
lret retf
lret $0x100 retf 0x100
Segment-offset pointers는 다음 형식을 사용해서 지정한다:
jmp $segment, $offset
다음이 그 예제이다.
jmp $0x10, $0x100000
더 자세한 GNU assembler에 대해서 더 자세히 알고 싶으면 문서를 참고하자.
참고: https://csiflabs.cs.ucdavis.edu/~ssdavis/50/att-syntax.htm