亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 841 | 回復(fù): 0
打印 上一主題 下一主題

GCC內(nèi)嵌匯編的一些資料 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2007-04-29 19:53 |只看該作者 |倒序?yàn)g覽

  內(nèi)核代碼絕大部分使用C語(yǔ)言編寫,只有一小部分使用匯編語(yǔ)言編寫,例如與特定體系結(jié)構(gòu)相關(guān)的代碼和對(duì)性能影響很大的代碼。GCC提供了內(nèi)嵌匯編的功能,可以在C代碼中直接內(nèi)嵌匯編語(yǔ)言語(yǔ)句,大大方便了程序設(shè)計(jì)。
簡(jiǎn)單的內(nèi)嵌匯編很容易理解
在網(wǎng)上找到的一點(diǎn)東西,希望對(duì)大家有用!
   在內(nèi)嵌匯編中,可以將C語(yǔ)言表達(dá)式指定為匯編指令的操作數(shù),而且不用去管如何將C語(yǔ)言表達(dá)式的值讀入哪個(gè)寄存器,以及如何將計(jì)算結(jié)果寫回C 變量,你只要告訴程序中C語(yǔ)言表達(dá)式與匯編指令操作數(shù)之間的對(duì)應(yīng)關(guān)系即可, GCC會(huì)自動(dòng)插入代碼完成必要的操作。
1、簡(jiǎn)單的內(nèi)嵌匯編
例:
     __asm__ __volatile__("hlt"); “__asm__”表示后面的代碼為內(nèi)嵌匯編,“asm”是“__asm__”的別名!癬_volatile__”表示編譯器不要優(yōu)化代碼,后面的指令保留原樣,“volatile”是它的別名。括號(hào)里面是匯編指令。
在內(nèi)嵌匯編中,可以將C語(yǔ)言表達(dá)式指定為匯編指令的操作數(shù),而且不用去管如何將C語(yǔ)言表達(dá)式的值讀入哪個(gè)寄存器,以及如何將計(jì)算結(jié)果寫回C 變量,你只要告訴程序中C語(yǔ)言表達(dá)式與匯編指令操作數(shù)之間的對(duì)應(yīng)關(guān)系即可, GCC會(huì)自動(dòng)插入代碼完成必要的操作。
1、簡(jiǎn)單的內(nèi)嵌匯編
例:
     __asm__ __volatile__("hlt"); “__asm__”表示后面的代碼為內(nèi)嵌匯編,“asm”是“__asm__”的別名。“__volatile__”表示編譯器不要優(yōu)化代碼,后面的指令保留原樣,“volatile”是它的別名。括號(hào)里面是匯編指令。
2、內(nèi)嵌匯編舉例
  使用內(nèi)嵌匯編,要先編寫匯編指令模板,然后將C語(yǔ)言表達(dá)式與指令的操作數(shù)相關(guān)聯(lián),并告訴GCC對(duì)這些操作有哪些限制條件。例如在下面的匯編語(yǔ)句:
   __asm__ __violate__ ("movl %1,%0" : "=r" (result) : "m" (input));   
“movl %1,%0”是指令模板;“%0”和“%1”代表指令的操作數(shù),稱為占位符,內(nèi)嵌匯編靠它們將C 語(yǔ)言表達(dá)式與指令操作數(shù)相對(duì)應(yīng)。指令模板后面用小括號(hào)括起來(lái)的是C語(yǔ)言表達(dá)式,本例中只有兩個(gè):“result”和“input”,他們按照出現(xiàn)的順序分別與指令操作數(shù)“%0”,“%1”對(duì)應(yīng);注意對(duì)應(yīng)順序:第一個(gè)C 表達(dá)式對(duì)應(yīng)“%0”;第二個(gè)表達(dá)式對(duì)應(yīng)“%1”,依次類推,操作數(shù)至多有10 個(gè),分別用“%0”,“%1”….“%9”表示。在每個(gè)操作數(shù)前面有一個(gè)用引號(hào)括起來(lái)的字符串,字符串的內(nèi)容是對(duì)該操作數(shù)的限制或者說(shuō)要求!皉esult”前面的限制字符串是“=r”,其中“=”表示“result”是輸出操作數(shù),“r”表示需要將“result”與某個(gè)通用寄存器相關(guān)聯(lián),先將操作數(shù)的值讀入寄存器,然后在指令中使用相應(yīng)寄存器,而不是“result”本身,當(dāng)然指令執(zhí)行完后需要將寄存器中的值存入變量“result”,從表面上看好像是指令直接對(duì)“result”進(jìn)行操作,實(shí)際上GCC做了隱式處理,這樣我們可以少寫一些指令!癷nput”前面的“r”表示該表達(dá)式需要先放入某個(gè)寄存器,然后在指令中使用該寄存器參加運(yùn)算。
  C表達(dá)式或者變量與寄存器的關(guān)系由GCC自動(dòng)處理,我們只需使用限制字符串指導(dǎo)GCC如何處理即可。限制字符必須與指令對(duì)操作數(shù)的要求相匹配,否則產(chǎn)生的匯編代碼將會(huì)有錯(cuò),讀者可以將上例中的兩個(gè)“r”,都改為“m”(m表示操作數(shù)放在內(nèi)存,而不是寄存器中),編譯后得到的結(jié)果是:
            movl input, result
