AT T彙編簡介

2021-06-02 19:03:41 字數 4835 閱讀 3855

1.暫存器引用 引用暫存器要在暫存器號前加百分號%,如「movl %eax, %ebx」。

80386有如下暫存器: 8個32-bit暫存器 %eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp;

8個16-bit暫存器,它們事實上是上面8個32-bit暫存器的低16位:%ax,%bx,%cx,%dx,%di,%si,bp,% sp;8個8-bit暫存器:%ah,%al,%bh,%bl,%ch,%cl,%dh,%dl。它們事實上是暫存器%ax,%bx,%cx,%dx的高8位和低8位;

6個段暫存器:%cs(code),%ds(data),%ss(stack), %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)。

2. 運算元順序 運算元排列是從源(左)到目的(右),如「movl %eax(源), %ebx(目的)」

3. 立即數 使用立即數,要在數前面加符號$, 如「movl $0x04, %ebx」 或者: para = 0x04 movl $para, %ebx 指令執行的結果是將立即數04h裝入暫存器ebx。

4.符號常數 符號常數直接引用 如 value: .long 0x12a3f2de movl value , %ebx指令執行的結果是將常數0x12a3f2de裝入暫存器ebx。 引用符號位址在符號前加符號$, 如「movl $value, %ebx」則是將符號value的位址裝入暫存器ebx。

5. 運算元的長度 運算元的長度用加在指令後的符號表示b(byte,8-bit), w(word, 16-bits), l(long, 32-bits),如「movb %al, %bl」,「movw %ax,%bx」,「movl %eax, %ebx 」。 如果沒有指定運算元長度的話,編譯器將按照目標運算元的長度來設定。比如指令「mov %ax,%bx」,由於目標運算元bx的長度為word,那麼編譯器將把此指令等同於「movw %ax, %bx」。同樣道理,指令「mov $4,%ebx」等同於指令「movl $4, %ebx」,「push %al」等同於「pushb%al」。對於沒有指定運算元長度,但編譯器又無法猜測的指令,編譯器將會報錯,比如指令「push $4」。

6.符號擴充套件和零擴充套件指令絕大多數面向80386的at&t彙編指令與intel格式的彙編指令都是相同的,符號擴充套件指令和零擴充套件指令則是僅有的不同格式指令。符號擴充套件指令和零擴充套件指令需要指定源運算元長度和目的運算元長度,即使在某些指令中這些運算元是隱含的。在at&t語法中,符號擴充套件和零擴充套件指令的格式為,基本部分"movs"和"movz"(對應intel語法的movsx和movzx),後面跟上源運算元長度和目的運算元長度。movsbl意味著movs (from)byte (to)long;movbw意味著movs(from)byte (to)word;movswl意味著movs (from)word(to)long。對於movz指令也一樣。比如指令「movsbl %al,%edx」意味著將al暫存器的內容進行符號擴充套件後放置到edx暫存器中。 其它的intel格式的符號擴充套件指令還有: cbw --sign-extend byte in %al to word in %ax; cwde -- sign-extend word in %axto long in %eax; cwd -- sign-extend word in %ax to long in %dx:%ax; cdq-- sign-extend dword in %eax to quad in %edx:%eax;對應的at&t語法的指令為cbtw,cwtl,cwtd,cltd。

7. 呼叫和跳轉指令段內呼叫和跳轉指令為"call","ret"和"jmp",段間呼叫和跳轉指令為"lcall","lret"和"ljmp"。段間呼叫和跳轉指令的格式為「lcall/ljmp $section, $offset」,而段間返回指令則為「lret$stack-adjust」。

8. 字首 操作碼字首被用在下列的情況: 字串重複操作指令(rep,repne);指定被操作的段(cs,ds,ss,es,fs,gs); 進行匯流排加鎖(lock); 指定位址和操作的大小(data16,addr16);在at&t彙編語法中,操作碼字首通常被單獨放在一行,後面不跟任何運算元。例如,對於重複scas指令,其寫法為: repne scas上述操作碼字首的意義和用法如下:指定被操作的段字首為cs,ds,ss,es,fs,和gs。在at&t語法中,只需要按照section:memory-operand的格式就指定了相應的段字首。比如:lcall %cs:realmode_swtch運算元/位址大小字首是「data16」和"addr16",它們被用來在32-bit運算元/位址**中指定16-bit的運算元/位址。匯流排加鎖字首「lock」,它是為了在多處理器環境中,保證在當前指令執行期間禁止一切中斷。這個字首僅僅對add, adc, and, btc,btr, bts, cmpxchg,dec, inc, neg, not, or,sbb, sub, xor, xadd,xchg指令有效,如果將lock字首用在其它指令之前,將會引起異常。 字串重複操作字首"rep","repe","repne"用來讓字串操作重複「%ecx」次。

9.記憶體引用 intel語法的間接記憶體引用的格式為: section:[base+index*scale+displacement]而在at&t語法中對應的形式為: section:displacement(base,index,scale)其中,base和index是任意的32-bit base和index暫存器。scale可以取值1,2,4,8。

