亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

AT&T/x86/asm語法

2019-11-17 05:27:08
字體:
來源:轉載
供稿:網友

  Homepage:http://www.whitecell.org

DJGPP使用AT&T格式的匯編語法,和一般的intel格式的語法有點不同。主要不同點如下:

AT&T語法顛倒了源和目的操作數的位置, 目的操作數在源操作數之后。寄存器操作數要有個%的前綴,立即數操作數要有個$符號的前綴。存儲器操作數的大小取決于操作碼的最后一個字符。 它們是b(8-bit), w(16-bit)和l(32-bit)。
這里有一些例子。左邊部分是at&t格式,右邊是intel指令格式。
movw %bx, %ax// mov ax, bx
xorl %eax, %eax// xor eax, eax
movw $1, %ax// mov ax,1
movb X, %ah// mov ah, byte ptr X
movw X, %ax// mov ax, Word ptr X
movl X, %eax// mov eax, X
大部分操作指令,at&t和intel都是差不多的,除了這些:
movsSD // movsx
movzSD // movz

S和D分辨代表源和目的操作數后綴。
movswl %ax, %ecx// movsx ecx, ax
cBTw // cbw
cwtl // cwde
cwtd // cwd
cltd // cdq
lcall $S,$O // call far S:O
ljmp $S,$O // jump far S:O
lret $V // ret far V
操作嘛,前綴不能與它們作用的指令寫在同一行。例如rep和stosd應該是兩個相互獨立的指令, 存儲器的情況也有一點不同。通常intel格式的如下:

section:[base + index*scale + disp]

被寫成:

section:disp(base, index, scale)

這里有些例子:

movl 4(%ebp), %eax // mov eax, [ebp+4])
addl (%eax,%eax,4), %ecx // add ecx, [eax + eax*4])
movb $4, %fs:(%eax) // mov fs:eax, 4)
movl _array(,%eax,4), %eax // mov eax, [4*eax + array])
movw _array(%ebx,%eax,4), %cx// mov cx, [ebx + 4*eax + array])

Jump 指令通常是個短跳轉。可是, 下面這些指令都是只能在一個字節的范圍內跳轉: jcxz,jecxz,loop,loopz,loope,loopnz和loopne。象在線文檔所說的那樣,一個jcxz foo可以擴展成以下工作:
jcxz cx_zero
jmp cx_nonzero
cx_zero:
jmp foo
cx_nonzero:
文檔也注重到了mul和imul指令。 擴展的乘法指令只用一個操作數,例如, imul $ebx, $ebx將不會把結果放入edx:eax。使用imul %ebx中的單操作數來獲得擴展結果。


--------------------------------------------------------------------------------

Inline Asm
我將首先開始inline asm, 因為似乎關于這方面的疑問非常多。這是最基本的語法了, 就象在線幫助信息
中描述的:
__asm__(asm statements : outputs : inputs : registers-modified);

這四個字段的含義是:

asm statements - AT&T 的結構, 每新行都是分開的。
outputs - 修飾符一定要用引號引起來, 用逗號分隔
inputs - 修飾符一定要用引號引起來, 用逗號分隔
registers-modified - 名字用逗號分隔
一個小小的例子:
__asm__("
pushl %eax

movl $1, %eax

popl %eax"
);
假如你不用到非凡的輸入輸出變量或者修改任何寄存器的值,一般來說是不會使用到其他的三個字段的,讓我們來分析一下輸入變量。

int i = 0;

__asm__("
pushl %%eax

movl %0, %%eax

addl $1, %%eax

movl %%eax, %0

popl %%eax"
:
: "g" (i)
);// increment i

不要為上面的代碼所困擾! 我將盡力來解釋它。我們想讓輸入變量i加1,沒有任何輸出變量, 也沒有改變寄存器值(我們保存了eax值)。 因此,第二個和最后一個字段是空的。 因為指定了輸入字段, 我們仍需要保留一個空的輸出字段, 但是沒有最后一個字段, 因為它沒被使用。在兩個空冒號之間留下一個新行或者至少一個空格。