很明顯這是一條非法指令,因此限制字符串必須與指令對(duì)操作數(shù)的要求匹配。例如指令movl允許寄存器到寄存器,立即數(shù)到寄存器等,但是不允許內(nèi)存到內(nèi)存的操作,因此兩個(gè)操作數(shù)不能同時(shí)使用“m”作為限定字符。
內(nèi)嵌匯編語(yǔ)法如下:
      __asm__(匯編語(yǔ)句模板: 輸出部分: 輸入部分: 破壞描述部分)
共四個(gè)部分:匯編語(yǔ)句模板,輸出部分,輸入部分,破壞描述部分,各部分使用“:”格開(kāi),匯編語(yǔ)句模板必不可少,其他三部分可選,如果使用了后面的部分,而前面部分為空,也需要用“:”格開(kāi),相應(yīng)部分內(nèi)容為空。例如:
            __asm__ __volatile__("cli": : :"memory")
1、匯編語(yǔ)句模板
   匯編語(yǔ)句模板由匯編語(yǔ)句序列組成,語(yǔ)句之間使用“;”、“\n”或“\n\t”分開(kāi)。指令中的操作數(shù)可以使用占位符引用C語(yǔ)言變量,操作數(shù)占位符最多10個(gè),名稱如下:%0,%1,…,%9。指令中使用占位符表示的操作數(shù),總被視為long型(4個(gè)字節(jié)),但對(duì)其施加的操作根據(jù)指令可以是字或者字節(jié),當(dāng)把操作數(shù)當(dāng)作字或者字節(jié)使用時(shí),默認(rèn)為低字或者低字節(jié)。對(duì)字節(jié)操作可以顯式的指明是低字節(jié)還是次字節(jié)。方法是在%和序號(hào)之間插入一個(gè)字母,“b”代表低字節(jié),“h”代表高字節(jié),例如:%h1。
2、輸出部分
   輸出部分描述輸出操作數(shù),不同的操作數(shù)描述符之間用逗號(hào)格開(kāi),每個(gè)操作數(shù)描述符由限定字符串和C 語(yǔ)言變量組成。每個(gè)輸出操作數(shù)的限定字符串必須包含“=”表示他是一個(gè)輸出操作數(shù)。
例:
         __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x) )
描述符字符串表示對(duì)該變量的限制條件,這樣GCC 就可以根據(jù)這些條件決定如何分配寄存器,如何產(chǎn)生必要的代碼處理指令操作數(shù)與C表達(dá)式或C變量之間的聯(lián)系。
3、輸入部分
輸入部分描述輸入操作數(shù),不同的操作數(shù)描述符之間使用逗號(hào)格開(kāi),每個(gè)操作數(shù)描述符由限定字符串和C語(yǔ)言表達(dá)式或者C語(yǔ)言變量組成。
例1 :
           __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
例二(bitops.h):
Static __inline__ void __set_bit(int nr, volatile void * addr)
{
       __asm__(
                        "btsl %1,%0"
                       :"=m" (ADDR)
                       :"Ir" (nr));
}
后例功能是將(*addr)的第nr位設(shè)為1。第一個(gè)占位符%0與C 語(yǔ)言變量ADDR對(duì)應(yīng),第二個(gè)占位符%1與C語(yǔ)言變量nr對(duì)應(yīng)。因此上面的匯編語(yǔ)句代碼與下面的偽代碼等價(jià):btsl nr, ADDR,該指令的兩個(gè)操作數(shù)不能全是內(nèi)存變量,因此將nr的限定字符串指定為“Ir”,將nr 與立即數(shù)或者寄存器相關(guān)聯(lián),這樣兩個(gè)操作數(shù)中只有ADDR為內(nèi)存變量。
4、限制字符
  4.1、限制字符列表
  限制字符有很多種,有些是與特定體系結(jié)構(gòu)相關(guān),此處僅列出常用的限定字符和i386中可能用到的一些常用的限定符。它們的作用是指示編譯器如何處理其后的C語(yǔ)言變量與指令操作數(shù)之間的關(guān)系。
  分類            限定符                    描述
