日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

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

生活随笔

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

编程问答

GCC如何编译内嵌汇编代码

發(fā)布時(shí)間:2024/4/18 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GCC如何编译内嵌汇编代码 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
內(nèi)核代碼絕大部分使用C?
語(yǔ)言編寫(xiě),只有一小部分使用匯編語(yǔ)言編寫(xiě),例如與特定體系結(jié)構(gòu)相關(guān)的代碼和對(duì)性能影響很大的代碼。GCC提供了內(nèi)嵌匯編的功能,可以在C代碼中直接內(nèi)嵌匯編語(yǔ)言語(yǔ)句,大大方便了程序設(shè)計(jì)。?

簡(jiǎn)單的內(nèi)嵌匯編很容易理解?


例:?

__asm__?
__volatile__("hlt");?

“__asm__”表示后面的代碼為內(nèi)嵌匯編,“asm”是“__asm__”的別名。?
“__volatile__”表示編譯器不要優(yōu)化代碼,后面的指令保留原樣,?
“volatile”是它的別名。括號(hào)里面是匯編指令。?

2.2 內(nèi)嵌匯編舉例在內(nèi)嵌匯編中,可以將C?
語(yǔ)言表達(dá)式指定為匯編指令的操作數(shù),而且不用去管如何將C?
語(yǔ)言表達(dá)式的值讀入哪個(gè)寄存器,以及如何將計(jì)算結(jié)果寫(xiě)回C?
變量,你只要告訴程序中C語(yǔ)言表達(dá)式與匯編指令操作數(shù)之間的對(duì)應(yīng)關(guān)系即可, GCC?
會(huì)自動(dòng)插入代碼完成必要的操作。?


使用內(nèi)嵌匯編,要先編寫(xiě)匯編指令模板,然后將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?
”,依次類(lèi)推,操作數(shù)至多有10個(gè),分別用“%0”,“%1”….“%9,”表示。在每個(gè)操作數(shù)前?
面有一個(gè)用引號(hào)括起來(lái)的字符串,字符串的內(nèi)容是對(duì)該操作數(shù)的限制或者說(shuō)要求。“result”前面?
的限制字符串是“=r”,其中“=”表示“result”是輸出操作數(shù),“r?
”表示需要將“result”與某個(gè)通用寄存器相關(guān)聯(lián),先將操作數(shù)的值讀入寄存器,然后?
在指令中使用相應(yīng)寄存器,而不是“result”本身,當(dāng)然指令執(zhí)行完后需要將寄存器中的值?
存入變量“result”,從表面上看好像是指令直接對(duì)“result”進(jìn)行操作,實(shí)際上GCC?
做了隱式處理,這樣我們可以少寫(xiě)一些指令。“input”前面的“r”表示該表達(dá)式需要先放入?
某個(gè)寄存器,然后在指令中使用該寄存器參加運(yùn)算。?

我們將上面的內(nèi)嵌代碼放到一個(gè)C源文件中,然后使用gcc –c–S得到該C?
文件源代碼相對(duì)應(yīng)的匯編代碼,然后查看一下匯編代碼,看看GCC是如何處理的。?
C源文件如下內(nèi)容如下,注意該代碼沒(méi)有實(shí)際意義,僅僅作為例子。?

extern int?
input,result;?

void test(void)?
{?
input?
= 1;?
__asm__ __volatile__ ("movl %1,%0" :?
"=r" (result) : "r" (input));?
return?
;?
}?

對(duì)應(yīng)的匯編代碼如下;?

行號(hào) 代碼 解釋?

1?
7?
8 movl $1, input 對(duì)應(yīng)C語(yǔ)言語(yǔ)句input = 1;?
9 input, %eax?
10 #APP GCC插入的注釋,表示內(nèi)嵌匯編開(kāi)始?
11 movl %eax,%eax 我們的內(nèi)嵌匯編語(yǔ)句?
12 #NO_APP GCC 插入的注釋,表示內(nèi)嵌匯編結(jié)束?
13 movl %eax, result 將結(jié)果存入result變量?
14?
-?
18?
。。。。。。?

從匯編代碼可以看出,第9行和第13行是GCC,自動(dòng)增加的代碼,GCC?
根據(jù)限定字符串決定如何處理C表達(dá)式,本例兩個(gè)表達(dá)式都被指定為“r”型,所以先使用指令:?
movl input, %eax?

將input讀入寄存器%eax;GCC,也指定一個(gè)寄存器與輸出變量result?
相關(guān),本例也是%eax,等得到操作結(jié)果后再使用指令:?

movl %eax, result?


將寄存器的值寫(xiě)回C變量result中。從上面的匯編代碼我們可以看出與result?
和input,相關(guān)連的寄存器都是%eax,GCC使用%eax,替換內(nèi)嵌匯編指令模板中的?
%0,%1?

movl %eax,%eax?
顯然這一句可以不要。但是沒(méi)有優(yōu)化,所以這一句沒(méi)有被去掉。?

由此可見(jià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”作為限定字符。?

2.3 語(yǔ)法?


內(nèi)嵌匯編語(yǔ)法如下:?

__asm__(?
匯編語(yǔ)句模板:?
輸出部分:?
輸入部分:?
破壞描述部分)?


共四個(gè)部分:匯編語(yǔ)句模板,輸出部分,輸入部分,破壞描述部分,各部分使用“:”格?
開(kāi),匯編語(yǔ)句模板必不可少,其他三部分可選,如果使用了后面的部分,而前面部分為空,?
也需要用“:”格開(kāi),相應(yīng)部分內(nèi)容為空。例如:?

__asm__ __volatile__(?
"cli":?
:?
:"memory")?

2.3.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.3.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)系。?

2.3.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)存變量。?

2.3.4 限制字符?
2.3.4.1 限制字符列表?
限制字符有很多種,有些是與特定體系結(jié)構(gòu)相關(guān),此處僅列出常用的限定字符和i386?
中可能用到的一些常用的限定符。它們的作用是指示編譯器如何處理其后的C?
語(yǔ)言變量與指令操作數(shù)之間的關(guān)系,例如是將變量放在寄存器中還是放在內(nèi)存中等,?
下表列出了常用的限定字母。?

分類(lèi)?
限定符 描述 通用寄存器?


“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位的寄存器(uselong longs)?
“m”內(nèi)存變量?
“o”操作數(shù)為內(nèi)存變量,但是其尋址方式是偏移量類(lèi)型,也即是基址尋址,或者是基址加變址尋址?
“V”操作數(shù)為內(nèi)存變量,但尋址方式不是偏移量類(lèi)型?
“,” 操作數(shù)為內(nèi)存變量,但尋址方式為自動(dòng)增量?
“p”操作數(shù)是一個(gè)合法的內(nèi)存地址(指針)?


寄存器或內(nèi)存?

“g” 將輸入變量放入eax,ebx,ecx ,edx中的一個(gè)或者作為內(nèi)存變量?
“X”操作數(shù)可以是任何類(lèi)型?