下面讓我們來看看輸入字段。 附加描述符可以修正指令來讓你給定的編譯器來正確處理這些變量。他們一般被附上雙引號。 那么這個"g"是用來做什么的呢? 只要是合法的匯編指令,"g"就讓編譯器決定該在哪里加載i的值。一般來說,你的大部分輸入變量都可以被賦予"g", 讓編譯器決定如何去加載它們 (gcc甚至可以優化它們!)。 其他描述符使用"r" (加載到任何可用的寄存器去), "a" (ax/eax), "b"(bx/ebx), "c" (cx/ecx), "d" (dx/edx), "D" (di/edi), "S" (si/esi), 等等。

我們將要提到一個在asm代碼里面的如%0的輸入變量。假如我們有兩個輸入, 他們會一個是%0,一個是%1,在輸入段里按順序排列 (如下一個例子)。假如N個輸入變量且沒有輸出變量, 從%0到%N-1將和輸入字段里的變量相對應, 按順序排列。

假如任何的輸入, 輸出, 寄存器修改字段被使用, 匯編代碼里的寄存器名必須用兩個%來代替一個%。對應于第一個沒有使用最后三個字段的例子。

讓我們看看兩個輸入變量且引入了"volatile"的例子:

int i=0, j=1;
__asm__ __volatile__("
pushl %%eax

movl %0, %%eax

addl %1, %%eax

movl %%eax, %0

popl %%eax"
:
: "g" (i), "g" (j)
);// increment i by j
Okay, 現在我們已經有了兩個輸入變量了。沒問題了, 我們只需要記住%0對應第一個輸入變量(在這個例子中是i), %1對應在i后面的列出的j。
Oh yeah, 這個volatile到底是什么意思呢? 它防止你的編譯器修改你的匯編代碼,就是不進行優化(紀錄, 刪除, 結合,等等優化手段。), 不改變代碼原樣來匯編它們。建議一般情況下使用volatile選項。

讓我們來看看輸出字段:

int i=0;
__asm__ __volatile__("
pushl %%eax

movl $1, %%eax

movl %%eax, %0

popl %%eax"
: "=g" (i)
);// assign 1 to i
這看起來非常象我們前面提到的輸入字段的例子; 確實也沒有很大的不同。所有的輸出修飾符前面都應該加上=字符,他們同樣在匯編代碼里面用%0到%N-1來表示, 在輸出字段按順序排列。你一定會問假如同時有輸入和輸出字段會怎么排序的呢? 好,下面一個例子就是讓大家知道如何同時處理輸入輸出字段的。

int i=0, j=1, k=0;
__asm__ __volatile__("
pushl %%eax

movl %1, %%eax

addl %2, %%eax

movl %%eax, %0

popl %%eax"
: "=g" (k)
: "g" (i), "g" (j)
);// k = i + j
Okay, 唯一個不清楚的地方就是匯編代碼中的變量的個數。我馬上來解釋一下。
當同時使用輸入字段和輸出字段的時候:

%0 ... %K 是輸出變量

%K+1 ... %N 是輸入變量

在我們的例子中, %0對應k, %1對應i, %2對應j。很簡單,是吧?

到現在為止我們都沒有使用最后一個字段(registers-modified)。假如我們要在我們的匯編代碼里使用任何寄存器, 我們要明確的用push和pop指令來保存它們, 或者列到最后一個字段里面讓gcc來處理它們。


這是前面的一個例子, 沒有明確的保留和存貯eax。

int i=0, j=1, k=0;
__asm__ __volatile__("
pushl %%eax
/*譯者注:似乎原文說的有點問題,明明是保存了eax的值,:(*/
movl %1, %%eax

addl %2, %%eax

movl %%eax, %0

popl %%eax"
: "=g" (k)
: "g" (i), "g" (j)
: "ax", "memory"
);// k = i + j
我們讓gcc來保存和存貯eax, 假如必要的話。一個16-bit寄存器名代表了32-, 16-或8-bit寄存器。 假如我們要改寫內存 (寫入一個變量等。), 建議在register-modified字段里面來指定"memroy"修飾符。這意味著除了第一個例子我們都應該加上這個修飾符, 但是直到現在我才提出來, 是為了更簡單易懂。

在你的內聯匯編里面定位標號應該使用b或f來作為終止符, 尤其是向后向前的跳轉。(譯者注:b代表向后跳轉,f代表向前跳轉)

For example,

__asm__ __volatile__("
0:

...
jmp 0b

...
jmp 1f

...
1:

...
);
這里有個用c代碼和內聯匯編代碼混合寫的跳轉程序的例子(thanks to Srikanth B.R for this tip).


void MyFunction( int x, int y )
{
__asm__( "Start:" );
__asm__( ...do some comparison... );
__asm__( "jl Label_1" );

CallFunction( &x, &y );
__asm__("jmp Start");

Label_1:
return;
}

--------------------------------------------------------------------------------

External Asm
Blah... Okay fine. Here's a clue: Get some of your C/C++ files, 且用gcc -S file.c來編譯。 然
后查看file.S文件?;窘Y構如下:
.file "myasm.S"

.data
somedata: .word 0
...

.text
.globl __myasmfunc
__myasmfunc:
...
ret
Macros, macros! 頭文件libc/asmdefs.h便于你寫asm。 在你的匯編代碼最前面包含此頭文件然后就可以
使用宏了。一個例子: myasm.S:
#include <libc/asmdefs.h>

.file "myasm.S"

.data
.align 2
somedata: .word 0
...

.text
.align 4
FUNC(__MyExternalAsmFunc)
ENTER
movl ARG1, %eax
...
jmp mylabel
...
mylabel:
...
LEAVE
這是一個很經典的匯編代碼框架。

///////////////////////////////////////////////////////////////////////////////
linux下gcc的匯編格式是at&t格式的,和我們平時用的intel格式的匯編語法不一樣,所以很多熟悉windows匯編的人到linux下有點無所適從,所以我貼了我以前寫的這篇文檔,幫助大家理解at&t匯編,做個參考手冊
////////////////////////////////////////////////////////////////////////////////

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产女人精品视频| 伊人激情综合网| 日本欧美一二三区| 日韩精品有码在线观看| 日韩中文字幕国产精品| 欧美在线观看网站| 成人av色在线观看| 亚洲色图国产精品| 日韩中文理论片| 中文字幕九色91在线| 高清欧美一区二区三区| 国产丝袜精品第一页| 国产精品免费一区豆花| 5278欧美一区二区三区| 91久久国产综合久久91精品网站| 中文字幕久久久av一区| 性欧美亚洲xxxx乳在线观看| 亚洲欧美国产视频| 久久人人爽人人| 日韩精品视频免费在线观看| 日韩av在线影院| 欧美多人乱p欧美4p久久| 国产一区二区三区日韩欧美| 久久av中文字幕| 日日狠狠久久偷偷四色综合免费| 日韩av一区二区在线观看| 国内精品一区二区三区| 亚洲人成电影在线观看天堂色| 欧美成人四级hd版| 日韩精品免费综合视频在线播放| 国产精品69精品一区二区三区| 成人欧美一区二区三区黑人| 成人a级免费视频| 亚洲免费av片| 欧亚精品在线观看| 日本一区二区在线免费播放| 国产欧美日韩精品丝袜高跟鞋| 久久久www成人免费精品张筱雨| 欧美专区国产专区| 日韩中文字幕国产| 91精品久久久久久久| 欧美激情亚洲一区| 中日韩美女免费视频网址在线观看| 久久91精品国产91久久久| 亚洲精品电影在线| 亚洲精品videossex少妇| 国产一区视频在线播放| 亚洲精品国精品久久99热一| 精品毛片三在线观看| 懂色av影视一区二区三区| 亚洲精品女av网站| 国产一区二区激情| 中文字幕v亚洲ⅴv天堂| 久久国产精品久久国产精品| 亚洲专区国产精品| 日韩欧美国产黄色| 亚洲国产天堂久久国产91| 亚洲国产精品久久久久久| 日韩电影免费观看中文字幕| 日韩精品中文字幕在线| 国产91久久婷婷一区二区| 精品欧美国产一区二区三区| 亚洲国产精品成人av| 国产一区二区av| 日韩中文av在线| www.国产精品一二区| 欧美刺激性大交免费视频| 欧美在线视频观看| 国语对白做受69| 55夜色66夜色国产精品视频| 亚洲精品一区二区三区婷婷月| 亚洲美女福利视频网站| 国产精品久久久久久久7电影| 国产主播在线一区| 午夜精品久久久久久久久久久久久| 色偷偷91综合久久噜噜| 久久精品视频免费播放| 日韩大片免费观看视频播放| 91精品久久久久| 国产精品一区二区久久久| 国产精品久久久久久久美男| 国产一区二区动漫| 91精品视频一区| 国产精品欧美日韩久久| y97精品国产97久久久久久| 97超级碰在线看视频免费在线看| 亚洲精品视频网上网址在线观看| 成人久久久久爱| 欧美亚洲视频在线看网址| 91中文字幕在线| 国产69精品久久久久9| 日本精品一区二区三区在线| 亚洲系列中文字幕| 久久久精品一区二区三区| 久久久91精品| 欧美在线视频播放| 91欧美精品成人综合在线观看| 欧美激情一区二区三区在线视频观看| 国产精品日韩专区| 91在线观看欧美日韩| 国产福利视频一区| 亚洲精品免费网站| 欧美日韩中文字幕在线视频| 欧美日韩亚洲高清| 亚洲综合国产精品| 国产日韩精品综合网站| 亚洲女同性videos| 国产欧美一区二区白浆黑人| 精品国内产的精品视频在线观看| 亚洲国产成人久久| 国产精品自产拍高潮在线观看| 欧美在线视频一区| 欧美电影免费观看高清| 久久影视免费观看| 国产精自产拍久久久久久| 亚洲精品白浆高清久久久久久| 久久久久成人网| 国产午夜精品全部视频在线播放| 欧美日韩中文在线| 欧美精品精品精品精品免费| 色偷偷偷亚洲综合网另类| 日韩视频免费观看| 国产精品久久久久久五月尺| 午夜精品99久久免费| 亚洲日本aⅴ片在线观看香蕉| 成人国产精品久久久久久亚洲| 欧美大片大片在线播放| 日韩欧美中文第一页| 这里只有精品在线播放| 精品电影在线观看| 亚洲成人黄色在线观看| 日韩免费不卡av| 国外成人在线视频| 97香蕉久久超级碰碰高清版| 亚洲三级免费看| 成人有码在线播放| 国产精品成久久久久三级| 久久精品一区中文字幕| 国产在线播放不卡| 国产精品久久一区| 久久成人一区二区| 精品少妇一区二区30p| 在线观看视频亚洲| 久久深夜福利免费观看| 欧美一区第一页| 欧美日韩国产999| 欧美午夜丰满在线18影院| 一区二区三区回区在观看免费视频| 欧美亚洲一级片| 精品毛片网大全| 国产欧美一区二区三区久久人妖| 高清一区二区三区日本久| 亚洲精品久久7777777| 午夜精品久久17c| 国产999在线| 亚洲欧美中文另类| 精品久久久免费| 亚洲日本欧美日韩高观看| 国产成人一区二区在线| 在线播放亚洲激情| 国产精品第100页| 成人h视频在线观看播放| 久久精品久久精品亚洲人| 日韩av有码在线|