W Linux-ie używana jest inna składnia języka Assembler, tak zawana składnia AT&T, niż w DOS-ie, gdzie używana jest składnia Intel-a. Różnice występują w niektórych elementach języka.
W AT&T nazwy rejestrów są poprzedzana znakiem %, natomiast liczby znakiem $.
W standardzie Intel-a to parametr, który jest parametrem źródłowym znajduje się po prawej stronie. W AT&T jest odwrotnie.
Oparatory odnoszące się do pamięci są też różne. Zamiast "[]" używamy "()".
W standardzie AT&T mnemoniki są kończone literą oznaczającą wielkość parametrów.
Przykłady:
mov eax, 1 | movl $1, %eax |
mov ebx, 0ffh | movl $0xff, %ebx |
int 80h | int $0x80 |
mov eax, [ebx+5] | movl 5(%ebx), %eax |
add eax,[ebx+ecx*2h] | (%ebx,%ecx,0x2),%eax |
sub eax,[ebx+ecx*4h-20h] | subl -0x20(%ebx,%ecx,0x4),%eax |
mov ax,bx | movw %bx,%ax |
W Linux-ie przerwaniem systemowym jest przerwanie 0x80h. Jest to odpowiednik przerwania 21h w DOS-ie. Numer przerwania zgodny z plikiem sys/syscall.h umieszany jest w rejestrze %eax, tam też jest zwracana wartość funkcji. Parametry powinny się znaleźć w kolejnych rejestrach.
Asemblacje inline umozliwia makro __asm__, lub asm, przyjmujace jako parametr string, będący kodem assemblera. Na przykład:
__asm__("movl %esp,%eax");
Można też korzystać z makra postaci __asm__("polecenia":input:output:modify).
Użyteczne jest też polecenie __volatile__ chroniące instrukcje assemblera przed zmianami optymalizacyjnymi przez kompilator.
volatile__ __asm__("
test %0,%0
test %1,%1
test %2,%2"
: /* no outputs */
: "a"((long)eax), "b"((short)bx), "c"((char)cl)
);
Istnieją dwie metody skompilowania kodu assemblera.
.data hw: .string "hello world\n" .text .globl main main: movl $SYS_write,%eax movl $1,%ebx movl $hw,%ecx movl $12,%edx int $0x80 movl $SYS_exit,%eax xorl %ebx,%ebx int $0x80 ret $ gcc -o write write.s $ wc -c ./write 4790 ./write $ strip ./write $ wc -c ./write 2556 ./write |
.data hw: .string "hello world\n" .text .globl _start _start: movl $SYS_write,%eax movl $1,%ebx movl $hw,%ecx movl $12,%edx int $0x80 movl $SYS_exit,%eax xorl %ebx,%ebx int $0x80 $ gcc -c write.s $ ld -s -o write write.o $ wc -c ./write 408 ./write |