立即數(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”,“1 ,”... “9 ”?

表示用它限制的操作數(shù)與某個(gè)指定的操作數(shù)匹配,也即該操作數(shù)就是指定的那個(gè)操作數(shù),?
例如用“0 ”去描述“%1”操作數(shù),那么“%1”引用的其實(shí)就是“%0”操作數(shù),注意作為?
限定符字母的0-9 ,與指令中的“%0”-“%9”的區(qū)別,前者描述操作數(shù),后者代表操作數(shù)。?


后面有詳細(xì)描述 & 該輸出操作數(shù)不能使用過(guò)和輸入操作數(shù)相同的寄存器?


后面有詳細(xì)描述?


操作數(shù)類(lèi)型?
“=” 操作數(shù)在指令中是只寫(xiě)的(輸出操作數(shù))?
“+” 操作數(shù)在指令中是讀寫(xiě)類(lèi)型的(輸入輸出操作數(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)之間所有字母被忽略?

* 表示如果選用寄存器,則其后的字母被忽略?


現(xiàn)在繼續(xù)看上面的例子,?
"=m" (ADDR)表示ADDR為內(nèi)存變量(“m”),而且是輸出變量(“=”);"Ir" (nr)表示nr,為?
0-31之間的立即數(shù)(“I”)或者一個(gè)寄存器操作數(shù)(“r”)。?



2.3.4.2?
匹配限制符?

I386?
指令集中許多指令的操作數(shù)是讀寫(xiě)型的(讀寫(xiě)型操作數(shù)指先讀取原來(lái)的值然后參加運(yùn)算,最后?
將結(jié)果寫(xiě)回操作數(shù)),例如addl %1,%0,它的作用是將操作數(shù)%0與操作數(shù)%1的和存入操作數(shù)%0,?
因此操作數(shù)%0是讀寫(xiě)型操作數(shù)。老版本的GCC對(duì)這種類(lèi)型操作數(shù)的支持不是很好,它將操作數(shù)嚴(yán)格?
分為輸入和輸出兩種,分別放在輸入部分和輸出部分,而沒(méi)有一個(gè)單獨(dú)部分描述讀寫(xiě)型操作數(shù),?
因此在GCC中讀寫(xiě)型的操作數(shù)需要在輸入和輸出部分分別描述,靠匹配限制符將兩者關(guān)聯(lián)到一起?
注意僅在輸入和輸出部分使用相同的C變量,但是不用匹配限制符,產(chǎn)生的代碼很可能不對(duì),后?
面會(huì)分析原因。?




匹配限制符是一位數(shù)字:“0”、“1”……“9,”,分別表示它限制的C表達(dá)式分別與?
占位符%0,%1,……%9對(duì)應(yīng)的C變量匹配。例如使用“0”作為%1,的限制字符,那么?
%0和%1表示同一個(gè)C,變量。?


看一下下面的代碼就知道為什么要將讀寫(xiě)型操作數(shù),分別在輸入和輸出部分加以描述。?


該例功能是求input+result的和,然后存入result:?


extern int input,result;?

void test_at_t()?
{?
result= 0;?
input = 1;?
__asm__?
__volatile__ ("addl %1,%0":"=r"(result): "r"(input));?

}?

對(duì)應(yīng)的匯編代碼為:?

movl $0,_result?
movl $1,_input?
movl _input,%edx /APP?
addl %edx,%eax /NO_APP?
movl %eax,%edx?
movl %edx,_result?

input 為輸入型變量,而且需要放在寄存器中,GCC給它分配的寄存器是%edx,在執(zhí)行addl之前%edx,?
的內(nèi)容已經(jīng)是input的值。可見(jiàn)對(duì)于使用“r”限制的輸入型變量或者表達(dá)式,在使用之前GCC會(huì)插入?
必要的代碼將他們的值讀到寄存器;“m”型變量則不需要這一步。讀入input后執(zhí)行addl,顯然%eax?
的值不對(duì),需要先讀入result的值才行。再往后看:movl %eax,%edx和movl %edx,_result?
的作用是將結(jié)果存回result,分配給result的寄存器與分配給input的一樣,都是%edx。?

綜上可以總結(jié)出如下幾點(diǎn):?

1. 使用“r”限制的輸入變量,GCC先分配一個(gè)寄存器,然后將值讀入寄存器,最后?
用該寄存器替換占位符;?


2. 使用“r”限制的輸出變量,GCC會(huì)分配一個(gè)寄存器,然后用該寄存器替換占位符,?
但是在使用該寄存器之前并不將變量值先讀入寄存器,GCC認(rèn)為所有輸出變量以前的?
值都沒(méi)有用處,不讀入寄存器(可能是因?yàn)锳T&T匯編源于CISC架構(gòu)處理器的匯編語(yǔ)言?
,在CISC處理器中大部分指令的輸入輸出明顯分開(kāi),而不像RISC那樣一個(gè)操作數(shù)既?
做輸入又做輸出,例如add r0,r1,r2,r0,和r1是輸入,r2是輸出,輸入和輸出分開(kāi),?
沒(méi)有使用輸入輸出型操作數(shù),這樣我們就可以認(rèn)為r2對(duì)應(yīng)的操作數(shù)原來(lái)的值沒(méi)有用處,?
也就沒(méi)有必要先將操作數(shù)的值讀入r2,因?yàn)檫@是浪費(fèi)處理器的CPU周期),最后GCC插入代碼,?
將寄存器的值寫(xiě)回變量;?


3. 輸入變量使用的寄存器在最后一處使用它的指令之后,就可以挪做其他用處,因?yàn)?
已經(jīng)不再使用。例如上例中的%edx。在執(zhí)行完addl之后就作為與result對(duì)應(yīng)的寄存器。?


因?yàn)榈诙l,上面的內(nèi)嵌匯編指令不能奏效,因此需要在執(zhí)行addl之前把result的值讀入?
寄存器,也許再將result放入輸入部分就可以了(因?yàn)榈谝粭l會(huì)保證將result?
先讀入寄存器)。修改后的指令如下(為了更容易說(shuō)明問(wèn)題將input限制符由“r,”改為“m”):?


extern int input,result;?

void test_at_t()?
{?

result = 0;?
input = 1;?
__asm__?
__volatile__ ("addl %2,%0":"=r"(result):"r"(result),"m"(input));?

}?


看上去上面的代碼可以正常工作,因?yàn)槲覀冎?0和%1都和result相關(guān),應(yīng)該使用同一個(gè)?
寄存器,但是GCC并不去判斷%0和%1,是否和同一個(gè)C表達(dá)式或變量相關(guān)聯(lián)(這樣易于產(chǎn)生與?
內(nèi)嵌匯編相應(yīng)的匯編代碼),因此%0和%1使用的寄存器可能不同。我們看一下匯編代碼就知道了。?

movl $0,_result?
movl $1,_input?
movl _result,%edx /APP?
addl _input,%eax /NO_APP?
movl %eax,%edx?
movl %edx,_result?

現(xiàn)在在執(zhí)行addl之前將result的值被讀入了寄存器%edx,但是addl指令的操作數(shù)%0?
卻成了%eax,而不是%edx,與預(yù)料的不同,這是因?yàn)镚CC給輸出和輸入部分的變量分配了不同?
的寄存器,GCC沒(méi)有去判斷兩者是否都與result相關(guān),后面會(huì)講GCC如何翻譯內(nèi)嵌匯編,看完之后?
就不會(huì)驚奇啦。?


使用匹配限制符后,GCC知道應(yīng)將對(duì)應(yīng)的操作數(shù)放在同一個(gè)位置(同一個(gè)寄存器或者同一個(gè)?
內(nèi)存變量)。使用匹配限制字符的代碼如下:?


extern int input,result;?

void test_at_t()?
{?
result = 0;?
input = 1;?
__asm__?
__volatile__ ("addl %2,%0":"=r"(result):"0"(result),"m"(input));?

}?

輸入部分中的result用匹配限制符“0”限制,表示%1與%0,代表同一個(gè)變量,?
輸入部分說(shuō)明該變量的輸入功能,輸出部分說(shuō)明該變量的輸出功能,兩者結(jié)合表示result?
是讀寫(xiě)型。因?yàn)?0和%1,表示同一個(gè)C變量,所以放在相同的位置,無(wú)論是寄存器還是內(nèi)存。?

相應(yīng)的匯編代碼為:?


movl $0,_result?
movl $1,_input?
movl _result,%edx?
movl %edx,%eax /APP?
addl _input,%eax /NO_APP?
movl %eax,%edx?
movl %edx,_result?


可以看到與result相關(guān)的寄存器是%edx,在執(zhí)行指令addl之前先從%edx將result讀入%eax,?
執(zhí)行之后需要將結(jié)果從%eax讀入%edx,最后存入result中。這里我們可以看出GCC?
處理內(nèi)嵌匯編中輸出操作數(shù)的一點(diǎn)點(diǎn)信息:addl并沒(méi)有使用%edx,可見(jiàn)它不是簡(jiǎn)單的用result?
對(duì)應(yīng)的寄存器%edx去替換%0,而是先分配一個(gè)寄存器,執(zhí)行運(yùn)算,最后才將運(yùn)算結(jié)果存入?
對(duì)應(yīng)的變量,因此GCC是先看該占位符對(duì)應(yīng)的變量的限制符,發(fā)現(xiàn)是一個(gè)輸出型寄存器變量,?
就為它分配一個(gè)寄存器,此時(shí)沒(méi)有去管對(duì)應(yīng)的C變量,最后GCC,知道還要將寄存器的值寫(xiě)回變量,?
與此同時(shí),它發(fā)現(xiàn)該變量與%edx關(guān)聯(lián),因此先存入%edx,再存入變量。?


