[ASM] AT&T assembly syntax

기본 형식

가장 큰 차이점은 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