AT&T 彙編是一種和intel彙編在語法上完全不同的彙編語言,爲避免混淆intel語法,本文只介紹AT&T彙編,以下是所有的寄存器,AT&T的第一個特點就是每個寄存器名前必須加‘%’,立即數前必須加‘$’:(下面省略了%)
8個32位寄存器:eax, ecx, edx, ebx, esp, ebp, esi, edi
8個16位寄存器:ax, cx, dx, bx, sp, bp, si, di
8個8位寄存器:al, cl, dl, bl, ah, ch, dh, bh
(注:16位寄存器分別是32位寄存器的低16位,8位寄存器分別是ax,cx,dx,bx的高低8位【l:低位,h:高位】)
6個段寄存器:cs, ds, ss, es, fs, gs
3個控制寄存器:cr0, cr2, cr3
6個debug寄存器:db0, db1, db2, db3, db6, db7
2個測試寄存器:tr6, tr7
8個浮點寄存器棧:st(0), st(1), st(2), st(3), st(4), st(5), st(6), st(7)
AT&T語法一個很明顯的特點是操作數從左到右排列的,簡單來講,例:
intel語法=》MOV AX,123 ;將123存入寄存器ax
AT&T語法=》mov $123,%ax #將123存入寄存器ax
在大多數指令上,兩種彙編指令都是一樣的。
在AT&T中,想要說明操作數的長度,有三種符號:l(long),w(word),b(byte),使用時在指令後面直接加上就行了,比如“movl $0x80,%eax”,指明瞭立即數0x80的長度爲4字節
對於註釋符號,AT&T允許了3種註釋符號,c/c++的兩種(單行註釋“//”和多行註釋“/**/”),還有"#"單行註釋,值得注意的是,“//”雖然可以單行註釋,但只能放在空行註釋,其他兩個註釋均可以跟在代碼行後面,"/**/"甚至允許你在代碼行的最前面寫一行註釋。相比較而言,像nasm這樣intel語法的彙編器只有一個單行註釋符號“;”。AT&T彙編器雖然不支持這個註釋符號,但碰到時會直接忽視掉。
(intel語法的彙編代碼多用大寫字母,AT&T則用小寫字母)
彙編例子(linux下):
//向屏幕輸出字符串
.section .data #聲明數據段,.section用來指明這是一個段,在這裏可不加
msg:
.ascii "goodmorning!\n" #.ascii聲明爲ASCII碼,也可以用.string,一樣的效果
len=.-msg #len儲存了字符串長度
.section .text #聲明代碼段
.globl _start#.globl用來聲明程序入口
_start:
movl$msg,%ecx #標號實質上就是一個地址,這個地址指向該段的第一個數據的地址
movl $len,%edx #將字符串的長度放進寄存器edx
movl $1,%ebx #
movl $4,%eax #將中斷號存入eax
Int 0x80 #進入中斷
movl$0,%ebx
movl $1,%eax#當eax存入1時進入中斷,說明已經運行完了,程序將自動結束
Int 0x80
/*ebx儲存程序的返回值,當程序在終端中執行完成後,你可以使用“echo $?”指令查看程序的返回值*/
一般linux系統都會裝有AT&T編譯器,下面簡述一下執行上面那個代碼的步驟
1.將上面的代碼保存,命名爲“m.s”(文件名隨便,linux對文件後綴名要求並不嚴格)
2.在保存的目錄下單機鼠標右鍵,打開終端。
3.在終端輸入"as m.s -o m.o" (-o可以把生成文件命名爲你想要的名字,這裏m.s經過as程序編譯後,生成的目標文件爲m.o,當沒有用-o指定文件名時,默認命名爲“a.out”)
4.再在終端輸入“ld m.o -o m”,ld是鏈接程序,任何要在操作系統層面上運行的程序必須要鏈接成可執行文件才能正常運行
5.生成的文件m就是我們的程序,輸入“./m”,然後回車,就可以運行了,你可以輸入echo $?來查看程序結束後的返回值,即ebx中的值。