至此讀者應(yīng)該明白了匹配限制符的意義和用法。在新版本的GCC中增加了一個(gè)限制字符“+”,?
它表示操作數(shù)是讀寫(xiě)型的,GCC知道應(yīng)將變量值先讀入寄存器,然后計(jì)算,最后寫(xiě)回變量,而?
無(wú)需在輸入部分再去描述該變量。?


例;?
extern int input,result;?

void test_at_t()?
{?

result = 0;?
input = 1;?
__asm__?
__volatile__ ("addl %1,%0":"+r"(result):"m"(input));?

}?


此處用“+”替換了“=”,而且去掉了輸入部分關(guān)于result的描述,產(chǎn)生的匯編代碼如下:?
movl $0,_result?
movl $1,_input?
movl _result,%eax /APP?
addl _input,%eax /NO_APP?
movl %eax,_result?
L2:?
movl %ebp,%esp?

處理的比使用匹配限制符的情況還要好,省去了好幾條匯編代碼。?


2.3.4.3 “&”限制符?

限制符“&”在內(nèi)核中使用的比較多,它表示輸入和輸出操作數(shù)不能使用相同的寄存器,?
這樣可以避免很多錯(cuò)誤。?

舉一個(gè)例子,下面代碼的作用是將函數(shù)foo的返回值存入變量ret中:?


__asm__ ( “call foo;movl %%edx,%1”, :”=a”(ret) : ”r”(bar) );?


我們知道函數(shù)的int型返回值存放在%eax中,但是gcc編譯的結(jié)果是輸入和輸出同時(shí)使用了?
寄存器%eax,如下:?

movl bar, %eax?
#APP?
call foo?
movl %ebx,%eax?

#NO_APP?
movl %eax, ret?

結(jié)果顯然不對(duì),原因是GCC并不知道%eax中的值是我們所要的。避免這種情況的方法是使用“&”?
限定符,這樣bar就不會(huì)再使用%eax寄存器,因?yàn)橐驯籸et指定使用。?

_asm__ ( “call foo;movl %%edx,%1”,:”=&a”(ret) : ”r”(bar) );?


2.3.5 破壞描述部分?

2.3.5.1 寄存器破壞描述符?


通常編寫(xiě)程序只使用一種語(yǔ)言:高級(jí)語(yǔ)言或者匯編語(yǔ)言。高級(jí)語(yǔ)言編譯的步驟大致如下:?
l?
預(yù)處理;?
l?
編譯?
l?
匯編?
l?
鏈接?


我們這里只關(guān)心第二步編譯(將C代碼轉(zhuǎn)換成匯編代碼):因?yàn)樗械拇a都是用高級(jí)語(yǔ)言編寫(xiě),?
編譯器可以識(shí)別各種語(yǔ)句的作用,在轉(zhuǎn)換的過(guò)程中所有的寄存器都由編譯器決定如何分配使用,?
它有能力保證寄存器的使用不會(huì)沖突;也可以利用寄存器作為變量的緩沖區(qū),因?yàn)榧拇嫫鞯脑L問(wèn)?
速度比內(nèi)存快很多倍。如果全部使用匯編語(yǔ)言則由程序員去控制寄存器的使用,只能靠程序員去?
保證寄存器使用的正確性。但是如果兩種語(yǔ)言混用情況就變復(fù)雜了,因?yàn)閮?nèi)嵌的匯編代碼可以直接?
使用寄存器,而編譯器在轉(zhuǎn)換的時(shí)候并不去檢查內(nèi)嵌的匯編代碼使用了哪些寄存器(因?yàn)楹茈y檢測(cè)?
匯編指令使用了哪些寄存器,例如有些指令隱式修改寄存器,有時(shí)內(nèi)嵌的匯編代碼會(huì)調(diào)用其他子過(guò)程,?
而子過(guò)程也會(huì)修改寄存器),因此需要一種機(jī)制通知編譯器我們使用了哪些寄存器(程序員自己知道?
內(nèi)嵌匯編代碼中使用了哪些寄存器),否則對(duì)這些寄存器的使用就有可能導(dǎo)致錯(cuò)誤,修改描述部分?
可以起到這種作用。當(dāng)然內(nèi)嵌匯編的輸入輸出部分指明的寄存器或者指定為“r”,“g”型由編譯器?
去分配的寄存器就不需要在破壞描述部分去描述,因?yàn)榫幾g器已經(jīng)知道了。?


破壞描述符由逗號(hào)格開(kāi)的字符串組成,每個(gè)字符串描述一種情況,一般是寄存器名;除寄存器外?
還有“memory”。例如:“%eax”,“%ebx”,“memory”等。?


下面看個(gè)例子就很清楚為什么需要通知GCC內(nèi)嵌匯編代碼中隱式(稱它為隱式是因?yàn)镚CC并不知道)?
使用的寄存器。?

在內(nèi)嵌的匯編指令中可能會(huì)直接引用某些寄存器,我們已經(jīng)知道AT&T格式的匯編語(yǔ)言中,寄存器?
名以“%”作為前綴,為了在生成的匯編程序中保留這個(gè)“%”號(hào),在asm語(yǔ)句中對(duì)寄存器的?
引用必須用“%%”作為寄存器名稱的前綴。原因是“%”在asm,內(nèi)嵌匯編語(yǔ)句中的作用與“\”在C?
語(yǔ)言中的作用相同,因此“%%”轉(zhuǎn)換后代表“%”。?

例(沒(méi)有使用修改描述符):?

int main(void)?
{?
int input, output,temp;?
input = 1;?

__asm__ __volatile__ ("movl $0, %%eax;\n\t?
movl %%eax, %1;\n\t?
movl %2, %%eax;\n\t?
movl %%eax, %0;\n\t"?
:"=m"(output),"=m"(temp) /* output */?
:"r"(input) /* input */?
);?
return 0;?
}?


這段代碼使用%eax作為臨時(shí)寄存器,功能相當(dāng)于C代碼:“temp = 0;output=input”,?
對(duì)應(yīng)的匯編代碼如下:?

movl $1,-4(%ebp)?
movl -4(%ebp),%eax /APP?
movl $0, %eax;?
movl %eax, -12(%ebp);?
movl %eax, %eax;?
movl %eax, -8(%ebp); /NO_APP?

顯然GCC給input分配的寄存器也是%eax,發(fā)生了沖突,output的值始終為0,而不是input。?

使用破壞描述后的代碼:?


int main(void)?
{?
int input, output,temp;?

input = 1;?

__asm__ __volatile__?
( "movl $0, %%eax;\n\t?
movl %%eax, %1;\n\t?
movl %2, %%eax;\n\t?
movl %%eax, %0;\n\t"?
:"=m"(output),"=m"(temp) /* output */?
:"r"(input) /* input */?
:"eax"); /* 描述符 */?

return 0;?
}?

對(duì)應(yīng)的匯編代碼:?


movl $1,-4(%ebp)?
movl -4(%ebp),%edx /APP?
movl $0, %eax;?
movl %eax, -12(%ebp);?
movl %edx, %eax;?
movl %eax, -8(%ebp); /NO_APP?


通過(guò)破壞描述部分,GCC得知%eax已被使用,因此給input分配了%edx。在使用內(nèi)嵌匯編時(shí)請(qǐng)記?
住一點(diǎn):盡量告訴GCC盡可能多的信息,以防出錯(cuò)。?


如果你使用的指令會(huì)改變CPU的條件寄存器cc,需要在修改描述部分增加“cc”。?

2.3.5.2 memory破壞描述符?

“memory”比較特殊,可能是內(nèi)嵌匯編中最難懂部分。為解釋清楚它,先介紹一下編譯器的?
優(yōu)化知識(shí),再看C關(guān)鍵字volatile。最后去看該描述符。?

2.3.5.2.1 編譯器優(yōu)化介紹?

內(nèi)存訪問(wèn)速度遠(yuǎn)不及CPU處理速度,為提高機(jī)器整體性能,在硬件上引入硬件高速緩存Cache,?
加速對(duì)內(nèi)存的訪問(wèn)。另外在現(xiàn)代CPU中指令的執(zhí)行并不一定嚴(yán)格按照順序執(zhí)行,沒(méi)有相關(guān)性?
的指令可以亂序執(zhí)行,以充分利用CPU的指令流水線,提高執(zhí)行速度。以上是硬件級(jí)別的優(yōu)化。?
再看軟件一級(jí)的優(yōu)化:一種是在編寫(xiě)代碼時(shí)由程序員優(yōu)化,另一種是由編譯器進(jìn)行優(yōu)化。編譯器?
優(yōu)化常用的方法有:將內(nèi)存變量緩存到寄存器;調(diào)整指令順序充分利用CPU指令流水線,常見(jiàn)的?
是重新排序讀寫(xiě)指令。?


