第5部分-Linux x86 64位彙編 AT&T彙編

第5部分-Linux x86 64位彙編 AT&T彙編

     關於調試我們放到後面,因爲這篇開始還是進入本系列的正題了。

    學習了前面的INTEL 彙編,開始使用AT&T彙編了。

    不是所有彙編器使用的標準都一樣的,不通匯編器使用不同的彙編語法。

    關於AT&T彙編,也就是基於gas彙編器的。可以參考書籍《Programming Ground Up》。

    AT&T彙編程序的結構跟其它彙編語言類似,由directives, labels, instructions組成,助記符最多可以跟隨三個操作數。與Intel彙編語言相比,最大的區別在於操作數的順序。

這裏要提醒的是:這些都會在實例中來學習鞏固,死記還是比較難的,在實踐中不斷理解即可。

    比如Intel彙編語法的傳送指令通常是:

        mnemonic destination,source

    在AT&T彙編中,通常是:

        mnemonic source,destination

  • 也即源操作數在左邊,目的操作數在右邊
  • 所有寄存器前面都要加前綴%.
  • 所有立即數必須冠以前綴$.
  • 符號常數直接引用,引用符號地址在符號前加符號$
  • 通過對操作指令添加b/w/l/q等後綴來指示操作數“尺寸”. Intel 語法通過在內存操作數(而不是操作碼本身)前面加 byte ptr、word ptr 和 dword ptr 來指定大小。

jmp, call, ret這些指令用於控制程序從某條指令跳到另外的指令處。它又分爲近跳轉(在同一段內)和遠跳轉(不同段內)。跳轉地址可以用相對偏移(label),寄存器,內存操作數.

  • 中間形式長跳轉和調用是 lcall/ljmp $section, $offset;Intel 語法是 call/jmp far section:offset。在 AT&T 語法中,遠返回指令是 lret $stack-adjust,而 Intel 使用 ret far stack-adjust。
  • GAS中的內存操作數的尋址方式是section:disp(base, index, scale)。%segment:ADDRESS (, index, multiplier)或%segment:(offset, index, multiplier)或%segment:ADDRESS(base, index, multiplier)。ADDRESS or offset + base + index * multiplier。NASM 使用的語法比較簡單。上面的公式在 NASM 中表示爲:Segment:[ADDRESS or offset + index * multiplier]
  • GAS 中,重複結構以.rept指令開頭,用一個.endr指令結束這個指令。.rept後面是一個數字,指定.rept/.endr結構中表達式重複執行的次數。相當於編寫這個指令count次,每次重複佔據單獨的一行。NASM 中,在預處理器級使用相似的結構。它以 %rep 指令開頭,以%endrep結尾。%rep指令後面是一個表達式。NASM 中還有另一種結構,times指令。與%rep相似,它也在彙編級起作用。

    在AT&T語法中,符號擴展和零擴展指令的格式爲,基本部分"movs"和"movz"(對應Intel語法的movsx和movzx),後面跟源操作數長度和目的操作數長度。movsbl意味着movs (from)byte (to)long;movsbw意味着movs (from)byte (to)word;movswl意味着movs (from)word (to)long。對於movz指令也一樣。

    以點號開頭的任何內容都不會直接轉換爲機器指令。例如.section .data表示數據段,.section .text表示代碼段,.globl意味着彙編程序在彙編後不應丟棄此符號,因爲鏈接器將需要它。 _start是一個特殊的符號,總是需要用.globl標記,因爲它標記了程序開始的位置。

    函數定義.type funcname,@function,定義函數。

  • GAS 中的彙編器指令以 “.” 開頭,但是在 NASM 中不是。
  • GAS 支持 C 風格(/* */)、C++ 風格(//)和 shell 風格(#)的註釋。NASM 支持以 “;” 字符開頭的單行註釋。
  • NASM 分別使用 dd、dw 和 db 指令聲明 32 位、16 位和 8 位數字,而 GAS 分別使用 .long、.int 和 .byte。GAS 還有其他指令,如 .ascii、.asciz 和 .string。在 GAS 中,像聲明其他標籤一樣聲明變量(使用冒號),在 NASM 中,只需在內存分配指令(dd、dw 等等)前面輸入變量名,後面加上變量的值。
  • 內存直接尋址模式。NASM 使用方括號間接引用一個內存位置指向的地址值:[var1]。GAS 使用圓括號間接引用同樣的值:(var1)
  • 字符串的地址 ,在 NASM 中,內存變量代表內存位置本身,所以 push str 這樣的調用實際上是將地址壓入堆棧的頂部。在 GAS中,變量 str 必須加上前綴 $,纔會被當作地址。如果不加前綴 $,那麼會將內存變量代表的實際字節,而不是地址。
  • 關於註釋,Nasm是;,而在AT&T中是# 單行註釋;// 單行註釋;/* */ 多行註釋

當然這些都會在實例中來學習鞏固,死記還是比較難的,實踐中不斷理解即可。

數據聲明

AT&T中數據聲明如下:

命令 數據類型

.ascii 文本字符串

.asciz 以空字符串結尾的文本字符串

.byte  字節值

.double       雙精度浮點數

.float 單精度浮點數

.int    32位整數

.long 32位整數(同32)

.octa  16字節整數

.quad 8字節整數

.short 16位整數

.single        單精度浮點數(和.float同)

 

此外匯編器使用兩個命令聲明緩衝:

命令 描述

.comm        聲明未初始化的數據的通用內存區域

.lcomm       聲明未初始化的數據的本地通用內存區域

movx,其中x可以是下面字符:

x       描述

q   用於64位的長字值

l        用於32位的長字值

w      用於16位的字值

b       用於8位的字節值

後面我們會給出幾個常用的AT&T語法彙編例子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章