gcc中的內(nèi)嵌匯編語言_第1頁
gcc中的內(nèi)嵌匯編語言_第2頁
gcc中的內(nèi)嵌匯編語言_第3頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、gcc中的內(nèi)嵌匯編語言作者:歐陽光初次接觸到AT&T格式的匯編代碼,看著那一堆莫名其妙的怪符號,真是有點痛不欲生的感覺,只好慢慢地去啃g(shù)cc文檔,在似懂非懂的狀態(tài)下過了一段時間。后來又在網(wǎng)上找到了靈溪寫的gcc中的內(nèi)嵌匯編語言一文,讀后自感大有裨益。幾個月下來,接觸的源代碼多了以后,慢慢有了一些經(jīng)驗。為了使初次接觸AT&T格式的匯編代碼的同志不至于遭受我這樣的痛苦,就整理出該文來和大家共享.如有錯誤之處,歡迎大家指正,共同提高.本文主要以舉例的方式對gcc中的內(nèi)嵌匯編語言進(jìn)行進(jìn)一步的解釋。一、gcc對內(nèi)嵌匯編語言的處理方式gcc在編譯內(nèi)嵌匯編語言時,采取的步驟如下1. 變量輸入:根據(jù)限定符的內(nèi)

2、容將輸入操作數(shù)放入合適的寄存器,如果限定符指定為立即數(shù)(I)或內(nèi)存變量(m),則該步被省略,如果限定符沒有具體指定輸入操作數(shù)的類型(如常用的g),gcc會視需要決定是否將該操作數(shù)輸入到某個寄存器.這樣每個占位符都與某個寄存器,內(nèi)存變量,或立即數(shù)形成了一一對應(yīng)的關(guān)系.這就是對第二個冒號后內(nèi)容的解釋.如:a(foo),T(100),m(bar)表示%0對應(yīng)eax寄存器,%1對應(yīng)100,%2對應(yīng)內(nèi)存變量bar.2. 生成代碼:然后根據(jù)這種一一對應(yīng)的關(guān)系(還應(yīng)包括輸出操作符),用這些寄存器,內(nèi)存變量,或立即數(shù)來取代匯編代碼中的占位符(則有點像宏操作),注意,則一步驟并不檢查由這種取代操作所生成的匯編代