對(duì)常規(guī)內(nèi)存進(jìn)行優(yōu)化的時(shí)候,這些優(yōu)化是透明的,而且效率很好。由編譯器優(yōu)化或者硬件重新排序引起的問(wèn)題的解決辦法是在從硬件(或者其他處理器)的角度看必須以特定順序執(zhí)行的操作之間設(shè)置內(nèi)存屏障(memory barrier),linux提供了一個(gè)宏解決編譯器的執(zhí)行順序問(wèn)題。?

void Barrier(void)?

這個(gè)函數(shù)通知編譯器插入一個(gè)內(nèi)存屏障,但對(duì)硬件無(wú)效,編譯后的代碼會(huì)把當(dāng)前CPU?
寄存器中的所有修改過(guò)的數(shù)值存入內(nèi)存,需要這些數(shù)據(jù)的時(shí)候再重新從內(nèi)存中讀出。?

2.3.5.2.2 C 語(yǔ)言關(guān)鍵字volatile?

C 語(yǔ)言關(guān)鍵字volatile(注意它是用來(lái)修飾變量而不是上面介紹的__volatile__)表明某個(gè)變量?
的值可能在外部被改變,因此對(duì)這些變量的存取不能緩存到寄存器,每次使用時(shí)需要重新存取。?
該關(guān)鍵字在多線程環(huán)境下經(jīng)常使用,因?yàn)樵诰帉?xiě)多線程的程序時(shí),同一個(gè)變量可能被多個(gè)線程修?
改,而程序通過(guò)該變量同步各個(gè)線程,例如:?


DWORD __stdcall threadFunc(LPVOID signal)?
{?

int* intSignal=reinterpret_cast(signal);?

*intSignal=2;?

while(*intSignal!=1)?
sleep(1000);?

return 0;?

}?


該線程啟動(dòng)時(shí)將intSignal置為2,然后循環(huán)等待直到intSignal為1,時(shí)退出。顯然intSignal?
的值必須在外部被改變,否則該線程不會(huì)退出。但是實(shí)際運(yùn)行的時(shí)候該線程卻不會(huì)退出,即使?
在外部將它的值改為1,看一下對(duì)應(yīng)的偽匯編代碼就明白了:?


mov ax,signal?
label:?
if(ax!=1)?
goto label?


對(duì)于C編譯器來(lái)說(shuō),它并不知道這個(gè)值會(huì)被其他線程修改。自然就把它c(diǎn)ache在寄存器里面。記住,C?
編譯器是沒(méi)有線程概念的!這時(shí)候就需要用到volatile。volatile的本意是指:這個(gè)值可能會(huì)在?
當(dāng)前線程外部被改變。也就是說(shuō),我們要在threadFunc中的intSignal前面加上volatile?
關(guān)鍵字,這時(shí)候,編譯器知道該變量的值會(huì)在外部改變,因此每次訪問(wèn)該變量時(shí)會(huì)重新讀取,所作?
的循環(huán)變?yōu)槿缦旅鎮(zhèn)未a所示:?

label:?
mov ax,signal?
if(ax!=1)?
goto label?


2.3.5.2.3 Memory?


有了上面的知識(shí)就不難理解Memory?
修改描述符了,Memory描述符告知GCC:?
(1)不要將該段內(nèi)嵌匯編指令與前面的指令重新排序;也就是在執(zhí)行內(nèi)嵌匯編代碼之前,?
它前面的指令都執(zhí)行完畢。?


(2)不要將變量緩存到寄存器,因?yàn)檫@段代碼可能會(huì)用到內(nèi)存變量,而這些內(nèi)存變量會(huì)?
以不可預(yù)知的方式發(fā)生改變,因此GCC插入必要的代碼先將緩存到寄存器的變量值寫(xiě)回內(nèi)存,?
如果后面又訪問(wèn)這些變量,需要重新訪問(wèn)內(nèi)存。?


如果匯編指令修改了內(nèi)存,但是GCC本身卻察覺(jué)不到,因?yàn)樵谳敵霾糠譀](méi)有描述,?
此時(shí)就需要在修改描述部分增加“memory”,告訴GCC內(nèi)存已經(jīng)被修改,GCC得知這個(gè)信息后,?
就會(huì)在這段指令之前,插入必要的指令將前面因?yàn)閮?yōu)化Cache到寄存器中的變量值先寫(xiě)回內(nèi)存,?
如果以后又要使用這些變量再重新讀取。?


例:?
………..?
Char test[100];?
char a;?
char c;?

c = 0;?
test[0] = 1;?
……..?
a = test [0];?
……?
__asm__(?
"cld\n\t"?
"rep\n\t"?
"stosb"?
: /* no output */?

: "a" (c),"D" (test),"c" (100)?
:?
"cx","di","memory");?
……….?
// 我們知道test[0] 已經(jīng)修改,所以重新讀取?
a=test[0];?

……?

這段代碼中的匯編指令功能與?
memset?
相當(dāng),也就是相當(dāng)于調(diào)用了memset(test,0,100);它使用stosb修改了test?
數(shù)組的內(nèi)容,但是沒(méi)有在輸入或輸出部分去描述操作數(shù),因?yàn)檫@兩條指令都不需要?
顯式的指定操作數(shù),因此需要增加“memory”通知GCC。現(xiàn)在假設(shè):GCC在優(yōu)化時(shí)將test[0]?
放到了%eax寄存器,那么test[0] = 1對(duì)應(yīng)于%eax=1,a = test [0]被換為a=%eax?
,如果在那段匯編指令中不使用“memory”,Gcc,不知道現(xiàn)在test[0]?
的值已經(jīng)被改變了(如果整段代碼都是我們自己使用匯編編寫(xiě),我們自己當(dāng)然知道?
這些內(nèi)存的修改情況,我們也可以人為的去優(yōu)化,但是現(xiàn)在除了我們編寫(xiě)的那一小段外,?
其他匯編代碼都是GCC?
生成的,它并沒(méi)有那么智能,知道這段代碼會(huì)修改test[0]),結(jié)果其后的a=test[0]?
,轉(zhuǎn)換為匯編后卻是a=%eax,因?yàn)镚CC不知道顯式的改變了test數(shù)組,結(jié)果出錯(cuò)了。?
如果增加了“memory”修飾符,GCC知道:?
“這段代碼修改了內(nèi)存,但是也僅此而已,它并不知道到底修改了哪些變量”,?
因此他將以前因優(yōu)化而緩存到寄存器的變量值全部寫(xiě)回內(nèi)存,從內(nèi)嵌匯編開(kāi)始,如果后面?
的代碼又要存取這些變量,則重新存取內(nèi)存(不會(huì)將讀寫(xiě)操作映射到以前緩存的那個(gè)寄存器)。?
這樣上面那段代碼最后一句就不再是%eax=1,而是test[0] = 1。?

這兩條對(duì)實(shí)現(xiàn)臨界區(qū)至關(guān)重要,第一條保證不會(huì)因?yàn)橹噶畹闹匦屡判驅(qū)⑴R界區(qū)內(nèi)的代碼調(diào)?
到臨界區(qū)之外(如果臨界區(qū)內(nèi)的指令被重排序放到臨界區(qū)之外,What will happen?),?
第二條保證在臨界區(qū)訪問(wèn)的變量的值,肯定是最新的值,而不是緩存在?
寄存器中的值,否則就會(huì)導(dǎo)致奇怪的錯(cuò)誤。例如下面的代碼:?


int del_timer(struct timer_list * timer)?
{?
int?
ret = 0;?
if?
(timer->next) {?
unsigned?
long flags;?
struct?
timer_list * next;?
save_flags(flags);?
cli();?

// 臨界區(qū)開(kāi)始?
if?
((next = timer->next) != NULL) {?
(next->prev = timer->prev)->next = next;?
timer->next = timer->prev = NULL;?
ret = 1;?
} // 臨界區(qū)結(jié)束?

restore_flags(flags);?
}?
return?
ret;?
}?

