AT&T彙編和8086組合語言雖然兩者很相似,但是還是不能根據8086的文法規則來讀AT&T彙編的吧,所以還是要看看AT&T彙編的文法規則,因為在讀核心代碼時,跟硬體打交道的部分代碼是用AT&T彙編編寫的,所以不可避免的會遇到AT&T彙編,下面先來看看AT&T彙編的文法規則吧。
一、 大小寫
INTEL格式的指令使用大寫字母,而AT&T格式的使用小寫字母。
例:
INTEL AT&T
MOV EAX,EBX movl %ebx,%eax
二、 運算元賦值方向
在INTEL文法中,第一個表示目的運算元,第二個表示源運算元,賦值方向從右向左。
AT&T文法第一個為源運算元,第二個為目的運算元,方向從左至右,合乎自然。
例:
INTEL AT&T
MOV EAX,EBX movl %ebx,%eax
三、首碼
在 INTEL 文法中寄存器和立即數不需要首碼;AT&T 中寄存器需要加首碼“%” ;立即數
需要加首碼“$” 。
例:
INTEL AT&T
MOV EAX,1 movl $1,%eax
符號常數直接引用,不需要加首碼,如:movl value , %ebx,value為一常數;在符
號前加首碼$表示引用符號地址, 如movl $value, %ebx,是將value的地址放到 ebx中。
匯流排鎖定首碼“lock” :匯流排鎖定操作。 “lock”首碼在Linux 核心代碼中使用很多,特
別是SMP代碼中。當匯流排鎖定後其它CPU不能存取鎖定地址處的記憶體單元。
遠程跳轉指令和子程序呼叫指令的作業碼使用首碼“l“,分別為 ljmp,lcall,與之
相應的返回指令偽lret。
例:
INTEL AT&T
CALL FAR SECTION:OFFSET lcall $secion:$offset
JMP FAR SECTION:OFFSET ljmp $secion:$offset
RET FAR SATCK_ADJUST lret $stack_adjust
四、間接定址文法
INTEL 中基地址使用“[” 、“]” ,而在 AT&T 中使用“(”、“)” ;另外處理複雜運算元的
文法 也 不同 , INTEL 為 Segreg:[base+index*scale+disp] , 而在 AT&T 中為
%segreg:disp(base,index,sale),其中segreg,index,scale,disp都是可選的,在指定
index而沒有顯式指定Scale的情況下使用預設值 1。Scale和 disp不需要加首碼“&” 。
INTEL AT&T
Instr
foo,segreg:[base+index*scale+disp]
instr
%segreg:disp(base,index,scale),foo
五、 尾碼
AT&T 文法中大部分指令作業碼的最後一個字母表示運算元大小, “b”表示 byte(一個
位元組) ;“w”表示 word(2 個位元組) ;“l”表示 long(4 個位元組) 。INTEL 中處理記憶體運算元
時也有類似的文法如:BYTE PTR、WORD PTR、DWORD PTR。
例:
INTEL AT&T
mov al, bl movb %bl,%al
mov ax,bx movw %bx,%ax
mov eax, dword ptr [ebx] movl (%ebx), %eax
在 AT&T 彙編指令中,運算元擴充指令有兩個尾碼,一個指定源運算元的字長,另一個
指定目標運算元的字長。AT&T 的符號擴充指令的為“movs” ,零擴充指令為“movz” (相應
的 Intel指令為“movsx”和“movzx”) 。因此, “movsbl %al,%edx”表示對寄存器 al 中的
位元組資料進行位元組到長字的符號擴充,計算結果存放在寄存器edx中。下面是一些允許的操
作數擴充尾碼:
bl: 位元組->長字
bw: 位元組->字
wl: 字->長字
跳轉指令標號後的尾碼表示跳轉方向, “f” 表示向前 (forward) , “b” 表示向後 (back) 。
例: jmp 1f
1: jmp 1f
1:
有了上面內容做基礎,在接下來我們講解GCC內嵌彙編時就好多了。