翻譯自:http://staffwww.fullcoll.edu/aclifton/courses/cs241/syntax.html
x86(32位和64位)有兩種語法:AT&T和intel,有些彙編器只能支持一種,有些彙編器可以兩種都支持。
在標準linux和其他的在線資源上主要使用AT&T
語法,但是我們(斯坦福大學課堂)主要使用Intel語法。
下面的表中展示了兩種語法的區別:
- | Intel | AT&T |
---|---|---|
註釋 | ; |
// |
指令 | 不帶後綴add |
帶有長度後綴的addq |
寄存器使用 | eax, ebx | %eax,%ebx |
立即數使用 | 0x100 | $0x100 |
寄存器值引用 | [eax] |
`(%eax) |
間接尋址 | [base + reg + reg * scale + displacement] |
`displacement(reg, reg, scale)`` |
在通常間接引用時,Intel語法將會計算基址+偏移
,而且操作碼允許一個單獨的立即數偏移,而在AT&T語法中,你必須自己做,把相加的結果當做括號中第三個值。
主要的區別是Intel不需要明確指出使用了指令操作數的長度,而AT&T需要顯式地指明他們並且通過在指令操作碼後面跟上相應的長度後綴,下面是一個兩個值相加的示例:
add eax, ebx;
這是Intel語法,將兩個32bit的寄存器相加(因爲eax和ebx都是32位寄存器),並且把結果放在了eax
,其中Intel語法中目的寄存器放在前面,源寄存器放在後面。因爲源和目標都是32bit,彙編器就知道他只需要轉換成32位的加指令
.而在AT&T語法中,相同的指令需要寫成這樣:
addq %ebx, %eax ;
在AT&T語法中,寄存器使用都需要帶有%
,並且源寄存器放在前面,目的寄存器放在後面,和Intel是相反的,而且最大的區別是指令的q
後綴,q
是quadword
的縮寫,代表32bit值。這個語法明確告訴了彙編器操作碼的長度,不需要通過寄存器的大小來推測出來正確的指令長度。
可能在一個指令中有兩個不同長度的寄存器,例如,將ebx
的低16位加到eax
中,Intel語法只需要寫成這樣:
add eax, bx ;
但是在AT&T語法中,你需要這樣寫:
addzqd %bx, %eax ;
其中指令後綴d
代表doubleword
,z
代碼它是一個無符號相加(用零填充高位),如果我們是有符號相加,我們需要一個符號擴展s
.
後綴’b’、‘w’、'l’分別表示操作數爲字節(byte,8 bit)、字(word,16bit)和長字(long,32bit)
這樣看來intel語法更加簡潔,對編程人員更加友好,很可惜在linux上AT&T纔是主流。
擴展閱讀
http://www.cs.cmu.edu/afs/cs/academic/class/15213-f01/docs/gas-notes.txt
https://www.cnblogs.com/hdk1993/p/4820353.html