它先判斷timer->next?
的值,如果是空直接返回,無(wú)需進(jìn)行下面的操作。如果不是空,則進(jìn)入臨界區(qū)進(jìn)行操作,但是cli()?
的實(shí)現(xiàn)(見(jiàn)下面)沒(méi)有使用“memory”,timer->next的值可能會(huì)被緩存到寄存器中,?
后面if ((next =timer->next) != NULL)會(huì)從寄存器中讀取timer->next的值,如果?
在if (timer->next)之后,進(jìn)入臨界區(qū)之前,timer->next的值可能被在外部改變,?
這時(shí)肯定會(huì)出現(xiàn)異常情況,而且這種情況很難Debug。但是如果cli使用“memory”,?
那么if ((next = timer->next) !=NULL)語(yǔ)句會(huì)重新從內(nèi)存讀取timer->next的值,而不會(huì)從寄存器?
中取,這樣就不會(huì)出現(xiàn)問(wèn)題啦。?

2.4 版內(nèi)核中cli和sti的代碼如下:?
#define __cli()?
__asm__?
__volatile__("cli": : :"memory")?
#define __sti()?
__asm__?
__volatile__("sti": : :"memory")?

通過(guò)上面的例子,讀者應(yīng)該知道,為什么指令沒(méi)有修改內(nèi)存,但是卻使用“memory?
”修改描述符的原因了吧。應(yīng)從指令的上下文去理解為什么要這樣做。?

使用“volatile”也可以達(dá)到這個(gè)目的,但是我們?cè)诿總€(gè)變量前增加該關(guān)鍵字,?
不如使用“memory”方便。?

2.4 GCC如何編譯內(nèi)嵌匯編代碼?

GCC 編譯內(nèi)嵌匯編代碼的步驟如下:?

1.輸入變量與占位符?

根據(jù)限定符和破壞描述部分,為輸入和輸出部分的變量分配合適的寄存器,如果限定符指定為立即數(shù)?
(“i”),或內(nèi)存變量(“m”),則不需要該步驟,如果限定符沒(méi)有具體指定輸入操作數(shù)的?
類(lèi)型(如“g”),GCC會(huì)視需要決定是否將該操作數(shù)輸入到某個(gè)寄存器。這樣每個(gè)占位符都與某個(gè)?
寄存器、內(nèi)存變量或立即數(shù)形成了一一對(duì)應(yīng)的關(guān)系。對(duì)分配了寄存器的輸入變量需要增加代碼?
將它的值讀入寄存器。另外還要根據(jù)破壞描述符的部分增加額外代碼。?


2.指令模板部分?
然后根據(jù)這種一一對(duì)應(yīng)的關(guān)系,用這些寄存器、內(nèi)存變量或立即數(shù)來(lái)取代匯編代碼中的占位符。?

3.變量輸出?

按照輸出限定符的指定將寄存器的內(nèi)容輸出到某個(gè)內(nèi)存變量中,如果輸出操作數(shù)的限定符指定為內(nèi)存變量(“m”),則該步驟被省略。


實(shí)例:比如需要在C程序中打印LR(r14)的值,那直接執(zhí)行如下:

long ret_reg;
asm volatile("mov ?%0, r14" : "=r" (ret_reg));
printk("enten into %s, the ret_reg is 0x%.8x\n", __func__, ret_reg);

另外可以看《LINUX內(nèi)核源代碼情景分析》

總結(jié)

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

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