如果不指定scale值,則預設值為1。section可以指定任意的段暫存器作為段字首,預設的段暫存器在不同的情況下不一樣。如果你在指令中指定了預設的段字首,則編譯器在目標**中不會產生此段字首**。

下面是一些例子:-4(%ebp):base=%ebp,displacement=-4,section沒有指定,由於base=%ebp,所以預設的section=%ss,index,scale沒有指定,則index為0。foo(,%eax,4):index=%eax,scale=4,displacement=foo。其它域沒有指定。這裡預設的section=%ds。foo(,1):這個表示式引用的是指標foo指向的位址所存放的值。注意這個表示式中沒有base和index,並且只有乙個逗號,這是一種異常語法,但卻合法。 %gs:foo:這個表示式引用的是放置於%gs段裡變數foo的值。

如果call和jump操作在運算元前指定字首「*」,則表示是乙個絕對位址呼叫/跳轉,也就是說jmp/call指令指定的是乙個絕對位址。如果沒有指定"*",則運算元是乙個相對位址。任何指令如果其運算元是乙個記憶體操作,則指令必須指定它的操作尺寸(byte,word,long),也就是說必須帶有指令字尾(b,w,l)。

二 基本的行內彙編 基本的行內彙編很簡單,一般是按照下面的格式 asm("statements"); 例如:asm("nop");asm("cli"); asm 和 __asm__是完全一樣的. 如果有多行彙編,則每一行都要加上 "\n\t" 例如: asm("pushl % eax\n\t" "movl $0,% eax\n\t" "popl % eax");實際上gcc在處理彙編時,是要把asm(...)的內容"列印"到彙編 檔案中,所以格式控制字元是必要的.

再例如:asm("movl % eax,% ebx"); asm("xorl % ebx,% edx"); asm("movl $0,_booga);在上面的例子中,由於我們在行內彙編中改變了edx和ebx的值,但是 由於gcc的特殊的處理方法,即先形成彙編檔案,再交給gas去彙編,所以gas並不知道我們已經改變了edx和ebx的值,如果程式的上下文 需要edx或ebx作暫存,這樣就會引起嚴重的後果.

對於變數_booga也 存在一樣的問題.為了解決這個問題,就要用到擴充套件的行內彙編語法. 三 擴充套件的行內彙編 基本的格式是: asm(statements : outputs : inputs : registers-modified);statements是一些彙編語句,outputs是輸出暫存器,inputs是輸入暫存器,registers-modified是在這個過程中改變的暫存器。

例如: int i=0, j=1, k=0; __asm__ __volatile__("pushl %% eax\n movl %1, %% eax\n addl %2, %% eax\n movl %% eax, %0\npopl %% eax" : "=g" (k) : "g" (i), "g" (j) ); // k = i + j在上面的這段**中,輸入暫存器用了"g"限定符,它的意思是將輸入變數放入 eax,ebx,ecx,edx或記憶體變數其中之一,類似的限定還有:"a" eax "b" ebx "c" ecx "d" edx "s" esi "d" edi "q"從eax,ebx,ecx,edx分配暫存器 "r" 從eax,ebx,ecx,edx,esi,edi分配暫存器 "g"eax,ebx,ecx,edx或記憶體變數 "a" 把eax和edx合成乙個64位的暫存器(use long longs) "i" i是常數值,

例如"1",它是把輸出暫存器和輸入暫存器由左到右,由上到下順序往下數對應的暫存器在上面這段**中,%0對應k存放的暫存器,,%1對應i存放的暫存器,%2對應j存放的暫存器. "i" 立即數 "m" 記憶體變數輸出暫存器要在前面加"=",指示輸出的位置。

上面的**展開大概是: mov i, % eax mov j, % ebx pushl %% eax movl % eax, %% eax movl % ebx, %% eax movl %% eax, % ecx popl %% eax

又如: do while (0)

中 %3 對應edx, %2對應eax, %1是(*(1+(long *) (gate_addr))). 這段**是將中斷處理函式的位址填到 ldt(中斷向量表)中。

AT T彙編簡介

at t語法與intel匯程式設計序使用的語法很不一樣,他們之間的主要區別有以下幾點 這種定址方式常常用於在資料結構陣列中訪問特定元素內的乙個字段,base為陣列的起始位址,scale為每個陣列元素的大小,index為下標。如果陣列元素是資料結構,則disp為具體欄位在結構中的偏移。at t彙編器不...

AT T彙編語法簡介

引用自 ps 這段時間在研究linux源 遇到了at t彙編,故轉貼個不錯的at t彙編貼。就像軟體的真諦 給我乙個標準,我用我的邏輯舞動世界 一樣,at t彙編是組合語言裡的另一種標準,這是相對於鼎鼎大名的intel的x86彙編來說。即使對於電子專業的學生來說,一旦掌握了c51微控制器的彙編,x8...

att格式彙編指令 關於ATT彙編

att 彙編大體格式是 指令 源運算元 目的運算元 比如將 10 移動到 eax 暫存器的寫法 movl 10,eax 1.att 彙編的源運算元和目的運算元和 intel 正好相反,也就是資料流向是從左到右 2.att 中立即數前需要加 符號,暫存器前加 符號 3.att 的指令加字尾 b w l...