So sánh nhỏ về cú pháp câu lệnh ASM giữa AT&T và Intel

Link gốc:
http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm

Người dịch:
Ngôn ngữ Assembly không phải là ngôn ngữ tốt để viết ứng dụng,nhất là bây giờ đã là năm 2017. Có quá nhiều thứ hiệu quả và nhanh hơn. Tuy nhiên, khi cần tìm hiểu ở mức hệ điều hành, rồi driver thiết bị, thì việc đọc được Assembly là rất hữu ích.

Nội dung

Cú pháp ASM giữa Intel và AT&T có rất nhiều điềm khác nhau rõ rệt. Điều này nhiều khi dẫn đến sự nhầm lẫn khi một người đã học một ASM của Intel trước rồi sang học ASM của AT&T hoặc ngoặc lại. Bài này, chúng ta sẽ xem xét những cái khác biệt cơ bản đó.

1. Về tiền tố (Prefixes)

Cú pháp Intel thì không bất cứ tiền tố nào.
Còn cú pháp AT&T:

  • thanh ghi được theo sau tiền tố %
  • giá trị được theo sau tiền tố $

Cú pháp Intel sử dụng hậu tố ‘h’ sau giá trị cơ số 16, ‘b’ sau giá trị cơ số 2.
Nếu giá trị đầu tiên của giá trị cơ số 16 là chữ thì nó phải được theo sao bằng tiền tố 0.

// Intex Syntax  
mov eax,1  
mov ebx,0ffh  
int 80h

// AT&T Syntax  
movl $1,%eax  
movl $0xff,%ebx  
int $0x80  

2. Về chiều của toán tử (Direction of Operands)

Chiều của toán tử theo cú pháp Intel ngược với cú pháp AT&T.
Trong cú pháp Intel, toán tử đầu tiên (hay tham số đầu tiên) là đích. Toán tử thứ 2 là nguồn.
Trong cú pháp AT&T thì ngược lại. Đầu tiên là nguồn, thứ 2 là đích.

Tham khảo thêm:
Có một chú ý về lệnh MOV về giá trị đích, nguồn do người dịch tổng hợp

Ví dụ:

//Intex Syntax  
instr dest,source  
mov eax,[ecx]

//AT&T Syntax  
instr source,dest  
movl (%ecx),%eax  

3. Cách chỉ định bộ nhớ (Memory Operands)

Cách chỉ định địa chỉ cũng khác nhau.
Trong cú pháp Intel, thanh ghi chứa địa chỉ được bao bởi 2 dấu ngoặc vuông [].
Trong cú pháp AT&T, được bao bởi 3 dấu ngoặc đơn ().

Ví dụ:

//Intex Syntax  
mov eax,[ebx]  
mov eax,[ebx+3]

//AT&T Syntax  
movl (%ebx),%eax  
movl 3(%ebx),%e  

Kiểu của AT&T có vẻ phức tạo hơn kiểu của Intel.
Kiểu Intel, cách viết sẽ có dạng sau: segreg[base+index * scale + disp]
Kiểu AT&T, sẽ là: %segreg:disp(base,index,scale)

Các giá trị index/scale/disp/segreg có thể bị lược bỏ.
Scale nếu không được chỉ định thì index phai được chỉ định.
Giá trị mặc định của Scale là .

Ví dụ:

//Intel Syntax  
instr foo,segreg:[base+index*scale+disp]  
mov eax,[ebx+20h]  
add eax,[ebx+ecx*2h  
lea eax,[ebx+ecx]  
sub eax,[ebx+ecx*4h-20h]

//AT&T Syntax  
instr %segreg:disp(base,index,scale),foo  
movl 0x20(%ebx),%eax  
addl (%ebx,%ecx,0x2),%eax  
leal (%ebx,%ecx),%eax  
subl -0x20(%ebx,%ecx,0x4),%eax  

Như bạn cũng thấy, kiểu AT&T khá khó hiểu.
Cách viết [base + index*scale + disp] trong dễ hiểu hơn nhiều cách viếtdisp(base, index, scale)`

4. Về hậu tố

Cái này khác nhau nhiều đây.
Cú pháp AT&T sử dụng hậu tố gợi nhớ cho câu lệnh để ám chỉ kích thước toán tử (DEST, SRC).
l nghĩa là long
w nghĩa là word
b nghĩa là byte
Cú pháp Intel thì lại sử dụng hậu tố gợi nhớ cho bộ nhớ, phía địa chỉ.
ví dụ:

byte ptr  
word ptr  
dword ptr  
// word tương ứng với "long"  

Nó tương tự giống định nghĩa kiểu dữ liệu trongC.

Ví dụ so sanh:

//Intel Syntax  
mov al,bl  
mov ax,bx  
mov eax,ebx  
mov eax, dword ptr [ebx]

//AT&T Syntax  
movb %bl,%al  
movw %bx,%ax  
movl %ebx,%eax  
movl (%ebx),%eax