亚洲每日更新 | 免费成人av | 在线视频 你懂得 | 国产精品毛片一区二区 | av资源免费观看 | 在线观看中文字幕亚洲 | 久久精彩免费视频 | 在线观看国产 | 亚洲国产免费 | 99精品视频免费看 | 成人小视频在线播放 | 麻豆传媒视频在线免费观看 | 国产精品视频免费 | 精品国模一区二区三区 | 麻豆视频在线看 | 午夜在线看 | 曰韩在线| 欧美一级片免费观看 | 性色av香蕉一区二区 | 久久国产影院 | 日韩午夜精品 | 日日夜夜操av | 亚洲女同ⅹxx女同tv | 欧美日韩在线观看一区 | 亚洲高清精品在线 | 日韩超碰 | 一区二区三区精品久久久 | 色亚洲网 | 国产成人99久久亚洲综合精品 | 国产看片免费 | 97免费中文视频在线观看 | 欧美精品一区二区在线播放 | 日韩欧美视频在线播放 | av一区二区在线观看中文字幕 | 久久久久激情 | 国产精品黄色av | 91污视频在线观看 | 国产亚洲成人网 | 在线国产视频一区 | 丁香色婷| 亚洲免费精彩视频 | 在线国产黄色 | 在线免费观看亚洲视频 | 97热久久免费频精品99 | 永久免费精品视频网站 | 欧美亚洲一级片 | 精品久久久久久久久久久久久 | 国产一级大片免费看 | 欧美日韩中文国产 | 人人艹人人 | 黄色中文字幕 | 日韩在线视频精品 | 久久久九九| 久久久久久久久久久久久国产精品 | 日本性高潮视频 | 97色噜噜| 大胆欧美gogo免费视频一二区 | 丝袜美女视频网站 | 在线之家免费在线观看电影 | 狠狠色丁香婷婷综合久久片 | 97视频在线观看网址 | 91资源在线播放 | 毛片网站在线观看 | 91香蕉视频污在线 | 久久超碰免费 | 在线免费成人 | 91色吧| 国产视频18| 久久久久美女 | 丁香六月中文字幕 | 人人爽人人爽人人片 | 国产精品1区2区3区在线观看 | 国产成人精品综合久久久久99 | 亚洲乱码精品久久久久 | 久久久人| 香蕉视频网站在线观看 | 免费情缘 | 久草在线免费资源站 | 国产精品女人久久久久久 | 国产剧情久久 | 成人啪啪18免费游戏链接 | 久草视频首页 | 99 国产精品| 精品成人a区在线观看 | 国产资源在线视频 | 欧美成人xxxxx| 成年人国产在线观看 | 亚洲成aⅴ人片久久青草影院 | 久久国产电影 | 久草热久草视频 | 1024久久| 四虎5151久久欧美毛片 | 五月婷婷丁香在线观看 | 国产一区在线观看免费 | www.五月天激情 | 欧美韩日在线 | 看国产黄色片 | av一区二区在线观看中文字幕 | 国产一区二区三区高清播放 | 青草视频在线免费 | 午夜视频欧美 | 国产精品久久久久久久久久尿 | 日韩欧美综合在线视频 | 亚洲日本黄色 | 亚洲精品乱码久久久久久蜜桃不爽 | 热久精品 | 91爱看片 | 亚洲精品国产第一综合99久久 | 玖玖在线资源 | 久久精品一二三区 | 精品美女在线观看 | 国产成人av | 最新国产精品久久精品 | 国产一区二区久久久 | 久久夜色精品国产欧美乱极品 | 亚洲精选在线 | 不卡的av在线 | 中文一区在线 | 国产香蕉久久精品综合网 | 久久久精品视频网站 | 亚洲人成在线观看 | 在线观看一区二区精品 | 亚洲激情在线播放 | 婷婷亚洲五月 | 久久精品国产久精国产 | 精品久久久久久久久久久久久久久久久久 | 日韩欧美在线中文字幕 | 国产又粗又长的视频 | 人人狠狠综合久久亚洲 | 国产91丝袜在线播放动漫 | 国产成人免费高清 | 久久久三级视频 | 国产日韩精品在线观看 | 激情欧美在线观看 | 国产黑丝一区二区三区 | 精品国产三级 | 91麻豆国产福利在线观看 | 精品一区电影国产 | 精品国产一区二区三区av性色 | 精品欧美一区二区精品久久 | 午夜久久久久久久久久久 | 久久艹免费 | 免费在线观看国产精品 | 国产 日韩 欧美 在线 | 日韩美女久久 | 黄色电影小说 | 日本中文字幕在线视频 | 国产精品青青 | 日日碰狠狠躁久久躁综合网 | 精品久久电影 | 综合伊人av| 国内视频在线 | 日韩国产精品一区 | 久久老司机精品视频 | 国产精品久久久久免费观看 | 久久久国产精品人人片99精片欧美一 | 免费黄在线观看 | 欧美日韩视频一区二区三区 | 十八岁免进欧美 | 国产精品影音先锋 | 天天摸日日操 | 国产色视频网站 | 玖玖玖精品 | 免费观看性生交大片3 | 成人在线观看你懂的 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 中文字幕在线字幕中文 | 91精品国产九九九久久久亚洲 | 日韩精品免费在线视频 | 五月香婷 | 国产综合在线视频 | 欧美日韩精品在线观看视频 | 成年性视频 | 久草在线视频在线 | 中文字幕在线国产精品 | 国产福利91精品一区二区三区 | 香蕉视频国产在线 | 91视频91自拍 | 日韩色在线 | 91久久久久久久一区二区 | 久久久国产精品亚洲一区 | 91porny九色91啦中文 | 国内精品久久久久影院男同志 | 奇米网网址 | 国产精品入口66mio女同 | 国产免费久久精品 | 99产精品成人啪免费网站 | 狠狠干在线 | 在线观看岛国 | 国产麻豆视频 | 中文区中文字幕免费看 | 超碰成人免费电影 | 精品久久久久久亚洲综合网 | 中文字幕影片免费在线观看 | 一级电影免费在线观看 | 欧美日韩一区二区三区在线观看视频 | 五月婷婷一级片 | 四虎成人精品永久免费av | 婷婷激情久久 | 国产成人在线网站 | 国产精品久久久久久久妇 | 一区免费在线 | 日韩免费电影网站 | 97视频入口免费观看 | 精品国产一区二区三区四 | 特级西西人体444是什么意思 | 成人在线视频免费观看 | 久久精品视频免费播放 | 成人视屏免费看 | 波多野结依在线观看 | 亚洲精品视频在线观看免费视频 | 亚洲国产精品久久久久婷婷884 | 久久久精品视频成人 | av线上免费看 | 国内精品视频在线 | 久久久久久蜜av免费网站 | 成人毛片一区 | 免费看一级片 | 字幕网资源站中文字幕 | sm免费xx网站 | 日本黄色免费网站 | 成人午夜电影免费在线观看 | 又黄又爽又无遮挡免费的网站 | 国产精品久久久av久久久 | 一区二区三区四区久久 | 日韩高清激情 | 国产亚洲精品xxoo | 99热免费在线 | 国产在线播放一区二区 | 亚洲综合色丁香婷婷六月图片 | 久久国产精品久久国产精品 | 亚洲最大成人网4388xx | 99视频精品在线 | 在线观看的a站 | 在线观看一区二区精品 | ww视频在线观看 | 久草视频手机在线 | 欧美视频日韩 | 中文字幕有码在线观看 | 国产精品一区二区三区在线免费观看 | 人人干人人搞 | 久久高清av | 夜夜躁日日躁狠狠久久88av | 精品国产乱码久久久久久1区二区 | 蜜臀一区二区三区精品免费视频 | 蜜桃传媒一区二区 | 日本在线观看一区二区 | 免费影视大全推荐 | 久草精品电影 | 一区二区理论片 | av大片网址| 国产免费久久精品 | 精品欧美在线视频 | 黄色免费av | 亚洲精品777 | 久久久久久久久毛片精品 | 91麻豆操 | av播放在线 | 久久综合狠狠综合久久狠狠色综合 | 国产精品免费不卡 | 色国产精品一区在线观看 | 婷婷在线观看视频 | 欧美影院久久 | 久久精品视频2 | 黄色av电影在线观看 | 国产网站在线免费观看 | 精品一区二区三区四区在线 | 亚洲成 人精品 | 超碰人人射 | 精品国产1区2区 | 日韩欧美在线第一页 | 欧美精品九九99久久 | 亚洲视频免费视频 | 九九色网 | 中文字幕二区在线观看 | 中文字幕一区二区三区在线观看 | 91网页版在线观看 | av一级二级 | 黄污在线观看 | 久草网站在线观看 | 激情综合色播五月 | 中文字幕在线观看免费高清完整版 | av一级片在线观看 | 久久久99久久 | 日韩视频一区二区在线 | 国产精品久久久久999 | 91av电影在线观看 | 成人h视频| 久久字幕精品一区 | 人人插人人草 | av成人资源 | 日日干天天插 | 四虎在线观看精品视频 | 国产精品久久久久久久7电影 | 九九在线视频 | 欧美少妇xx | 四虎永久精品在线 | 国产小视频在线观看 | av福利免费 | 99久久久国产精品 | 日本在线h | 最新av电影网站 | 久久国产乱 | av资源网在线播放 | 99久高清在线观看视频99精品热在线观看视频 | 国产剧情一区在线 | 亚洲国产美女精品久久久久∴ | 91.麻豆视频| 欧美日韩天堂 | 国产日本亚洲高清 | 久久久久福利视频 | 成人h在线播放 | 亚洲播放一区 | 摸bbb搡bbb搡bbbb | 在线不卡视频 | 国产麻豆视频在线观看 | 97国产视频 | 五月天六月婷 | 色播五月激情五月 | 碰天天操天天 | 最近2019好看的中文字幕免费 | 免费三级a| 国产69久久精品成人看 | 国产又粗又猛又黄 | 六月丁香色婷婷 | 天天摸天天舔天天操 | 欧美日韩激情视频8区 | 免费a v网站 | 欧美作爱视频 | 久草久 | 欧美一区二区免费在线观看 | 国产在线不卡一区 | 人人搞人人爽 | 免费日韩一级片 | 欧美性受极品xxxx喷水 | 国产成人一区二区啪在线观看 | 亚洲视频每日更新 | av黄色一级片| 日韩精品一区二区电影 | 亚洲欧美视频在线 | 久久夜色精品国产欧美一区麻豆 | 亚洲美女免费精品视频在线观看 | 国产亚洲欧洲 | 欧美日韩xxx | 欧美日韩一区二区三区免费视频 | 日韩特黄一级欧美毛片特黄 | 狠狠狠狠狠狠天天爱 | 日韩伦理一区二区三区av在线 | 91日韩免费 | 2021国产在线 | 免费在线激情电影 | 96超碰在线 | 丁香六月中文字幕 | 日韩三级视频在线观看 | 久久热首页 | 午夜国产一区 | 亚洲视频久久 | 国产精品自产拍在线观看网站 | 天天操狠狠操网站 | 精品久久久99| 欧美日韩免费视频 | 婷婷激情欧美 | 免费观看www7722午夜电影 | 黄色一级大片在线免费看国产一 | 久久国产经典视频 | 久青草电影 | 国产亚洲情侣一区二区无 | 在线观看免费版高清版 | 天天干天天操人体 | 国产韩国日本高清视频 | 国产精品免费视频观看 | 在线国产专区 | 九色精品在线 | 99这里都是精品 | 国产一级大片免费看 | 九九精品无码 | 伊人五月婷 | 91视频在线免费 | 狠狠干婷婷色 | 日日夜夜免费精品 | 久久综合免费视频 | 在线网址你懂得 | 国产一在线精品一区在线观看 | 丁香高清视频在线看看 | 91在线国内视频 | 欧美日韩免费在线视频 | 国产精品亚洲a | 亚洲精品视频在线看 | 人人爽人人做 | www.av免费| 友田真希av| 国产午夜剧场 | 日日麻批40分钟视频免费观看 | 国产福利网站 | 久久精品这里精品 | 久久久久久国产精品亚洲78 | 婷婷5月激情5月 | 成人黄色大片 | 四虎海外影库www4hu | 久久人人爽 | 日韩免费福利 | 亚洲国产成人久久 | 九月婷婷色 | 久久特级毛片 | 日韩成人精品一区二区 | 日韩狠狠操 | 久久久久97国产 | 国产成人亚洲在线电影 | 国产专区欧美专区 | 日韩在线不卡视频 | 久久99国产精品久久 | 九九综合九九 | 久久资源总站 | 在线免费观看的av网站 | 天天操天天射天天爽 | 成人黄色在线 | 日本韩国中文字幕 | 91av视频网站| 久久久久五月天 | 欧美三人交 | 色婷婷97| 五月婷婷香蕉 | 国产成人在线免费观看 | 91视频 - v11av| 在线影院av | 91av短视频 | 在线观看视频免费大全 | 少妇搡bbbb搡bbb搡忠贞 | 就色干综合 | 中文字幕在线高清 | 久久综合久色欧美综合狠狠 | 天天操夜夜操国产精品 | 麻豆免费精品视频 | 激情五月开心 | 亚洲高清不卡av | 久久国产a| 波多野结衣一区二区 | 91福利国产在线观看 | 国产美女视频网站 | 人人搞人人爽 | 夜夜干天天操 | 久久婷五月 | 成人观看视频 | 一区二区三区精品久久久 | 久久久久亚洲精品中文字幕 | 亚洲 欧美 国产 va在线影院 | 99色在线观看视频 | 高潮毛片无遮挡高清免费 | 97超碰免费在线 | 久久在线视频精品 | 草久久久久| 五月天色综合 | 91精品视频在线 | 九九免费在线观看 | 国产在线超碰 | 久草在线中文视频 | av网站免费线看精品 | 日韩高清不卡一区二区三区 | 黄色精品一区二区 | 18久久久| 在线中文字幕一区二区 | 96看片| 亚洲无线视频 | 99在线视频播放 | 三级黄色网址 | 麻豆传媒一区二区 | 五月婷香蕉久色在线看 | 日韩亚洲在线视频 | 亚洲激情av | 亚洲狠狠操| 国产日韩欧美在线播放 | 天天干天天色2020 | 日韩视频免费在线观看 | 日韩在线第一区 | 国产亚洲欧美日韩高清 | 久草在线久 | 天天干天天干天天射 | 高清av在线 | 久久不卡电影 | 中文字幕在线观看av | 欧美大jb| 国产在线精品一区二区不卡了 | 欧美日韩国产一区二区在线观看 | 成人福利av | www蜜桃视频 | 国产视频亚洲视频 | 六月色丁香 | 免费激情网 | 亚洲精品男人天堂 | 国产精品igao视频网网址 | 中文字幕在线久一本久 | 九九视频免费 | 国产一区二区在线免费观看 | 久久综合九色综合久久久精品综合 | 亚洲国产一二三 | 4hu视频 | 亚洲色图激情文学 | 最新三级在线 | 91中文字幕一区 | 欧美午夜久久 | 亚洲伦理一区二区 | 久久精品8| 黄色在线观看污 | 久久久精品一区二区三区 | 欧美孕妇与黑人孕交 | 欧美analxxxx| 在线你懂的视频 | 国产粉嫩在线 | 狂野欧美激情性xxxx欧美 | 91在线免费播放 | 亚州国产精品视频 | 欧亚久久| 黄色大片日本 | 亚洲精品tv久久久久久久久久 | 久久1电影院 | 日韩精品在线免费观看 | 91九色老 | 有码一区二区三区 | 亚洲精品视频网站在线观看 | 9992tv成人免费看片 | 久久97精品 | 久久999精品 | 国产成人777777 | 黄色小说18 | 免费精品| 国产美女免费看 | 国产成人久久精品亚洲 | 成人久久久精品国产乱码一区二区 | 夜夜操天天干, | 一级免费黄色 | 中文字幕人成人 | 国产精品久久久久9999吃药 | 中文字幕视频免费观看 | 久久亚洲综合色 | 亚洲va男人天堂 | 久久久久久久久电影 | 久久国产精品免费一区二区三区 | 免费精品在线观看 | 国产精品午夜在线 | 国产 日韩 在线 亚洲 字幕 中文 | 日韩视频在线一区 | 欧美成人黄色 | 日韩小视频网站 | 亚洲电影自拍 | 久草成人在线 | 久久综合九色综合欧美就去吻 | 91av在线免费播放 | 国产精品一区免费观看 | 欧美日韩在线视频一区 | av蜜桃在线 | 国产成人a亚洲精品 | 日韩久久网站 | 日韩中文幕 | 韩国av永久免费 | 国产h在线观看 | 2024国产在线| 欧美一区二视频在线免费观看 | 天天舔夜夜操 | 激情视频免费观看 | 91九色在线观看视频 | 中文字幕在线免费看 | 久久久精品二区 | 天天天色综合a | 日韩在线视频免费播放 | 久久黄色影院 | 久久久久久久免费看 | 国产精品精品国产婷婷这里av | 视频在线观看亚洲 | 天天色天天艹 | 人人爽久久涩噜噜噜网站 | 91视频高清完整版 | 天天天天综合 | 国产精品99久久久久人中文网介绍 | 激情婷婷综合 | 亚洲视频www | 麻豆视频在线免费看 | 日韩在线无 | 天天av资源 | 狠狠色噜噜狠狠狠狠2022 | 亚洲国产精品va在线看黑人动漫 | 精品国产一区二区三区不卡 | 麻豆精品在线视频 | 久久视频在线观看中文字幕 | 亚洲欧美国产视频 | 免费成人结看片 | 国产精品毛片一区视频 | 色久天| 国产高清成人av | 免费观看av | 亚洲欧美精品一区 | 美女一二三区 | av成人免费在线 | 国产精品片 | 国产在线毛片 | 国产成人精品免费在线观看 | 看国产黄色片 | 九九综合在线 | 久久视频国产精品免费视频在线 | 99久热精品 | 美女网站黄免费 | 中文在线字幕免费观看 | 久热香蕉视频 | 在线观看黄网站 | 六月色婷婷 | 欧美日韩首页 | 97免费在线观看视频 | 国产精品毛片久久久久久久 | 天天插天天狠天天透 | 亚洲精品国产欧美在线观看 | 久久99视频精品 | 四虎影视成人永久免费观看亚洲欧美 | 日韩中文字幕亚洲一区二区va在线 | 亚洲精品1区2区3区 超碰成人网 | 91视频免费网站 | 日本护士三级少妇三级999 | 在线观看mv的中文字幕网站 | 欧美一区视频 | 午夜在线免费视频 | 亚洲高清资源 | 99热99re6国产在线播放 | 天天天天天天干 | 国内三级在线观看 | 99视频在线精品免费观看2 | 国产精品一区二区三区在线播放 | 日本精品一区二区三区在线播放视频 | 日韩在线观看一区二区三区 | 精品一区二区三区电影 | 亚洲国产精品电影 | 国产精品porn | 99精品久久精品一区二区 | 在线黄色国产 | 日韩二区三区在线观看 | 欧美一级片在线观看视频 | 国产男女无遮挡猛进猛出在线观看 | 成人中文字幕+乱码+中文字幕 | 韩国一区二区在线观看 | 亚洲精品国产综合99久久夜夜嗨 | 2019中文在线观看 | 99热手机在线 | 人人澡人人添人人爽一区二区 | 亚洲亚洲精品在线观看 | 九九涩涩av台湾日本热热 | 天天爽夜夜爽人人爽一区二区 | 午夜色站 | 91免费观看| 精品美女在线视频 | 香蕉91视频| 久久五月精品 | 日韩精品亚洲专区在线观看 | 91 在线视频播放 | 午夜 免费| 欧美精品乱码99久久影院 | 中文字幕色在线 | 日韩二区在线 | 探花视频免费观看 | 干 操 插 | 蜜桃麻豆www久久囤产精品 | 青草视频在线播放 | 五月婷婷视频在线 | 成人av免费在线播放 | 久久成人毛片 | 又粗又长又大又爽又黄少妇毛片 | 激情伊人五月天 | a在线免费观看视频 | 99热.com| 亚洲精品一区二区三区在线观看 | 国产成人免费 | 国产高清绿奴videos | 日韩在线观看小视频 | 久久久久久高潮国产精品视 | 色婷婷色 | 婷婷丁香七月 | 夜夜躁日日躁狠狠久久88av | 日日成人网 | 国产亚洲精品久久网站 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 国产一区成人在线 | 天天做日日做天天爽视频免费 | 久久精品播放 | 奇米网8888| 亚洲综合激情 | 久久精品国产成人精品 | www91在线观看 | 在线观看久草 | 成人a级网站 | 亚洲视频免费在线 | 免费在线色| 久久综合操 | 国产亚洲精品中文字幕 | 三级黄色理论片 | 国产91亚洲 | 麻豆国产精品一区二区三区 | 国产综合视频在线观看 | 国产视频黄 | 日韩资源在线观看 | 国产一区二区成人 | 一区免费在线 | 欧美日韩电影在线播放 | 456免费视频 | 欧美精品一区在线发布 | 四虎影视成人永久免费观看视频 | 99免在线观看免费视频高清 | 国产最新视频在线观看 | 狠狠狠干 | 婷婷在线综合 | 国产精品美乳一区二区免费 | 成人a免费看 | 久久久久久久久久毛片 | 亚洲五月六月 | 中文字幕在线观看免费高清电影 | 日韩免费在线观看视频 | 99这里都是精品 | 黄色电影网站在线观看 | 亚洲国产wwwccc36天堂 | 人人澡人人舔 | 黄免费在线观看 | 四虎永久免费网站 | 久青草国产在线 | 欧美日韩国产精品一区二区亚洲 | 午夜黄色影院 | 午夜av大片| 一级特黄aaa大片在线观看 | 国产日本高清 | 激情丁香5月 | 午夜av一区二区三区 | 久久国产露脸精品国产 | 91精品在线免费视频 | 国产特级毛片aaaaaa | 成人黄色毛片视频 | 久久夜色精品国产欧美一区麻豆 | 国产乱码精品一区二区三区介绍 | 美女视频网站久久 | 午夜久久久精品 | 国产精品久久久久久影院 | 久久99国产综合精品 | 久久久久久久久电影 | 欧美成人xxx | 精品久久久久久综合 | 久久视频这里有久久精品视频11 | 免费视频91| 人人干网| 久久综合9988久久爱 | 国产电影一区二区三区四区 | 天天干,天天射,天天操,天天摸 | 亚洲97在线 | 日韩av影视在线观看 | 99情趣网视频 | 国产伦理一区二区 | 欧美成年黄网站色视频 | 免费高清在线观看成人 | 久久国产精品精品国产色婷婷 | 久久不射电影网 | 亚洲精品免费观看视频 | 欧美日韩中文字幕综合视频 | 91视频91蝌蚪 | 在线精品播放 | 中文在线字幕观看电影 | 九九九国产| 免费在线观看视频a | 国产国产人免费人成免费视频 | 日韩中文字幕免费电影 | 在线观看午夜av | a在线观看视频 | 综合久久网站 | 五月婷婷综合在线 | 久久免费福利 | 日韩国产欧美在线视频 | 亚洲国产精品久久久久 | 久久人人爽爽人人爽人人片av | 国产亚洲视频在线观看 | 日韩网站在线免费观看 | 日韩超碰在线 | 在线v片免费观看视频 | 久久久精品免费看 | 精品国产网址 | 97国产精品一区二区 | 国产精品久久久久久婷婷天堂 | 日韩一区二区三区免费视频 | 六月丁香伊人 | 久久另类视频 | 久久激情综合网 | 99精品视频免费在线观看 | 免费观看丰满少妇做爰 | 激情狠狠干 | 亚洲首页 | 欧美日韩高清免费 | 黄色小网站在线 | 精品在线亚洲视频 | 成人免费在线播放视频 | 中国一 片免费观看 | 97超碰人人澡 | 亚洲天堂网在线视频观看 | 免费看黄在线 | 毛片一区二区 | 亚洲国产av精品毛片鲁大师 | 国产高清成人av | 五月天天天操 | 日本精a在线观看 | 久久综合九色综合久久久精品综合 | 四虎国产精品免费 | 久久精品国产免费看久久精品 | 中文字幕一区二区三区久久蜜桃 | 国产午夜精品福利视频 | 天天综合色 | 国产中文字幕91 | 一级精品视频在线观看宜春院 | 精品日韩中文字幕 | 免费中文字幕 | 97在线免费 | 国产精品欧美精品 | 一级黄色在线免费观看 | 99热这里是精品 | 91麻豆国产 | 91在线播 | 五月天婷婷在线观看视频 | 中文在线a天堂 | 免费av在线网 | 伊人婷婷久久 | 欧美亚洲国产精品久久高清浪潮 | 在线免费国产视频 | 麻豆综合网| 欧美极品xxxxx | 国产又黄又爽又猛视频日本 | 亚洲精品在线免费观看视频 | 亚洲精品国产精品久久99 | 狠狠操操操 | 91亚洲精品国偷拍 | 亚洲婷婷综合色高清在线 | 黄色免费视频在线观看 | 久久看毛片 | 国产精品18videosex性欧美 | 亚洲高清在线 | 伊人五月天 | 国产在线精品二区 | 中文字幕在线观看网站 | 国产精品欧美久久久久久 | 国产一级淫片在线观看 | 99亚洲国产| 欧美国产日韩在线观看 | av青草| 精品免费久久久久 | 久草在线视频免费资源观看 | 91视频a | av 一区二区三区 | 欧美大香线蕉线伊人久久 | 激情久久久 | 精品国内自产拍在线观看视频 | 精品不卡av | www.午夜视频 | 999久久久久久久久久久 | 欧美日韩性 | 99精品久久只有精品 | 色天天中文 | 日韩免费在线观看网站 | 日日碰夜夜爽 | 日韩一级电影在线 | 日韩三级不卡 | 日韩在线免费 | av中文字幕在线免费观看 | 在线a人片免费观看视频 | 在线观看免费国产小视频 | 久久免费视频播放 | 日韩视频1区| 在线观看免费av网站 | 中文字幕欧美日韩va免费视频 | 乱子伦av | 国内揄拍国产精品 | 国产黄av| 黄色福利网 | 人人艹人人 | 少妇bbw搡bbbb搡bbbb | 国产精品一区专区欧美日韩 | 91传媒视频在线观看 | 爱色av.com | 色黄www小说 | 91av原创| 国产精品丝袜久久久久久久不卡 | 欧美日韩国产精品一区 | 91视频高清 | 国产成人免费在线 | 亚洲精品在线二区 | 精品国产一区二区三区av性色 | 国产在线观看免 | 91手机视频在线 | 亚洲精品天天 | 久久99精品国产麻豆宅宅 | 国内精品久久久久久久 | av免费高清观看 | 中文在线a∨在线 | 久久新| 黄色网www| 最新日韩电影 | 久99久久| 欧美精品v国产精品v日韩精品 | 97在线成人 | 欧美精品久 | 免费91在线观看 | 色小说在线 | 夜色资源站wwwcom | 在线观看中文字幕亚洲 | 国产只有精品 | 久久精品国产免费观看 | 国产色视频一区 | 精品欧美乱码久久久久久 | 狠狠狠色丁香婷婷综合激情 | 久草免费福利在线观看 | 久久视影 | 亚洲狠狠丁香婷婷综合久久久 | 午夜免费久久看 | 九九热re | 国产一区二区在线免费视频 | 久草精品在线播放 | 成人小视频在线免费观看 | 97超碰中文字幕 | 国产美女久久 | 少妇高潮流白浆在线观看 | 国产成人一区二区三区 | 亚洲精品国产自产拍在线观看 | 日韩a在线观看 | 日日夜夜精品网站 | 国产免费成人av | 97超碰在 | 天天玩天天操天天射 | aaaaaa毛片| 欧美成人aa | 韩国精品视频在线观看 | 日韩免费观看av | 国产黄色大片免费看 | 中文字幕在线电影 | 国产精品视频大全 | 国产成人一区二区在线观看 | 国产精品久久久久久久久久妇女 | 亚洲精品视频www | 日韩欧美精品在线 | 91成人精品 | 人人草人 | 美女网站在线观看 | 亚洲激色| 亚洲 欧美 日韩 综合 | 日韩欧美在线综合网 | 在线播放视频一区 | 伊人资源站 | 久久精品久久久精品美女 | 国产精品久久久久久久久费观看 | 国产精品视频99 | 日韩一区二区三区观看 | 成人国产网站 | 亚洲综合在线五月天 | 久久综合影音 | 欧美91精品国产自产 | 国产va饥渴难耐女保洁员在线观看 | 日韩精品一区二区在线观看视频 | 久热av在线 | 看国产黄色大片 | 精品自拍网 | 国模视频一区二区 | 国产免费嫩草影院 | 日韩一级电影在线观看 | 色在线视频网 | 91cn国产在线| 天天人人综合 | 岛国av在线不卡 | 婷婷丁香色 | 91精品夜夜 | 成人黄色片在线播放 | 久久精品欧美一区 | 特黄免费av | 欧美一区二区在线 | 丝袜美女在线 | 在线观看一区 | 91激情 | 国产91免费看 | 激情视频区 | 久久99婷婷 | 久久午夜影院 | 亚洲电影第一页av | 久久久久亚洲精品国产 | 中文字幕在线观看资源 | 九九热免费精品视频 | 国产精品九九久久久久久久 | 永久黄网站色视频免费观看w | 一区二区精品在线 | 超碰公开97| 日韩av片无码一区二区不卡电影 | 日韩精品国产一区 | 免费av一级电影 | 国产成人福利在线 | 久久视屏网| 日韩动态视频 | 婷婷色六月天 | 亚洲人成人在线 | 精精国产xxxx视频在线播放 | 久草视频免费看 | 一区二区视频在线免费观看 | 狠狠干2018| 天天爽夜夜爽人人爽一区二区 | 在线日韩亚洲 | av综合在线观看 |