程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> AT&T匯編語言與GCC內嵌匯編簡介

AT&T匯編語言與GCC內嵌匯編簡介

編輯:關於C語言
 

1 AT&T 與INTEL的匯編語言語法的區別
1.1大小寫
1.2操作數賦值方向
1.3前綴
1.4間接尋址語法
1.5後綴
1.6指令

2 GCC內嵌匯編
2.1簡介
2.2內嵌匯編舉例
2.3語法
2.3.1匯編語句模板
2.3.2輸出部分
2.3.3輸入部分
2.3.4限制字符
2.3.5破壞描述部分
2.4GCC如何編譯內嵌匯編代碼

3後記

本節先介紹
AT&T匯編語言語法與INTEL匯編語法的差別,然後介紹GCC內嵌匯編語法。閱讀本節需要讀者具有INTEL
匯編語言基礎。

 

1 AT&T 與INTEL的匯編語言語法的區別


1.1
指令大小寫
INTEL格式的指令使用大寫字母,而AT&T
格式的使用小寫字母。
例:
INTEL AT&T
MOV EAX,EBX movl %ebx,%eax
1.2
指令操作數賦值方向

在INTEL語法中,第一個表示目的操作數,第二個表示源操作數,賦值方向從右向左。
AT&T語法第一個為源操作數,第二個為目的操作數,方向從左到右,合乎自然。


例:
INTEL AT&T
MOV EAX,EBX movl %ebx,%eax
1.3
指令前綴
在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

lcall $secion:$offset
JMP FAR SECTION:OFFSET ljmp $secion:$offset
RET FAR SATCK_ADJUST lret $stack_adjust

1.4 間接尋址語法

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

1.5
指令後綴

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
中。下面是一些允許的操作數擴展後綴:

l
bl: ,字節>->長字 l
bw: ,字節>->字 l
wl: ,字->長字

跳轉指令標號後的後綴表示跳轉方向,“f”表示向前(forward),
“b,”表示向後(back)。
例:

jmp 1f
jmp 1f

1.6 指令
INTEL匯編與AT&T匯編指令基本相同,差別僅在語法上。關於每條指令的語法可以參考I386Manual。

 

2 GCC內嵌匯編

2.1 簡介

內核代碼絕大部分使用C
語言編寫,只有一小部分使用匯編語言編寫,例如與特定體系結構相關的代碼和對性能影響很大的代碼。GCC提供了內嵌匯編的功能,可以在C代碼中直接內嵌匯編語言語句,大大方便了程序設計。

簡單的內嵌匯編很容易理解


例:

__asm__
__volatile__("hlt");

“__asm__”表示後面的代碼為內嵌匯編,“asm”是“__asm__”的別名。
“__volatile__”表示編譯器不要優化代碼,後面的指令保留原樣,
“volatile”是它的別名。括號裡面是匯編指令。

2.2 內嵌匯編舉例在內嵌匯編中,可以將C
語言表達式指定為匯編指令的操作數,而且不用去管如何將C
語言表達式的值讀入哪個寄存器,以及如何將計算結果寫回C
變量,你只要告訴程序中C語言表達式與匯編指令操作數之間的對應關系即可, GCC
會自動插入代碼完成必要的操作。

 


使用內嵌匯編,要先編寫匯編指令模板,然後將C語言表達式與指令的操作數相關聯,並告訴
GCC對這些操作有哪些限制條件。例如在下面的匯編語句:

__asm__ __violate__
("movl %1,%0" : "=r" (result) : "m" (input));

 

 

 

“movl %1,%0”是指令模板;“%0”和“%1”代表指令的操作數,稱為占位符,內嵌匯編靠它們將C  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved