Solitamente, nel mondo MS-DOS e Windows si usa la sintassi Intel per la scrittura di programmi assembly, e tipicamente è anche quella che viene insegnata nelle scuole tecniche (almeno nel mio caso).
Chi però entra nel mondo *nix, si ritrova a dover usare la sintassi AT&T. Anche se questo non è del tutto vero (quasi tutti i tool moderni permettono di specificare l’una o l’altra sintassi), conoscere anche questa sintassi non fa male 😉
Le differenze con la sintassi Intel non sono molte, ma importanti:
- L’operando sorgente e la destinazione sono invertite, cioè per scrivere “ax ← bx”:
Intel AT&T mov ax, bx
mov %bx, %ax
- Davanti ai nomi dei registri bisogna porre un %, davanti ai dati immediati (costanti) un $, e i valori esadecimali sono preceduti da “0x” (come in C)
Intel AT&T ax
%ax
ebx
%ebx
23
$23
147h
$0x147
- Se un’istruzione indicizza un’operando in memoria, bisogna specificare la dimensione del dato su cui si sta lavorando aggiungendo alla fine dell’opcode, “b”, “w”, “l”, rispettivamente per dati da 8, 16 o 32 bit. (es. movb, addw, xorl)
- Per indicare le modalità di indirizzamento, la sintassi Intel usa questa struttura: [base + index*scale + disp] , mentre la AT&T usa disp(base, index, scale).
Ecco un po’ di esempi per chiarire le idee:
Intel | AT&T |
---|---|
mov eax,1 |
movl $1,%eax |
mov ebx,0ffh |
movl $0xff,%ebx |
int 80h |
int $0x80 |
mov ebx, eax |
movl %eax, %ebx |
mov eax,[ecx] |
movl (%ecx),%eax |
mov eax,[ebx+3] |
movl 3(%ebx),%eax |
mov eax,[ebx+20h] |
movl 0x20(%ebx),%eax |
add eax,[ebx+ecx*2h] |
addl (%ebx,%ecx,0x2),%eax |
lea eax,[ebx+ecx] |
leal (%ebx,%ecx),%eax |
sub eax,[ebx+ecx*4h-20h] |
subl -0x20(%ebx,%ecx,0x4),%eax |