通用寄存器       “a”               將輸入變量放入eax
                                             這里有一個(gè)問(wèn)題:假設(shè)eax已經(jīng)被使用,那怎么辦?
                                其實(shí)很簡(jiǎn)單:因?yàn)镚CC 知道eax 已經(jīng)被使用,它在這段匯編代碼
                                的起始處插入一條語(yǔ)句pushl %eax,將eax 內(nèi)容保存到堆棧,然
                                后在這段代碼結(jié)束處再增加一條語(yǔ)句popl %eax,恢復(fù)eax的內(nèi)容
                    “b”               將輸入變量放入ebx
                    “c”               將輸入變量放入ecx
                    “d”               將輸入變量放入edx
                     “s”              將輸入變量放入esi
                     “d”              將輸入變量放入edi
                     “q”              將輸入變量放入eax,ebx,ecx,edx中的一個(gè)
                     “r”               將輸入變量放入通用寄存器,也就是eax,ebx,ecx,
                                       edx,esi,edi中的一個(gè)
                    “A”              把eax和edx合成一個(gè)64 位的寄存器(use long longs)
      內(nèi)存            “m”             內(nèi)存變量
                    “o”             操作數(shù)為內(nèi)存變量,但是其尋址方式是偏移量類型,
                                      也即是基址尋址,或者是基址加變址尋址
                    “V”             操作數(shù)為內(nèi)存變量,但尋址方式不是偏移量類型
                    “ ”             操作數(shù)為內(nèi)存變量,但尋址方式為自動(dòng)增量
                    “p”             操作數(shù)是一個(gè)合法的內(nèi)存地址(指針)
    寄存器或內(nèi)存    “g”             將輸入變量放入eax,ebx,ecx,edx中的一個(gè)
                                      或者作為內(nèi)存變量
                     “X”            操作數(shù)可以是任何類型
    立即數(shù)
                    “I”             0-31之間的立即數(shù)(用于32位移位指令)
                     “J”            0-63之間的立即數(shù)(用于64位移位指令)
                    “N”             0-255之間的立即數(shù)(用于out指令)
                    “i”             立即數(shù)   
                    “n”            立即數(shù),有些系統(tǒng)不支持除字以外的立即數(shù),
                                      這些系統(tǒng)應(yīng)該使用“n”而不是“i”
    匹配            “ 0 ”,         表示用它限制的操作數(shù)與某個(gè)指定的操作數(shù)匹配,
                    “1” ...               也即該操作數(shù)就是指定的那個(gè)操作數(shù),例如“0”
                     “9”            去描述“%1”操作數(shù),那么“%1”引用的其實(shí)就
                                      是“%0”操作數(shù),注意作為限定符字母的0-9 與
                                      指令中的“%0”-“%9”的區(qū)別,前者描述操作數(shù),
                                      后者代表操作數(shù)。
                      &                     該輸出操作數(shù)不能使用過(guò)和輸入操作數(shù)相同的寄存器
   操作數(shù)類型        “=”          操作數(shù)在指令中是只寫的(輸出操作數(shù))   
                      “+”          操作數(shù)在指令中是讀寫類型的(輸入輸出操作數(shù))
    浮點(diǎn)數(shù)            “f”          浮點(diǎn)寄存器
                     “t”           第一個(gè)浮點(diǎn)寄存器
                     “u”          第二個(gè)浮點(diǎn)寄存器
                     “G”          標(biāo)準(zhǔn)的80387浮點(diǎn)常數(shù)
                      %                   該操作數(shù)可以和下一個(gè)操作數(shù)交換位置
                                      例如addl的兩個(gè)操作數(shù)可以交換順序
                                     (當(dāng)然兩個(gè)操作數(shù)都不能是立即數(shù))
                      #                   部分注釋,從該字符到其后的逗號(hào)之間所有字母被忽略
                      *                     表示如果選用寄存器,則其后的字母被忽略
5、破壞描述部分
  破壞描述符用于通知編譯器我們使用了哪些寄存器或內(nèi)存,由逗號(hào)格開(kāi)的字符串組成,每個(gè)字符串描述一種情況,一般是寄存器名;除寄存器外還有“memory”。例如:“%eax”,“%ebx”,“memory”等。


本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u1/36646/showart_289190.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP