日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

浅析gcc内嵌汇编

發(fā)布時(shí)間:2024/9/5 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅析gcc内嵌汇编 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在Linux代碼中很多地方都使用了這種形式的匯編語(yǔ)言,嵌入?yún)R編程序的格式如下:
__asm__ __volatile__ (
asm statements
: outputs
: inputs
: registers-modified
);
asm statements是一組AT&T格式的匯編語(yǔ)言語(yǔ)句,每個(gè)語(yǔ)句一行,由\n分隔各行。所有的語(yǔ)句都被包裹在一對(duì)雙引號(hào)內(nèi)。其中使用的寄存器前面要加兩個(gè)%%做前綴;轉(zhuǎn)移指令多是局部轉(zhuǎn)移,因此多使用數(shù)字標(biāo)號(hào)。
inputs指明程序的輸入?yún)?shù),每個(gè)輸入?yún)?shù)都括在一對(duì)圓括號(hào)內(nèi),各參數(shù)用逗號(hào)分開(kāi)。每個(gè)參數(shù)前加一個(gè)用雙引號(hào)括起來(lái)的標(biāo)志,告訴編譯器把該參數(shù)裝入到何處。
可用的標(biāo)志有:
“g”:讓編譯器決定如何裝入它;
“a”:裝入到ax/eax;
“b”:裝入到bx/ebx;
“c”:裝入到cx/ecx;
“d”:裝入到dx/edx;
“D”:裝入到di/edi;
“S”:裝入到si/esi;
“q”:a、b、c、d寄存器等;
“r”:任一通用寄存器;
“i”:整立即數(shù);
“I”:0-31 之間的立即數(shù)(用于32位移位指令);
“J”:0-63 之間的立即數(shù)(用于64 位移位指令);
“N”:0-255 ,之間的立即數(shù)(用于out 指令);
“n”:立即數(shù),有些系統(tǒng)不支持除字以外的立即數(shù),這些系統(tǒng)應(yīng)該使用“n”而不是“i”;
“p”:有效內(nèi)存地址;
“m”:內(nèi)存變量;
“o”:操作數(shù)為內(nèi)存變量,但是其尋址方式是偏移量類(lèi)型,也即是基址尋址,或者是基址加變址尋址;
“V”:操作數(shù)為內(nèi)存變量,但尋址方式不是偏移量類(lèi)型;
“,”:操作數(shù)為內(nèi)存變量,但尋址方式為自動(dòng)增量;
“X”:操作數(shù)可以是任何類(lèi)型;
“f”:浮點(diǎn)數(shù);
“t”:第一個(gè)浮點(diǎn)寄存器;
“u”:第二個(gè)浮點(diǎn)寄存器;
“G”:標(biāo)準(zhǔn)的80387;
??% :浮點(diǎn)常數(shù),該操作數(shù)可以和下一個(gè)操作數(shù)交換位置;
“=”:輸出;
“+”:既是輸入又是輸出;
“&”:改變其值之前寫(xiě),分配一個(gè)獨(dú)立的寄存器,使得函數(shù)返回值和該變量不因?yàn)橹貜?fù)使用同一個(gè)寄存器,出現(xiàn)數(shù)據(jù)覆蓋;
“%”:與下一個(gè)操作數(shù)之間可互換;
“#”:忽略其后的字符,直到逗號(hào);
“*”:當(dāng)優(yōu)先選擇寄存器時(shí),忽略下面的字符;
“0”~“9”:指定一個(gè)操作數(shù),它既做輸入又做輸出。通常用“g”;
outputs指明程序的輸出位置,通常是變量。每個(gè)輸出變量都括在一對(duì)圓括號(hào)內(nèi),各個(gè)輸出變量間用逗號(hào)隔開(kāi)。每個(gè)輸出變量前加一個(gè)標(biāo)志,告訴編譯器從何處輸出。
可用的標(biāo)志與輸入?yún)?shù)用的標(biāo)志相同,只是前面加“=”。如“=g”。輸出操作數(shù)必須是左值,而且必須是只寫(xiě)的。如果一個(gè)操作數(shù)即做輸出又做輸入,那么必須將它們分開(kāi):一個(gè)只寫(xiě)操作數(shù),一個(gè)輸入操作數(shù)。輸入操作數(shù)前加一個(gè)數(shù)字限制(0~9),指出輸出操作數(shù)的序號(hào),告訴編譯器它們必須在同一個(gè)物理位置。兩個(gè)操作數(shù)可以是同一個(gè)表達(dá)式,也可以是不同的表達(dá)式。
registers-modified告訴編譯器程序中將要修改的寄存器。每個(gè)寄存器都用雙引號(hào)括起來(lái),并用逗號(hào)隔開(kāi)。如“ax”。如果匯編程序中引用了某個(gè)特定的硬件寄存器,就應(yīng)該在此處列出這些寄存器,以告訴編譯器這些寄存器的值被改變了。如果匯編程序中用某種不可預(yù)測(cè)的方式修改了內(nèi)存,應(yīng)該在此處加上“memory”。這樣以來(lái),在整個(gè)匯編程序中,編譯器就不會(huì)把它的值緩存在寄存器中了。
如:
“cc”:你使用的指令會(huì)改變CPU的條件寄存器cc;
“memory”:你使用的指令會(huì)修改內(nèi)存;?

__volatile__是可選的,它防止編譯器修改該段匯編語(yǔ)句(重排序、重組、刪除等)。
輸入?yún)?shù)和輸出變量按順序編號(hào),先輸出后輸入,編號(hào)從0開(kāi)始。程序中用編號(hào)代表輸入?yún)?shù)和輸出變量(加%做前綴)。
輸入、輸出、寄存器部分都可有可無(wú)。如有,順序不能變;如無(wú),應(yīng)保留“:”,除非不引起二意性。
看一個(gè)在C語(yǔ)言中使用at&t的嵌入?yún)R編程序的例子,c語(yǔ)言中的3個(gè)int變量,一般會(huì)是三個(gè)內(nèi)存地址。每個(gè)操作數(shù)的長(zhǎng)度則要根據(jù)操作系統(tǒng)和編譯器來(lái)決定,一般32位操作系統(tǒng)為32位,則每個(gè)操作數(shù)占用4個(gè)字節(jié):
int i=0, j=1, k=0;
__asm__ __volatile__("
??pushl %%eax\n? ?? ?? ?? ?? ?//asm statement
??movl %1, %%eax\n? ?? ?? ?? ?//asm statement
??addl %2, %%eax\n? ?? ?? ?? ?//asm statement
??movl %%eax, %0\n? ?? ?? ?? ?//...
??popl %%eax"? ?? ?? ?? ?? ???//...
: "=g" (k)? ?? ?? ?? ?? ?? ? //outputs? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
: "g" (i), "g" (j)? ?? ?? ???//inputs
: "ax", "memory"? ?? ?? ?? ? //registers modified
);? ??
按照參數(shù)編號(hào)原則輸出參數(shù)參數(shù)k為%0,輸入?yún)?shù)i和j依次為%1和%2。值得注意的是輸出和輸入標(biāo)志都使用了"g",所以我們不必關(guān)心這些參數(shù)究竟是使用了寄存器還是內(nèi)存操作數(shù),編譯器自己會(huì)決定。?

本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn): http://blog.chinaunix.net/u1/38994/showart_333001.html

總結(jié)

以上是生活随笔為你收集整理的浅析gcc内嵌汇编的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。