at T語法格式

2021-10-06 11:18:26 字數 2896 閱讀 1616

.text

.globl _start

_start:

popl %ecx # argc

vnext:

popl %ecx # ar**

test %ecx, %ecx # 空指標表明結束

jz exit

movl %ecx, %ebx

xorl %edx, %edx

strlen:

movb (%ebx), %al

inc %edx

inc %ebx

test %al, %al

jnz strlen

movb $10, -1(%ebx)

movl $4, %eax # 系統呼叫號(sys_write)

movl $1, %ebx # 檔案描述符(stdout)

int $0x80

jmp vnext

exit: movl $1,%eax # 系統呼叫號(sys_exit)

xorl %ebx, %ebx # 退出**

int $0x80

ret六、gcc 內聯彙編

用彙編編寫的程式雖然執行速度快,但開發速度非常慢,效率也很低。如果只是想對關鍵**段進行優化,或許更好的辦法是將彙編指令嵌入到 c 語言程式中,從而充分利用高階語言和組合語言各自的特點。但一般來講,在 c **中嵌入彙編語句要比"純粹"的組合語言**複雜得多,因為需要解決如何分配暫存器,以及如何與c**中的變數相結合等問題。

gcc 提供了很好的內聯彙編支援,最基本的格式是:

asm(「asm statements」);

例如:asm(「nop」);

如果需要同時執行多條彙編語句,則應該用"\n\t"將各個語句分隔開,例如:

asm( 「pushl %%eax \n\t」

「movl $0, %%eax \n\t」

「popl %eax」);

通常嵌入到 c **中的彙編語句很難做到與其它部分沒有任何關係,因此更多時候需要用到完整的內聯彙編格式:

asm(「asm statements」 : outputs : inputs : registers-modified);

插入到 c **中的彙編語句是以":「分隔的四個部分,其中第一部分就是彙編**本身,通常稱為指令部,其格式和在組合語言中使用的格式基本相同。指令部分是必須的,而其它部分則可以根據實際情況而省略。

在將彙編語句嵌入到c**中時,運算元如何與c**中的變數相結合是個很大的問題。gcc採用如下方法來解決這個問題:程式設計師提供具體的指令,而對暫存器的使用則只需給出"樣板"和約束條件就可以了,具體如何將暫存器與變數結合起來完全由gcc和gas來負責。

在gcc 內聯彙編語句的指令部中,加上字首』』%』『的數字(如%0,%1)表示的就是需要使用暫存器的"樣板"運算元。指令部中使用了幾個樣板運算元,就表明有幾個變數需要與暫存器相結合,這樣gcc和gas在編譯和彙編時會根據後面給定的約束條件進行恰當的處理。由於樣板運算元也使用』』 %』『作為字首,因此在涉及到具體的暫存器時,暫存器名前面應該加上兩個』』%』』,以免產生混淆。

緊跟在指令部後面的是輸出部,是規定輸出變數如何與樣板運算元進行結合的條件,每個條件稱為乙個"約束」,必要時可以包含多個約束,相互之間用逗號分隔開就可以了。每個輸出約束都以』』=』『號開始,然後緊跟乙個對運算元型別進行說明的字後,最後是如何與變數相結合的約束。凡是與輸出部中說明的運算元相結合的暫存器或運算元本身,在執行完嵌入的彙編**後均不保留執行之前的內容,這是gcc在排程暫存器時所使用的依據。

輸出部後面是輸入部,輸入約束的格式和輸出約束相似,但不帶』』=』'號。如果乙個輸入約束要求使用暫存器,則gcc在預處理時就會為之分配乙個暫存器,並插入必要的指令將運算元裝入該暫存器。與輸入部中說明的運算元結合的暫存器或運算元本身,在執行完嵌入的彙編**後也不保留執行之前的內容。

有時在進行某些操作時,除了要用到進行資料輸入和輸出的暫存器外,還要使用多個暫存器來儲存中間計算結果,這樣就難免會破壞原有暫存器的內容。在gcc內聯彙編格式中的最後乙個部分中,可以對將產生***的暫存器進行說明,以便gcc能夠採用相應的措施。

下面是乙個內聯彙編的簡單例子:

例4.內聯彙編

int main()

上面的程式完成將變數a的值賦予變數b,有幾點需要說明:

變數b是輸出運算元,通過%0來引用,而變數a是輸入運算元,通過%1來引用。

輸入運算元和輸出運算元都使用r進行約束,表示將變數a和變數b儲存在暫存器中。輸入約束和輸出約束的不同點在於輸出約束多乙個約束修飾符』』=』』。

在內聯彙編語句中使用暫存器eax時,暫存器名前應該加兩個』』%』』,即%%eax。內聯彙編中使用%0、%1等來標識變數,任何只帶乙個』』%』『的識別符號都看成是運算元,而不是暫存器。

內聯彙編語句的最後乙個部分告訴gcc它將改變暫存器eax中的值,gcc在處理時不應使用該暫存器來儲存任何其它的值。

由於變數b被指定成輸出運算元,當內聯彙編語句執行完畢後,它所儲存的值將被更新。

在內聯彙編中用到的運算元從輸出部的第乙個約束開始編號,序號從0開始,每個約束記數一次,指令部要引用這些運算元時,只需在序號前加上』』%』'作為字首就可以了。需要注意的是,內聯彙編語句的指令部在引用乙個運算元時總是將其作為32位的長字使用,但實際情況可能需要的是字或位元組,因此應該在約束中指明正確的限定符:

限定符意義

「m」、「v」、「o」

記憶體單元

「r」任何暫存器

「q」暫存器eax、ebx、ecx、edx之一

「i」、「h」

直接運算元

「e"和"f」

浮點數「g」

任意「a」、「b」、「c」、「d」

分別表示暫存器eax、ebx、ecx和edx

「s"和"d」

暫存器esi、edi

「i」常數(0至31)

AT T彙編語法格式

1.暫存器的引用要在暫存器前加 如mov eax,ebx 2.運算元排列是左源右目的,如上例表示把值從eax暫存器mov到ebx暫存器 3.常數 立即數前面要加 如mov 4,ebx 4.對於變數加 表示取位址。如mov value,ebx表示傳值給ebx,而mov value,ebx表示傳位址給e...

Linux下AT T彙編語法格式簡介

一 at t 格式linux 彙編語法格式 在 at t 彙編格式中,暫存器名要加上 作為字首 而在 intel 彙編格式中,暫存器名不需要加字首。例如 at t格式 intel格式 pushl eax push eax 在 at t 彙編格式中,用 字首表示乙個立即運算元 而在 intel 彙編格...

Linux下AT T彙編語法格式簡介

絕大多數linux程式設計師以前只接觸過dos windows下的組合語言,這些彙編 都是intel風格的。但在unix和linux系統中,更多採用的還是at t格式,兩者在語法格式上有著很大的不同 在at t彙編格式中,暫存器名要加上 作為字首 而在intel彙編格式中,暫存器名不需要加字首。例如...