精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

走進Golang之運行與Plan9匯編

開發 后端
今天我們一起來學習一下生成的目標代碼如何在計算機上執行。以及通過查閱 Golang 的 Plan9 匯編來了解Golang的一些內部秘密。

通過上一篇走進Golang之匯編原理,我們知道了目標代碼的生成經歷了那些過程。今天我們一起來學習一下生成的目標代碼如何在計算機上執行。以及通過查閱 Golang 的 Plan9 匯編來了解Golang的一些內部秘密。

Golang的運行環境

當我們把編譯后的Go代碼運行起來,它會以進程的方式出現在系統中。然后開始處理請求、數據,我們會看到這個進程占用了內存消耗、cpu占比等等信息。本文就是要來解釋在程序的運行過程中,內存、CPU、操作系統(當然還有其它的硬件,文中關系不大,就不說了)是如何進行配合,完成了我們代碼所指定的事情。

內存

首先,我們先來說說內存。先來看一個我們運行的go進程。

代碼如下: 

  1. package main  
  2. import (  
  3.     "fmt"  
  4.     "log"  
  5.     "net/http"  
  6.  
  7. func main() {  
  8.     http.HandleFunc("/", sayHello)  
  9.     err :http.ListenAndServe(":9999", nil)  
  10.     if err != nil {  
  11.         log.Fatal("ListenAndServe: ", err)  
  12.     }  
  13.  
  14. func sayHello(w http.ResponseWriter, r *http.Request) {  
  15.     fmt.Printf("fibonacci: %d\n", fibonacci(1000))  
  16.     _, _ = fmt.Fprint(w, "Hello World!")  
  17.  
  18. func fibonacci(num int) int {  
  19.     if num < 2 {  
  20.         return 1  
  21.     }  
  22.     return fibonacci(num-1) + fibonacci(num-2)  

來看一下執行情況:

  1. dayu.com >ps aux  
  2. USER               PID   %CPU  %MEM      VSZ     RSS    TT  STAT   STARTED    TIME     COMMAND  
  3. xxxxx              3584  99.2  0.1     4380456  4376   s003  R+    8:33下午   0:05.81  ./myhttp 

這里我們先來不關注其它指標,先來看 VSZ 與 RSS。

  •  VSZ: 是指虛擬地址,他是程序實際操作的內存。包含了分配還沒有使用的內存。
  •  RSS: 是實際的物理內存,包含了棧內存與堆內存。

每一個進程都是運行在自己的內存沙盒里,程序被分配的地址都是 “虛擬內存”,物理內存對程序開發者來說實際是不可見的,而且虛擬地址比進程實際的物理地址要大的多。我們經常編程中取指針對應的地址實際就是虛擬地址。這里一定要注意區分虛擬內存與物理內存。來一張圖感受一下。

這張圖主要是為了說明兩個問題:

  1.  程序使用的是虛擬內存,但是操作系統會把虛擬內存映射到物理內存;你會發現自己機器上所有進程的VSZ要大得多;
  2.  物理內存可以被多個進程共享,甚至一個進程內的不同地址可能映射的都是同一個物理內存地址。

上面搞明白了程序中的內存具體是指什么,接下來說明程序是如何使用內存的(虛擬內存),內存說白了就是比硬盤存取速度更快的一個硬件,為了方便內存的管理,操作系統把分配給進程的內存劃分成了不同的功能塊。像我們經常說的:代碼區,靜態數據區,堆區,棧區等。

這里借用一張網絡上的圖來看一下。

這里就是我們程序(進程)在虛擬內存中的分布。

代碼區:存放的就是我們編譯后的機器碼,一般來說這個區域只能是只讀。

靜態數據區:存放的是全局變量與常量。這些變量的地址編譯的時候就確定了(這也是使用虛擬地址的好處,如果是物理地址,這些地址編譯的時候是不可能確定的)。Data與BSS都屬于這一部分。這部分只有程序中止(kill掉、crasg掉等)才會被銷毀。

棧區:主要是 Golang 里邊的函數、方法以及其本地變量存儲的地方。這部分伴隨函數、方法開始執行而分配,運行完后就被釋放,特別注意這里的釋放并不會清空內存。后面文章講內存分配的時候再詳細說;還有一個點需要記住棧一般是從高地址向低地址方向分配,換句話說:高地址屬于棧低,低地址屬于棧底,它分配方向與堆是相反的。

堆區:像 C/C++ 語言,堆完全是程序員自己控制的。但是 Golang 里邊由于有GC機制,我們寫代碼的時候并不需要關心內存是在棧還是堆上分配。Golang 會自己判斷如果變量的生命周期在函數退出后還不能銷毀或者棧上資源不夠分配等等情況,就會被放到堆上。堆的性能會比棧要差一些。原因也留到內存分配相關的文章再給大家介紹。

內存的結構搞明白了,我們的程序被加載到內存還需要操作系統來指揮才能正確運行。

補充一個比較重要的概念:

尋址空間:一般指的是CPU對于內存尋址的能力,通俗地說,就是能最多用到多少內存的一個問題。比如:32條地址線(32位機器),那么總的地址空間就有 2^32 個,如果是64位機器,就是 2^64 個尋址空間。可以使用 uname -a 來查看自己系統支持的位數字。

操作系統、CPU、內存互相配合

為了講清楚程序運行與調用,我們得先理清楚操作系統、內存、CPU、寄存器這幾者之間的關系。

  •  CPU: 計算機的大腦,它才能理解并執行指令;
  •  寄存器:嚴格講寄存器是CPU的組成部分,它主要負責CPU在計算時臨時存儲數據;當然CPU還有多級的高速緩存,與我們這里相關度不大,就略過,大家知道其目的是為了彌補內存與CPU速度的差距即可;
  •  內存:像上面內存被劃分成不同區,每一部分存了不同的數據;當然這些區的劃分、以及虛擬內存與物理內存的映射都是操作系統來做的;
  •  操作系統:控制各種硬件資源,為其它運行的程序提供操作接口(系統調用)及管理。

這里操作系統是一個軟件,CPU、寄存器、內存(物理內存)都是實打實的硬件。操作系統雖然也是一堆代碼寫出來的。但是她是硬件對其它應用程序的接口。總的來講操作系統通過系統調用控制所有的硬件資源,他把其它的程序調度到CPU上讓其它程序執行,但是為了讓每個程序都有機會使用CPU,CPU又通過時間中斷把控制權交給操作系統。

讓操作系統可以控制我們的程序,我們編寫的程序需要遵循操作系統的規定。這樣操作系統才能控制程序執行、切換進程等操作。

最后我們的代碼被編譯成機器碼之后,本質就是一條條的指令。我們期望的就是CPU去執行完這些指令進而完成任務。而操作系統又能夠幫助我們讓CPU來執行代碼以及提供所需資源的調用接口(系統調用)。是不是非常簡單?

Go程序的調用規約

在上面我們知道整個虛擬內存被我們劃分為:代碼區、靜態數據區、棧區、堆區。接下來要講的Go程序的調用規約(其實就是函數、方法運行的規則),主要是涉及上面所說的棧部分(堆部分會在內存分配的文章里邊去講)。以及計算機軟硬各個部分如何配合。接下來我們就來看一下程序的基本單位函數跟方法是怎么執行與相互調用的。

函數在棧上的分布

這一部分,我們先來了解一些理論,然后接著用一個實際的例子來分析一下。先通過一張圖來看一下在 Golang 中函數是如何在棧上分布的。

幾個涉及到的專業用語:

  •  棧:這里說的棧跟上面的解釋含義一致。無論是進程、線程、goroutine都有自己的調用棧;
  •  棧幀:可以理解是函數調用時在棧上為函數所分配的區域;
  •  調用者:caller,比如:a函數調用了b函數,那么a就是調用者;
  •  被調者:callee,還是上面的例子,b就是被調者。

棧幀

這幅圖所展示的就是一個 棧幀 的結構。也可以說棧楨是棧給一個函數分配的棧空間,它包括了函數調用者地址、本地變量、返回值地址、調用者參數等信息。

這里有幾個注意點,圖中的 BP、SP都表示對應的寄存器。

  •  BP:基址指針寄存器(extended base pointer),也叫幀指針,存放著一個指針,表示函數棧開始的地方。
  •  SP:棧指針寄存器(extended stack pointer),存放著一個指針,存儲的是函數棧空間的棧頂,也就是函數棧空間分配結束的地方,注意這里是硬件寄存器,不是Plan9中的偽寄存器。

BP 與 SP 放在一起,一個表示開始(棧頂)、一個表示結束(棧低)。

有了上面的基礎知識,接著下面用實際的例子來驗證一下。

Go的調用實例

才開始,我們就從一個簡單的函數開始來分析一下整個函數的調用過程(下面涉及到 Plan9 匯編,請別慌,大部分都能夠看懂,并且我也會寫注釋)。 

  1. package main  
  2. func main() {  
  3.     a :3  
  4.     b :2  
  5.     returnTwo(a, b)  
  6.  
  7. func returnTwo(a, b int) (c, d int) {  
  8.     tmp :1 // 這一行的主要目的是保證棧楨不為0,方便分析  
  9.     c = a + b  
  10.     d = b - tmp  
  11.     return  

上面有兩個函數,main 定義了兩個本地變量,然后調用 returnTwo 函數。returnTwo 函數有兩個參數與兩個返回值。設計兩個返回值主要是一起來看一下 golang 的多返回值是如何實現的。接下來我們把上面的代碼對應的匯編代碼展示出來。

有幾行代碼需要特別解釋下, 

  1. 0x0000 00000 (test1.go:3) TEXT "".main(SB), ABIInternal, $56-0 

這一行中的重點信息:$56-0。56 表示的該函數棧楨大小(兩個本地變量,兩個參數是int類型,兩個返回值是int類型,1個保存base pointer,合計7 * 8 = 56);0表示 mian 函數的參數與返回值大小。待會可以在 returnTwo 中去看一下它的返回值又是多少。

接下來在看一下計算機是怎么在棧上分配大小的。 

  1. 0x000f 00015 (test1.go:3)       SUBQ    $56, SP // 分配,56的大小在上面第一行定義了  
  2. ... ...  
  3. 0x004b 00075 (test1.go:7)       ADDQ    $56, SP // 釋放掉,但是并未清空 

這兩行,一個是分配,一個是釋放。為什么用了 SUBQ 指令就能進行分配呢?而 ADDQ 是釋放?記得我們前面說過嗎? SP 是一個指針寄存器,并且指向棧頂,棧又是從高地址向低地址分配。那么對它做一次減法,是不是表示從高地址向低地址方向移動指針了呢?釋放也是同樣的道理,一次加法操作又把 SP 恢復到初始狀態。

再來看一下對 BP 寄存器的操作。 

  1. 0x0013 00019 (test1.go:3)       MOVQ    BP, 48(SP) // 保存BP  
  2. 0x0018 00024 (test1.go:3)       LEAQ    48(SP), BP // BP存放了新的地址  
  3. ... ...  
  4. 0x0046 00070 (test1.go:7)       MOVQ    48(SP), BP // 恢復BP的地址 

這三行代碼是不是感覺很變扭?寫來寫去讓人云里霧里的。我先用文字描述一下,后面再用圖來解釋。

    我們先做如下假設:此時 BP 指向的 值 是:0x00ff,48(SP) 的 地址 是:0x0008。

  •  第一條指令 MOVQ BP, 48(SP) 是把 0x00ff 寫入到 48(SP)的位置;
  •  第二條指令 LEAQ 48(SP), BP 是更新寄存器指針,讓 BP 保存 48(SP) 這個位置的地址,也就是 0x00ff 這個值。
  •  第三條指令 MOVQ 48(SP), BP ,因為一開始 48(SP) 保存了最開始 BP 的所存的值 0x00ff,所以這里是又把 BP 恢復回去了。

這幾行代碼的作用至關重要,正因為如此在執行的時候,我們才能找到函數開始的地方以及回到調用函數的位置,它才可以繼續往下執行(如果覺得饒,先放過,后面有圖,看完后再回來理解)。接著來看一下 returnTwo 函數。

這里 NOSPLIT|ABIInternal, $0-32 說明,該函數的棧楨大小是0,由于有兩個int參數,以及2個int返回值,合計為 4*8 = 32 字節大小,是不是跟上面的 main 函數對上了?。

這里有沒有對 returnTwo 函數的棧楨大小是0表示迷惑呢?難道這個函數不需要棧空間嗎?其實主要原因是:golang的參數傳遞與返回值都是要求使用棧來進行的(這也是為什么go能夠支持多參數返回的原因)。所以參數與返回值所需空間都由 caller 來提供。

接下來,我們用完整的圖來演示一下這個調用過程。

這個圖就畫了將近1個小時,希望對大家理解有幫助。

整個的流程是:初始化 ----> call main function ----> call returnTwo function ----> returnTwo return ----> main return。

通過這張圖,在結合我上面的文字解釋,相信大家能夠理解了。不過這里還有幾個注意點:

  •  BP 與 SP 是寄存器,它保存的是棧上的地址,所以執行中可以對 SP 做運算找到下一個指令的位置;
  •  棧被回收 ADDQ $56, SP ,只是改變了 SP 指向的位置,內存中的數據并不會清空,只有下次被分配使用的時候才會清空;
  •  callee的參數、返回值內存都是caller分配的;
  •  returnTwo ret的時候,call returnTwo的next指令 所在棧位置會被彈出,也就是圖中 0x0d00 地址所保存的指令,所以 returnTwo 函數返回后,SP 又指向了 0x0d08 地址。

由于上面涉及到一些 Plan9 的知識,就順帶一起介紹一些它的語法,如果直接講語法會很枯燥,下面會結合一些實際中會用到的情況來介紹。既有收獲又能學會語法。

Go的匯編plan9

我們整個程序的編譯最終會被翻譯成機器碼,而匯編可以算是機器碼的文本形式,他們之間可以一一對應。所以如果我們能夠看懂匯編一點點就能夠分析出很多實際問題。

開發go語言的都是當前世界最TOP的那群程序員,他們選擇了持續裝逼,不用標準的 AT&T 也不用 Intel 匯編器,偏要自己搞一套,沒辦法,誰讓人家牛呢!Golang的匯編是基于 Plan9 匯編的,個人覺得要完全學懂太復雜了,因為這涉及到很多底層知識。不過如果只是要求看懂還是能夠做到的。下面我們就舉一些例子來試試看。

PS: 這東西完全學懂也沒有必要,投入產出比太低了,對于一個應用工程師能夠看懂就行。

在正式開始前,我們還是補充一些必要信息,上文已經涉及過一些,為了完整這里在整體介紹一下。

幾個重要的偽寄存器

  •  SB:是一個虛擬寄存器,保存了靜態基地址(static-base) 指針,即我們程序地址空間的開始地址;
  •  NOSPLIT:向編譯器表明不應該插入 stack-split 的用來檢查棧需要擴張的前導指令;
  •  FP:使用形如 symbol+offset(FP) 的方式,引用函數的輸入參數;
  •  SP:plan9 的這個 SP 寄存器指向當前棧幀的局部變量的開始位置,使用形如 symbol+offset(SP) 的方式,引用函數的局部變量,注意:這個寄存器與上文的寄存器是不一樣的,這里是偽寄存器,而我們展示出來的都是硬件寄存器。

其它還有一些操作指令,根據名字多半都能夠看出來,就不再介紹,直接開始干。

查看go應用代碼對應的翻譯函數 

  1. package main  
  2. func main() {  
  3. func test() []string {  
  4.     a :make([]string, 10)  
  5.     return a  
  6.  
  7. --------  
  8. "".test STEXT size=151 args=0x18 locals=0x40  
  9.         0x0000 00000 (test1.go:6)       TEXT    "".test(SB), ABIInternal, $64-24 // 棧幀大小,與參數、返回值大小  
  10.         0x0000 00000 (test1.go:6)       MOVQ    (TLS), CX  
  11.         0x0009 00009 (test1.go:6)       CMPQ    SP, 16(CX)  
  12.         0x000d 00013 (test1.go:6)       JLS     141  
  13.         0x000f 00015 (test1.go:6)       SUBQ    $64, SP  
  14.         0x0013 00019 (test1.go:6)       MOVQ    BP, 56(SP)  
  15.         0x0018 00024 (test1.go:6)       LEAQ    56(SP), BP 
  16.         ... ...  
  17.         0x001d 00029 (test1.go:6)       MOVQ    $0, "".~r0+72(SP)  
  18.         0x0026 00038 (test1.go:6)       XORPS   X0, X0  
  19.         0x0029 00041 (test1.go:6)       MOVUPS  X0, "".~r0+80(SP)  
  20.         0x002e 00046 (test1.go:7)       PCDATA  $2, $1  
  21.         0x002e 00046 (test1.go:7)       LEAQ    type.string(SB), AX  
  22.         0x0035 00053 (test1.go:7)       PCDATA  $2, $0  
  23.         0x0035 00053 (test1.go:7)       MOVQ    AX, (SP)  
  24.         0x0039 00057 (test1.go:7)       MOVQ    $10, 8(SP)  
  25.         0x0042 00066 (test1.go:7)       MOVQ    $10, 16(SP)  
  26.         0x004b 00075 (test1.go:7)       CALL    runtime.makeslice(SB) // 對應的底層runtime function 
  27.         ... ...  
  28.         0x008c 00140 (test1.go:8)       RET  
  29.         0x008d 00141 (test1.go:8)       NOP  
  30.         0x008d 00141 (test1.go:6)       PCDATA  $0, $-1  
  31.         0x008d 00141 (test1.go:6)       PCDATA  $2, $-1  
  32.         0x008d 00141 (test1.go:6)       CALL    runtime.morestack_noctxt(SB)  
  33.         0x0092 00146 (test1.go:6)       JMP     0 

根據對應的代碼行數與名字,很明顯的可以看到應用層寫的 make 對應底層是 makeslice。

逃逸分析

這里先說一下逃逸分析的概念。這里牽扯到棧、堆分配的問題。如果變量被分配到棧上,會伴隨函數調用結束自動回收,并且分配效率很高;其次分配到堆上,則需要GC進行標記回收。所謂逃逸就是指變量從棧上逃到了堆上(很多人對這個概念都不清楚就在談逃逸分析,面試遇到了好幾次😓)。 

  1. package main  
  2. func main() {  
  3.  
  4. func test() *int {  
  5.     t :3  
  6.     return &t  
  7.  
  8. ------  
  9. "".test STEXT size=98 args=0x8 locals=0x20  
  10.         0x0000 00000 (test1.go:6)       TEXT    "".test(SB), ABIInternal, $32-8  
  11.         0x0000 00000 (test1.go:6)       MOVQ    (TLS), CX  
  12.         0x0009 00009 (test1.go:6)       CMPQ    SP, 16(CX)  
  13.         0x000d 00013 (test1.go:6)       JLS     91  
  14.         0x000f 00015 (test1.go:6)       SUBQ    $32, SP  
  15.         0x0013 00019 (test1.go:6)       MOVQ    BP, 24(SP)  
  16.         0x0018 00024 (test1.go:6)       LEAQ    24(SP), BP  
  17.         ... ...  
  18.         0x001d 00029 (test1.go:6)       MOVQ    $0, "".~r0+40(SP)  
  19.         0x0026 00038 (test1.go:7)       PCDATA  $2, $1  
  20.         0x0026 00038 (test1.go:7)       LEAQ    type.int(SB), AX  
  21.         0x002d 00045 (test1.go:7)       PCDATA  $2, $0  
  22.         0x002d 00045 (test1.go:7)       MOVQ    AX, (SP)  
  23.         0x0031 00049 (test1.go:7)       CALL    runtime.newobject(SB) // 堆上分配空間,表示逃逸了  
  24.         ... ... 

這里如果是對 slice 使用匯編進行逃逸分析,并不會很直觀。因為只會看到調用了 runtime.makeslice 函數,該函數內部其實又調用了 runtime.mallocgc 函數,這個函數會分配的內存其實就是堆上的內存(如果棧上足夠保存,是不會看到對 runtime.makslice 函數的調用)。

實際go也提供了更方便的命令來進行逃逸分析:go build -gcflags="-m" ,如果真的是做逃逸分析,建議使用該命令,別折騰用匯編。

傳值還是傳指針

對于golang中的基本類型:字符串、整型、布爾類型就不多說了,肯定是值傳遞,那么對于結構體、指針到底是值傳遞還是指針傳遞呢? 

  1. package main    
  2. type Student struct {    
  3.     name string    
  4.     age  int    
  5. }    
  6. func main() {    
  7.     jack := &Student{"jack", 30}    
  8.     test(jack)    
  9. }    
  10. func test(s *Student) *Student {    
  11.     return s    
  12. }    
  13. -------    
  14. "".test STEXT nosplit size=20 args=0x10 locals=0x0    
  15.         0x0000 00000 (test1.go:14)      TEXT    "".test(SB), NOSPLIT|ABIInternal, $0-16   
  16.         ... ...   
  17.         0x0000 00000 (test1.go:14)      MOVQ    $0, "".~r1+16(SP) // 初始返回值為0   
  18.         0x0009 00009 (test1.go:15)      PCDATA  $2, $1   
  19.         0x0009 00009 (test1.go:15)      PCDATA  $0, $1   
  20.         0x0009 00009 (test1.go:15)      MOVQ    "".s+8(SP), AX // 將引用地址復制到 AX 寄存器  
  21.         0x000e 00014 (test1.go:15)      PCDATA  $2, $0   
  22.         0x000e 00014 (test1.go:15)      PCDATA  $0, $2   
  23.         0x000e 00014 (test1.go:15)      MOVQ    AX, "".~r1+16(SP) // 將 AX 的引用地址又復制到返回地址   
  24.         0x0013 00019 (test1.go:15)      RET  

 

通過這里可以看到在go里邊,只有值傳遞,因為它底層還是通過拷貝對應的值。

總結

今天的文章到此結束,本次主要講了下面幾個點:

  1.  計算機軟硬資源之間的相互配合;
  2.  Golang 編寫的代碼,函數與方法是怎么執行的,主要講了棧上分配與相關調用;
  3.  使用 Plan9 分析了一些常見的問題。

希望本文對大家在理解、學習Go的路上有一些幫助。 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2023-04-17 14:32:20

2019-11-15 15:20:27

Golang編譯器前端

2021-05-18 09:39:19

互聯網操作系統Go

2013-12-30 11:21:31

Go編譯器

2014-07-09 13:18:55

編程谷歌

2025-05-28 01:58:00

Go語言UTF-8

2012-11-13 10:27:45

PythonGo編程語言

2021-07-05 15:22:07

紫光CIO

2016-11-01 19:10:33

vue.js前端前端框架

2011-04-01 09:34:18

C#奇妙函數

2021-12-23 06:57:32

數據通信Websocket

2012-08-10 09:45:17

IBM專家集成系統PureSystemPureFlex Sy

2012-08-20 10:49:13

編程

2022-01-21 10:58:39

JavaScriptGolangPython

2021-07-22 09:43:09

Golang語言并發機制

2020-12-22 11:54:42

C語言Cortex-A9LED匯編

2012-08-20 09:53:48

編程編程建議程序員

2013-01-10 11:13:38

Golang WebRevel測試Web開發

2017-01-23 13:34:44

2017-05-27 20:32:20

點贊
收藏

51CTO技術棧公眾號

av图片在线观看| 日本午夜激情视频| 15—17女人毛片| 又色又爽又黄无遮挡的免费视频| 视频精品二区| 成人高清免费观看| 98精品国产自产在线观看| 青青草视频网站| 日韩伦理三区| 精品一二三四区| 久久久999国产| 久久久九九九热| 黄色在线观看www| 日本色综合中文字幕| 欧美成人精品二区三区99精品| 51xx午夜影福利| 天天综合在线视频| 成人精品影院| 欧美一级一级性生活免费录像| 99国产高清| 公侵犯人妻一区二区三区| 免费高清视频在线一区| 中文字幕欧美一| 欧美中文在线字幕| 黄色片网站在线播放| 国产精东传媒成人av电影| 91免费视频网| 久久久久久美女| 天天色综合天天色| 青草在线视频| 日本一区二区三区四区在线视频| 亚洲综合日韩在线| 欧美88888| caoporn成人免费视频在线| 国产精品久久久久久亚洲毛片| 99久久伊人精品影院| 少妇高潮av久久久久久| 欧美日韩一区二区三区四区在线观看| 亚洲图片在区色| 国产xxxx振车| 成人在线播放视频| 国产精品日本欧美一区二区三区| 精品久久久91| 男人天堂av电影| 九九99久久精品在免费线bt| 色av综合在线| 国产欧美在线一区二区| 中文字幕日产av| 色天下一区二区三区| 日韩一区二区三区四区五区六区| 无遮挡又爽又刺激的视频| 国产一二区在线观看| 久久久久久日产精品| 成人激情视频在线| 亚洲 欧美 视频| 国产精品啊啊啊| 久久av中文字幕| 亚洲AV成人无码网站天堂久久| 私拍精品福利视频在线一区| 日韩精品一区二区三区在线| 久久久久久国产精品日本| www免费网站在线观看| 成人美女在线视频| www.成人av.com| 国产高清在线免费| 国产乱子轮精品视频| 亚洲一区二区免费| 国产精品久久久久久久久久久久久久久久 | 亚洲最新av网站| 丝袜脚交一区二区| 欧美亚洲在线视频| 在线观看精品国产| 免费日韩一区二区| 日韩精品电影网| 制服丝袜在线第一页| 一区二区三区四区高清视频| 精品久久久久久国产| 国产九九九九九| 国产盗摄——sm在线视频| 日韩天天综合| 韩国成人在线视频| 国产精品视频区1| 中文字幕永久在线观看| 美女诱惑一区二区| 成人在线观看视频网站| 亚洲视频久久久| 国产原创一区二区| 成人看片在线| 亚洲精品视频网| 99精品国产91久久久久久| 久久亚洲综合网| 国产suv精品一区二区33| 国产精品久久久久久久免费软件 | 97久久精品在线| 精品国产aⅴ一区二区三区东京热| 亚洲人成网站在线在线观看| 亚洲精品中文在线影院| 日本高清xxxx| 91制片在线观看| 欧美视频在线观看 亚洲欧| www.色就是色| 日韩高清在线观看一区二区| 亚洲国产成人精品电影| 亚洲日本久久久| 神马电影久久| 精品国产一区二区三区在线观看 | 国产尤物一区二区在线| 99精品在线直播| 四虎在线观看| 国产精品久久三| 青青草成人免费在线视频| 亚洲天堂电影| 在线播放国产精品二区一二区四区 | 99re国产| 九色在线观看视频| 亚洲精品免费播放| 久久av一区二区| 成人动漫在线免费观看| 亚洲美女在线国产| 成人一级片网站| 激情国产在线| 精品视频在线看| 美女露出粉嫩尿囗让男人桶| 中文字幕色婷婷在线视频| 欧美久久久久久久久久| 男人午夜视频在线观看| 亚洲精品中文字幕99999| 久久色精品视频| 免费在线不卡视频| 欧美 亚欧 日韩视频在线 | 欧美aa在线| 8v天堂国产在线一区二区| 大又大又粗又硬又爽少妇毛片| 亚洲第一天堂| 国产成人在线精品| 国产在线视频第一页| 日韩在线卡一卡二| 91黄色国产视频| av片在线免费观看| 一本高清dvd不卡在线观看| 亚洲av午夜精品一区二区三区| 成人羞羞动漫| 欧美国产日韩中文字幕在线| 亚洲天堂中文在线| 91小视频在线| 国产va亚洲va在线va| 99久久久国产精品免费调教网站 | 欧美专区中文字幕| 六月婷婷综合网| 亚洲最新视频在线播放| 日韩在线不卡一区| av伊人久久| 国产成人福利网站| 麻豆国产在线播放| 欧美视频不卡中文| 亚洲av无码一区二区三区网址| 午夜精彩国产免费不卡不顿大片| 成人黄色av网站| 激情福利在线| 一本色道久久综合亚洲aⅴ蜜桃| 精品人妻一区二区免费| 亚洲欧美综合| 91久久爱成人| 免费在线看污片| 欧美va在线播放| 欧美日韩免费做爰视频| 国产成人综合亚洲网站| 国产精品8888| 91精品导航| 1769国产精品| av福利精品| 日韩精品一区二区三区蜜臀 | 亚洲精品看片| 欧美精品久久| 欧美三级电影网址| 久久91精品国产| 亚洲av成人无码网天堂| 91国偷自产一区二区三区成为亚洲经典| 欧美熟妇激情一区二区三区| 老司机午夜精品| 国产精品手机视频| 中老年在线免费视频| 中文字幕日韩av电影| 国产国语亲子伦亲子| 欧美日韩在线视频观看| 懂色av蜜臀av粉嫩av永久| 丁香桃色午夜亚洲一区二区三区| 日本wwww视频| 91一区在线| 精品在线视频一区二区三区| 电影一区二区| 久久久久久久爱| www免费网站在线观看| 欧美大片在线观看一区二区| 黄色av网站免费| 一区二区三区毛片| 成人午夜剧场视频网站| 国产福利91精品一区二区三区| 成人免费毛片网| 99久精品视频在线观看视频| 国产伦精品一区二区三区高清| www.国产精品| 97在线看福利| 国产在线高清视频| 亚洲人免费视频| 亚洲熟女综合色一区二区三区| 国产精品久久久久一区| 屁屁影院国产第一页| 久草这里只有精品视频| 人妻精品无码一区二区三区 | 欧美成年人在线观看| 欧美偷拍视频| 精品国产露脸精彩对白| 久久久无码一区二区三区| 国产欧美精品一区二区色综合朱莉 | 亚洲成人av动漫| 欧美电影在线观看免费| 亚洲综合国产精品| 开心久久婷婷综合中文字幕| 欧美一区二区三区四区在线 | 热re99久久精品国产66热| 在线免费观看污| 色偷偷偷亚洲综合网另类| 日本福利在线观看| 亚洲福利影片在线| 午夜精品一区二区三| 678五月天丁香亚洲综合网| 色老头在线视频| 福利视频一区二区| 日本三级欧美三级| 依依成人综合视频| 成人性生活毛片| 中文字幕精品在线不卡| www在线观看免费视频| 91亚洲国产成人精品一区二区三| 日本精品一二三| 国产精品99久久久久久久女警| 欧美成人福利在线观看| 日本欧美韩国一区三区| 青青在线视频免费| 老**午夜毛片一区二区三区 | 欧美黑人巨大xxxxx| 国内精品一区二区三区四区| 午夜视频www| 亚洲精品在线观| 粉嫩av一区二区夜夜嗨| 日韩视频一区二区三区 | 精品亚洲一区二区三区| 天堂在线观看免费视频| 亚洲精品黄网在线观看| 少妇又色又爽又黄的视频| 亚洲国产精品久久久久秋霞蜜臀| 免费观看国产精品| 亚洲国语精品自产拍在线观看| 欧美一级在线免费观看| 亚洲国产美女精品久久久久∴| 天天操天天干天天插| 日韩国产欧美区| 黄网在线观看| 日韩日本欧美亚洲| 在线āv视频| 国内精品久久久久久| 免费h在线看| 国产成人精品一区二区三区| 成人午夜亚洲| 亚洲一区精品电影| 高潮久久久久久久久久久久久久 | 天堂av在线免费观看| 亚洲欧美制服综合另类| 成人高清免费在线播放| 久久综合伊人77777蜜臀| 青春草在线免费视频| 57pao国产精品一区| 3d欧美精品动漫xxxx无尽| 国产精品亚洲自拍| 欧美专区一区| 国内成+人亚洲| 嫩草一区二区三区| japanese在线视频| 国产欧美日韩一级| 亚洲一级片免费| 国产精品69久久久久水密桃| 噜噜噜在线视频| 国产精品萝li| 久久久久久久久久综合| 色哟哟在线观看一区二区三区| 自拍偷拍色综合| 精品福利av导航| 成人亚洲性情网站www在线观看| 久久久91精品| 亚洲人成午夜免电影费观看| 国产精品视频网址| 亚洲一区二区三区日本久久九| 久久涩涩网站| 中文字幕日韩一区二区不卡 | 国产网站欧美日韩免费精品在线观看 | jlzzjlzz亚洲日本少妇| youjizz亚洲女人| 亚洲动漫第一页| 一本色道久久综合亚洲| 亚洲国产欧美一区二区三区久久| 国产无套粉嫩白浆在线2022年| 欧美精品做受xxx性少妇| 亚洲高清黄色| 国产精品伊人日日| 99精品美女| 国产综合免费视频| 粉嫩av亚洲一区二区图片| 摸摸摸bbb毛毛毛片| 亚洲一卡二卡三卡四卡无卡久久| 欧美日韩 一区二区三区| 亚洲福利视频在线| 亚洲区欧洲区| 成人激情在线播放| 国内精品久久久久久99蜜桃| 国产二区视频在线| 国产乱色国产精品免费视频| 亚洲最大成人综合网| 精品国产91久久久久久| 成人av无码一区二区三区| 日日狠狠久久偷偷四色综合免费| 欧美电影免费看| 精品日韩电影| 亚洲成人中文| 深夜视频在线观看| 亚洲激情综合网| 日本福利视频在线观看| 性xxxxfreexxxxx欧美丶| 亚洲一区二区少妇| 欧美大片aaaa| 欧美伦理片在线观看| 久久久av毛片精品| 国产微拍精品一区| 亚洲国产福利在线| 国产美女一区视频| 国产91一区二区三区| 欧美另类专区| 亚洲妇女无套内射精| 一区二区三区欧美久久| 国产精品久久久久久久免费看| 在线看日韩av| 成人在线视频免费看| 日韩高清av| 蜜臀久久99精品久久久久宅男| 国精产品一区二区三区| 日本电影亚洲天堂一区| 国产在线一二| 国产精品日韩在线观看| 日韩国产欧美一区二区| 国产理论在线播放| 国产精品第13页| 97超碰人人草| 久久成人综合视频| 亚洲成人五区| 黄色成人在线看| 91一区一区三区| 无码一区二区三区在线观看| 亚洲欧美国产精品专区久久 | 亚欧美无遮挡hd高清在线视频| 中文字幕成人在线视频| 中文字幕亚洲精品在线观看| 国产色片在线观看| 欧美国产日韩一区二区| 色婷婷久久久| 久久精品午夜福利| 国产精品美日韩| av中文字幕第一页| 久久久这里只有精品视频| 日韩极品在线| 手机在线看福利| 亚洲人成伊人成综合网小说| 亚洲国产精彩视频| 欧美夜福利tv在线| 成人影视亚洲图片在线| 久久久久无码精品| 午夜激情久久久| 成人小视频在线播放| 中文字幕日韩在线播放| 国产精品一区三区在线观看| 欧洲亚洲一区二区| 蜜桃一区二区三区在线观看| 久草综合在线视频| 亚洲精品二三区| 不卡亚洲精品| 18黄暴禁片在线观看| 国产亚洲va综合人人澡精品| 国产精品玖玖玖| 26uuu久久噜噜噜噜| 日韩中字在线| 久久精品女同亚洲女同13| 欧美丝袜自拍制服另类| 91jq激情在线观看| 一区在线电影| 91伊人久久大香线蕉| 国产色综合视频| 国产v综合ⅴ日韩v欧美大片| 欧美激情在线| 欧美老女人性生活视频| 亚洲成人在线视频播放| 欧美91在线|欧美|