3、碼是否合法,例如,如果有這樣一條指令asm(movl%0,%1:m(foo),m(bar);如果你用gcc-c-S選項編譯該源文件,那么在生成的匯編文件中,你將會看到生成了movlfoo,bar這樣一條指令,這顯然是錯誤的.這個錯誤在稍后的編譯檢查中會被發(fā)現(xiàn).3. 變量輸出:按照輸出限定符的指定將寄存器的內(nèi)容輸出到某個內(nèi)存變量中,如果輸出操作數(shù)的限定符指定為內(nèi)存變量(m),則該步驟被省略.這就是對第一個冒號后內(nèi)容的解釋,如:asm(mov%0,%1:=m(foo),=a(bar):);編譯后為#APPmovlfoo,eax#NO_APPmovleax,bar該語句雖然有點怪怪的,但它很好的體現(xiàn)

4、了gcc的運作方式.再以arch/i386/kernel/apm.c中的一段代碼為例,我們來比較一下它們編譯前后的情況源程序編譯后的匯編代碼_asm_(pushl%edintpushl%ebpntsaisa%|aoiupaxpa%|aoiu8lX08%|AOIUqaxqa%|aoiueaxea%iaoiuddV_ON#!P9%|doddqa%|dodaqa|ppe|e%ogs:so%|eo|dqa%|qsnd!P9%lUsndddV#X08%,UI-X08|AOIUxq8%,ui-xq8|aoiuxe8%,ui-xe8iaoiu(urxo8)11o11,(urxq8)11q11,(uFxe8)

5、11e11:(se)11S=H,(P9).1P=.1,(O9).P=.1,(q8)11q=11,(e8)11e=11:.Ju!pe%|dodu.judq8%|dodu.Ju2%lL%ippeu.Ju|e%ops“.ju:so%|eo|u第三個冒號后面內(nèi)容主要針對gcc優(yōu)化處理,它告訴gcc在本段匯編代碼中對寄存器和內(nèi)存的使用情況,以免gcc在優(yōu)化處理時產(chǎn)生錯誤.1.它可以是eax,ebx,ecx等寄存器名,表示本段匯編代碼對該寄存器進(jìn)行了顯式操作,如asm(mov%eax,%0,:=r(foo):eax);這樣gcc在優(yōu)化時會避免使用eax作臨時變量,或者避免cache到eax的內(nèi)存變量通過該

6、段匯編碼.下面的代碼均用gcc的-02級優(yōu)化,它顯示了嵌入?yún)R編中第三個冒號后eax的作用源程序編譯后的匯編代碼正常情況下intmain()intbar=1;bar=fun();bar+;returnbar;pushl%ebpmovl%esp,%ebpcallfunincl%eax#顯然,bar缺省使用eax寄存器leaveret加了匯編后intmain()intbar=1;bar=fun();asmvolatile(:eax);bar+;returnbar;pushl%ebpmovl%esp,%ebp#建立堆棧框架callfun#fun的返回值放入bar中,此時由于嵌入?yún)R編#指明改變了eax的

7、值,為了避免沖突,#bar改為使用edx寄存器movl%eax,%edx#APP#NO_APPincl%edxmovl%edx,%eax#放入main()的返回值leaveret2.merory是一個常用的限定,它表示匯編代碼以不可預(yù)知的方式改變了內(nèi)存,這樣gcc在優(yōu)化時就不會讓cache到寄存器的內(nèi)存變量使用該寄存器通過匯編代碼,否則可能會發(fā)生同步出錯.有了上面的例子,這個問題就很好理解了三.對&限定符的解釋這是一個較常見用于輸出的限定符.它告訴gcc輸出操作數(shù)使用的寄存器不可再讓輸入操作數(shù)使用.對于g,r等限定符,為了有效利用為數(shù)不多的幾個通用寄存器,gcc一般會讓輸入操作數(shù)和輸出操作數(shù)選

8、用同一個寄存器.但如果代碼沒編好,會引起一些意想不到的錯誤:如asm(callfun;movebx,%1:=a(foo):r(bar);gcc編譯的結(jié)果是foo和bar同時使用eax寄存器:movlbar,eax#APPcallfunmovlebx,eax#NO_APPmovleax,foo本來這段代碼的意圖是將fun()函數(shù)的返回值放入foo變量,但半路殺出個程咬金,用ebx的值沖掉了返回值,所以這是一段錯誤的代碼,解決的方法是加上一個給輸出操作數(shù)加上一個&限定符:asm(callfun;movebx,%1:=&a(foo):r(bar);這樣gcc就會讓輸入操作數(shù)另尋高就,不再使用eax寄

9、存器了GCC內(nèi)嵌匯編簡介發(fā)表:2004-4-30:16:23出處:你的博客網(wǎng)()在內(nèi)嵌匯編中,可以將C語言表達(dá)式指定為匯編指令的操作數(shù),而且不用去管如何將C語言表達(dá)式的值讀入哪個寄存器,以及如何將計算結(jié)果寫回C變量,你只要告訴程序中C語言表達(dá)式與匯編指令操作數(shù)之間的對應(yīng)關(guān)系即可,GCC會自動插入代碼完成必要的操作。1、簡單的內(nèi)嵌匯編例:_asmvolatile_(hit);“表示后面”勺代碼為內(nèi)嵌匯編,“asn是“_asm別名?!癬volatile_示編譯器不要優(yōu)化代碼,后面的指令保留原樣,“volatile是它的別名。括號里面是匯編指令。2、內(nèi)嵌匯編舉例使用內(nèi)嵌匯編,

10、要先編寫匯編指令模板,然后將C語言表達(dá)式與指令的操作數(shù)相關(guān)聯(lián),并告訴GCC對這些操作有哪些限制條件。例如在下面的匯編語句:_asmviolate_(movl%1,%0:=r(result):m(input);“movl%1,%0是指令模板;“(和“1代表指令的操作數(shù),稱為占位符,內(nèi)嵌匯編靠它們將C語言表達(dá)式與指令操作數(shù)相對應(yīng)。指令模板后面用小括號括起來的是C語言表達(dá)式,本例中只有兩個:“resul和”“input,”他們按照出現(xiàn)的順序分別與指令操作數(shù)“0,“1對應(yīng);注意對應(yīng)順序:第一個C表達(dá)式對應(yīng)“0;第二個表達(dá)式對應(yīng)“”依次類推,操作數(shù)至多有10個,分別用“0,“1.表%9示。在每個操作數(shù)前

11、面有一個用引號括起來的字符串,字符串的內(nèi)容是對該操作數(shù)的限制或者說要求。“resul前面的限制字符串是“=r,”其中“二表示“resul是輸出操作數(shù),“表示需要將“resul與某個通用寄存器相關(guān)聯(lián),先將操作數(shù)的值讀入寄存器,然后在指令中使用相應(yīng)寄存器,而不是“resul本身,當(dāng)然指令執(zhí)行完后需要將寄存器中的值存入變量“result,從表面上看好像是指令直接對“resul進(jìn)行操作,實際上GCC做了隱式處理,這樣我們可以少寫一些指令?!癷nput前面的“r表示該表達(dá)式需要先放入某個寄存器,然后在指令中使用該寄存器參加運算。C表達(dá)式或者變量與寄存器的關(guān)系由GCC自動處理,我們只需使用限制字符串指導(dǎo)G

12、CC如何處理即可。限制字符必須與指令對操作數(shù)的要求相匹配,否則產(chǎn)生的匯編代碼將會有錯,讀者可以將上例中的兩個“,都改為“m(r表示操作數(shù)放在內(nèi)存,而不是寄存器中),編譯后得到的結(jié)果是:movlinput,result很明顯這是一條非法指令,因此限制字符串必須與指令對操作數(shù)的要求匹配。例如指令movl允許寄存器到寄存器,立即數(shù)到寄存器等,但是不允許內(nèi)存到內(nèi)存的操作,因此兩個操作數(shù)不能同時使用“m乍為限定字符GCC內(nèi)嵌匯編2出處:內(nèi)嵌匯編語法如下:_asm_(匯編語句模板:輸出部分:輸入部分:破壞描述部分)共四個部分:匯編語句模板,輸出部分,輸入部分,破壞描述部分,各部分使用“:”格開,匯編語句模

13、板必不可少,其他三部分可選,如果使用了后面的部分,而前面部分為空,也需要用“:”格開,相應(yīng)部分內(nèi)容為空。例如:_asm_volatile_(cli:memory)、匯編語句模板匯編語句模板由匯編語句序列組成,語句之間使用“;”、n”或“t”分開。指令中的操作數(shù)可以使用占位符引用C語言變量,操作數(shù)占位符最多10個,名稱如下:%0,%1,%9。指令中使用占位符表示的操作數(shù),總被視為long型(4個字節(jié)),但對其施加的操作根據(jù)指令可以是字或者字節(jié),當(dāng)把操作數(shù)當(dāng)作字或者字節(jié)使用時,默認(rèn)為低字或者低字節(jié)。對字節(jié)操作可以顯式的指明是低字節(jié)還是次字節(jié)。方法是在%和序號之間插入一個字母,“b”代表低字節(jié),h”

14、代表高字節(jié),例如:%h1。1 、輸出部分輸出部分描述輸出操作數(shù),不同的操作數(shù)描述符之間用逗號格開,每個操作數(shù)描述符由限定字符串和C語言變量組成。每個輸出操作數(shù)的限定字符串必須包含“=”表示他是一個輸出操作數(shù)。例:_asm_volatile_(pushfl;popl%0;cli:=g(x)描述符字符串表示對該變量的限制條件,這樣GCC就可以根據(jù)這些條件決定如何分配寄存器,如何產(chǎn)生必要的代碼處理指令操作數(shù)與C表達(dá)式或C變量之間的聯(lián)系。2 、輸入部分輸入部分描述輸入操作數(shù),不同的操作數(shù)描述符之間使用逗號格開,每個操作數(shù)描述符由限定字符串和C語言表達(dá)式或者C語言變量組成。例1:_asm_volatil

15、e_(lidt%0:m(real_mode_idt);例二(bitops.h):Static_inline_void_set_bit(intnr,volatilevoid*addr)_asm_(btsl%1,%0:=m(ADDR):Ir(nr);后例功能是將(*addr)的第nr位設(shè)為1。第一個占位符%0與C語言變量ADDR對應(yīng),第二個占位符%1與C語言變量nr對應(yīng)。因此上面的匯編語句代碼與下面的偽代碼等價:btslnr,ADDR,該指令的兩個操作數(shù)不能全是內(nèi)存變量,因此將nr的限定字符串指定為“l(fā)r,將nr與立即數(shù)或者寄存器相關(guān)聯(lián),這樣兩個操作數(shù)中只有ADDR為內(nèi)存變量。4、限制字符4.1、

16、限制字符列表限制字符有很多種,有些是與特定體系結(jié)構(gòu)相關(guān),此處僅列出常用的限定字符和i386中可能用到的一些常用的限定符。它們的作用是指示編譯器如何處理其后的C語言變量與指令操作數(shù)之間的關(guān)系。分類限定符描述通用寄存器a”將輸入變量放入eax這里有一個問題:假設(shè)eax已經(jīng)被使用,那怎么辦?其實很簡單:因為GCC知道eax已經(jīng)被使用,它在這段匯編代碼的起始處插入一條語句pushl%eax,將eax內(nèi)容保存到堆棧,然后在這段代碼結(jié)束處再增加一條語句popl%eax,恢復(fù)eax的內(nèi)容b”將輸入變量放入C將輸入變量放入ebxecxd將輸入變量放入edxS將輸入變量放入d將輸入變量放入esiedi“q將輸入

17、變量放入eax,ebx,ecx,edx中的一個f將輸入變量放入通用寄存器,也就是eax,ebx,ecx,edx,esi,edi中的一個A”把eax和edx合成一個64位的寄存器(uselongIongs)內(nèi)存m”內(nèi)存變量o”操作數(shù)為內(nèi)存變量,但是其尋址方式是偏移量類型,也即是基址尋址,或者是基址加變址尋址“V操作數(shù)為內(nèi)存變量,但尋址方式不是偏移量類型“”操作數(shù)為內(nèi)存變量,但尋址方式為自動增量p”操作數(shù)是一個合法的內(nèi)存地址(指針)寄存器或內(nèi)存g”將輸入變量放入eax,ebx,ecx,edx中的一個或者作為內(nèi)存變量X”操作數(shù)可以是任何類型立即數(shù)“I”0-31之間的立即數(shù)(用于32位移位指令)“J”

18、0-63之間的立即數(shù)(用于64位移位指令)“N”0-255之間的立即數(shù)(用于out指令)“”立即數(shù)n”立即數(shù),有些系統(tǒng)不支持除字以外的立即數(shù),這些系統(tǒng)應(yīng)該使用“n”而不是i”匹配“0”,表示用它限制的操作數(shù)與某個指定的操作數(shù)匹配,“1”.也即該操作數(shù)就是指定的那個操作數(shù),例如“0”“9”去描述“1”操作數(shù),那么“%1”引用的其實就是“%0”操作數(shù),注意作為限定符字母的09與指令中的“0”“9”的區(qū)別,前者描述操作數(shù),后者代表操作數(shù)。&該輸出操作數(shù)不能使用過和輸入操作數(shù)相同的寄存器操作數(shù)類型“=”操作數(shù)在指令中是只寫的(輸出操作數(shù))“+”操作數(shù)在指令中是讀寫類型的(輸入輸出操作數(shù))浮點數(shù)浮點寄存

19、器“t”第一個浮點寄存器u”第二個浮點寄存器G”標(biāo)準(zhǔn)的80387浮點常數(shù)%該操作數(shù)可以和下一個操作數(shù)交換位置例如addl的兩個操作數(shù)可以交換順序(當(dāng)然兩個操作數(shù)都不能是立即數(shù))# 部分注釋,從該字符到其后的逗號之間所有字母被忽略表示如果選用寄存器,則其后的字母被忽略5、破壞描述部分破壞描述符用于通知編譯器我們使用了哪些寄存器或內(nèi)存,由逗號格開的字符串組成,每個字符串描述一種情況,一般是寄存器名;除寄存器外還有“memory。例如:eax”,ebx“memory”等。AT&T與INTEL的匯編語言語法的區(qū)別岀處:1、大小寫INTEL格式的指令使用大寫字母,而AT&T格式的使用小寫字母。例:INT

20、ELAT&TMOVEAX,EBXmovl%ebx,%eax2、操作數(shù)賦值方向在INTEL語法中,第一個表示目的操作數(shù),第二個表示源操作數(shù),賦值方向從右向左。AT&T語法第一個為源操作數(shù),第二個為目的操作數(shù),方向從左到右,合乎自然。例:INTELAT&TMOVEAX,EBXmovl%ebx,%eax3、前綴在INTEL語法中寄存器和立即數(shù)不需要前綴;AT&T中寄存器需要加前綴“%”;立即數(shù)需要加前綴“$”。例:INTELAT&TMOVEAX,1movl$1,%eax符號常數(shù)直接引用,不需要加前綴,如:movlvalue,%ebx,value為一常數(shù);在符號前加前綴$表示引用符號地址,如movl$

21、value,%ebx,是將value的地址放到ebx中??偩€鎖定前綴lock:總線鎖定操作?!發(fā)ock前綴在Linux核心代碼中使用很多,特別是SMP代碼中。當(dāng)總線鎖定后其它CPU不能存取鎖定地址處的內(nèi)存單元。遠(yuǎn)程跳轉(zhuǎn)指令和子過程調(diào)用指令的操作碼使用前綴l,分別為ljmp,Icall,與之相應(yīng)的返回指令偽lret。例:INTELAT&TCALLFARSECTION:OFFSETlcall$secion:$offsetJMPFARSECTION:OFFSETljmp$secion:$offsetRETFARSATCK_ADJUSTlret$stack_adjust3 、間接尋址語法INTEL中基

22、地址使用“”、“”,而在AT&T中使用“(”、)“”;另外處理復(fù)雜操作數(shù)的語法也不同,INTEL為Segreg:base+index*scale+disp,而在AT&T中為%segreg:disp(base,index,sale),其中segreg,index,scale,disp都是可選的,在指定index而沒有顯式指定Scale的情況下使用默認(rèn)值1。Scale和disp不需要加前綴“&”。INTELAT&TInstrinstrfoo,segreg:base+index*scale+disp%segreg:disp(base,index,scale),foo、后綴AT&T語法中大部分指令操作

23、碼的最后一個字母表示操作數(shù)大小,“b”表示byte(個字節(jié));“w”表示word(2個字節(jié));“丨”表示long(4個字節(jié))。INTEL中處理內(nèi)存操作數(shù)時也有類似的語法如:BYTEPTR、WORDPTR、DWORDPTR。例:INTELAT&Tmoval,blmovb%bl,%almovax,bxmovw%bx,%axmoveax,dwordptrebxmovl(%ebx),%eax在AT&T匯編指令中,操作數(shù)擴(kuò)展指令有兩個后綴,一個指定源操作數(shù)的字長,另一個指定目標(biāo)操作數(shù)的字長。AT&T的符號擴(kuò)展指令的為“movs”,零擴(kuò)展指令為“movz”(相應(yīng)的Intel指令為movsx”和movzx”

24、)。因此,movsbl%al,%edx”表示對寄存器al中的字節(jié)數(shù)據(jù)進(jìn)行字節(jié)到長字的符號擴(kuò)展,計算結(jié)果存放在寄存器edx中。下面是一些允許的操作數(shù)擴(kuò)展后綴:bl:字節(jié)-長字bw:字節(jié)-字wl:字-長字跳轉(zhuǎn)指令標(biāo)號后的后綴表示跳轉(zhuǎn)方向,“f表示向前(forward),b表示向后(back)。例:jmp1f1:jmp1f1:6、指令I(lǐng)NTEL匯編與AT&T匯編指令基本相同,差別僅在語法上。關(guān)于每條指令的語法可以參考I386Manual。gcc中的內(nèi)嵌匯編語言出處:gcc采用的是AT&T的匯編格式,MS采用Intel的格式一基本語法語法上主要有以下幾個不同.寄存器命名原則AT&T:%eaxIntel

25、:eax源/目的操作數(shù)順序AT&T:movl%eax,%ebxIntel:movebx,eax常數(shù)/立即數(shù)的格式AT&T:movl$_value,%ebxIntel:moveax,_value把_value的地址放入eax寄存器AT&T:movl$0xd00d,%ebxIntel:movebx,0xd00d操作數(shù)長度標(biāo)識AT&T:movw%ax,%bxIntel:movbx,ax尋址方式AT&T:immed32(basepointer,indexpointer,indexscale)Intel:basepointer+indexpointer*indexscale+imm32)Linux工作于

26、保護(hù)模式下,用的是32位線性地址,所以在計算地址時不用考慮segmentffset的問題上式中的地址應(yīng)為:imm32+basepointer+indexpointer*indexscale下面是一些例子:直接尋址AT&T:_booga;_booga是一個全局的C變量注意加上$是表示地址引用,不加是表示值引用注:對于局部變量,可以通過堆棧指針引用Intel:_booga寄存器間接尋址AT&T:(%eax)Intel:eax變址尋址AT&T:_variable(%eax)Intel:eax+_variableAT&T:_array(,%eax,4)Intel:eax*4+_arrayAT&T:_a

27、rray(%ebx,%eax,8)Intel:ebx+eax*8+_array基本的行內(nèi)匯編基本的行內(nèi)匯編很簡單,一般是按照下面的格式asm(statements);例如:asm(nop);asm(cli);asm和_asm_是完全一樣的如果有多行匯編,則每一行都要加上nt例如:asm(pushl%eaxntmovl$0,%eaxntpopl%eax);實際上gcc在處理匯編時,是要把asm(.)的內(nèi)容打印到匯編文件中,所以格式控制字符是必要的再例如:asm(movl%eax,%ebx);asm(xorl%ebx,%edx);asm(movl$0,_booga);在上面的例子中,由于我們在行內(nèi)

28、匯編中改變了edx和ebx的值,但是由于gcc的特殊的處理方法,即先形成匯編文件,再交給GAS去匯編,所以GAS并不知道我們已經(jīng)改變了edx和ebx的值,如果程序的上下文需要edx或ebx作暫存,這樣就會引起嚴(yán)重的后果對于變量_booga存在一樣的問題為了解決這個問題,就要用到擴(kuò)展的行內(nèi)匯編語法三擴(kuò)展的行內(nèi)匯編擴(kuò)展的行內(nèi)匯編類似于Watcom.基本的格式是:asm(statements:output_regs:input_regs:clobbered_regs);clobbered_regs指的是被改變的寄存器下面是一個例子(為方便起見,我使用全局變量):intcount=1;intvalue

29、=1;intbuf10;voidmain()asm(cldntrepntstosl:c(count),a(value),D(buf0):%ecx,%edi);得到的主要匯編代碼為:movlcount,%ecxmovlvalue,%eaxmovlbuf,%edi#APPcldrepstosl#NO_APPcld,rep,stos就不用多解釋了這幾條語句的功能是向buf中寫上count個value值冒號后的語句指明輸入,輸出和被改變的寄存器通過冒號以后的語句,編譯器就知道你的指令需要和改變哪些寄存器,從而可以優(yōu)化寄存器的分配其中符號c(count)指示要把count的值放入ecx寄存器類似的還有:

30、aeaxbebxcecxdedxSesiDediI常數(shù)值,(0-31)q,r動態(tài)分配的寄存器geax,ebx,ecx,edx或內(nèi)存變量A把eax和edx合成一個64位的寄存器(uselonglongs)我們也可以讓gcc自己選擇合適的寄存器如下面的例子:asm(leal(%1,%1,4),%0:=r(x):0(x);這段代碼實現(xiàn)5*x的快速乘法得到的主要匯編代碼為:movlx,%eax#APPleal(%eax,%eax,4),%eax#NO_APPmovl%eax,x幾點說明:1. 使用q指示編譯器從eax,ebx,ecx,edx分配寄存器使用r指示編譯器從eax,ebx,ecx,edx,e

31、si,edi分配寄存器我們不必把編譯器分配的寄存器放入改變的寄存器列表,因為寄存器已經(jīng)記住了它們.2. =是標(biāo)示輸出寄存器,必須這樣用.3. 數(shù)字n的用法:數(shù)字表示的寄存器是按照岀現(xiàn)和從左到右的順序映射到用r或q請求的寄存器如果我們要重用r或q請求的寄存器的話,就可以使用它們.4. 如果強(qiáng)制使用固定的寄存器的話,如不用%1,而用ebx,貝9asm(leal(%ebx,%ebx,4),%0:=r(x):0(x);注意要使用兩個%,因為一個%的語法已經(jīng)被n用掉了GCC內(nèi)嵌匯編之語法詳解發(fā)表:2004-4-30:54:05出處:你的博客網(wǎng)()內(nèi)嵌匯編語法如下:_asm_(匯編

32、語句模板:輸出部分:輸入部分:破壞描述部分)共四個部分:匯編語句模板,輸出部分,輸入部分,破壞描述部分,各部分使用“:格開,匯編語句模板必不可少,其他三部分可選,如果使用了后面的部分,而前面部分為空,也需要用“:格開,相應(yīng)部分內(nèi)容為空。例如:_asmvolatile_(cli:memory)1、匯編語句模板匯編語句模板由匯編語句序列組成,語句之間使用“;n”或“t分開。指令中的操作數(shù)可以使用占位符引用C語言變量,操作數(shù)占位符最多10個,名稱如下:%0,%1,%9。指令中使用占位符表示的操作數(shù),總被視為long型(4個字節(jié)),但對其施加的操作根據(jù)指令可以是字或者字節(jié),當(dāng)把操作數(shù)當(dāng)作字或者字節(jié)使用

33、時,默認(rèn)為低字或者低字節(jié)。對字節(jié)操作可以顯式的指明是低字節(jié)還是次字節(jié)。方法是在%和序號之間插入一個字母,“b代表低字節(jié),“h代表高字節(jié),例如:h1。2、輸出部分輸出部分描述輸出操作數(shù),不同的操作數(shù)描述符之間用逗號格開,每個操作數(shù)描述符由限定字符串和C語言變量組成。每個輸出操作數(shù)的限定字符串必須包含“=表示他是一個輸出操作數(shù)。例:_asmvolatile_(pushfl;popl%0;cli:=g(x)描述符字符串表示對該變量的限制條件,這樣GCC就可以根據(jù)這些條件決定如何分配寄存器,如何產(chǎn)生必要的代碼處理指令操作數(shù)與C表達(dá)式或C變量之間的聯(lián)系。3、輸入部分輸入部分描述輸入操作數(shù),不同的操作數(shù)描

34、述符之間使用逗號格開,每個操作數(shù)描述符由限定字符串和C語言表達(dá)式或者C語言變量組成。例1:_asmvolatile_(lidt%0:m(real_mode_idt);例二(bitops.h):Static_inline_void_set_bit(intnr,volatilevoid*addr)_asm_(btsl%1,%0:=m(ADDR):(nr);后例功能是將(*addr)的第nr位設(shè)為1。第一個占位符%0與C語言變量ADDR對應(yīng),第二個占位符%1與C語言變量nr對應(yīng)。因此上面的匯編語句代碼與下面的偽代碼等價:btslnr,ADDR,該指令的兩個操作數(shù)不能全是內(nèi)存變量,因此將nr的限定字符串指定為“l(fā)r,”將nr與立即數(shù)或者寄存器相關(guān)聯(lián),這樣兩個操作數(shù)中只有ADDR為內(nèi)存變量。4、限制字符4.1、限制字符列表i386中可能用

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論