3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

西电计科院微机原理与系统设计课程笔记(车向泉版)

發布時間:2023/12/10 windows 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 西电计科院微机原理与系统设计课程笔记(车向泉版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

微機原理與系統設計

以下內容是西安電子科技大學計算機科學與技術學院2021年大三上學期車向泉老師的微機原理與系統設計課程的隨課筆記。筆記的PDF版本和課程的學在西電上課錄像下載鏈接如下(請勿將錄像上傳到B站等網站!!):

鏈接:https://pan.baidu.com/s/12b7Ssu6uygtFn-gfBYoy6g
提取碼:2v5w

?

閱讀時請注意:

1.筆記中的刪除線標注了上課時老師做了講解但筆記沒有詳細記述的內容,有需要可以自己觀看錄播的相應內容學習

2.9月30日的錄播缺失,該節課的內容對應第三章最后的幾小節,期末考試不要求

3.第8章只講了前一部分,該章內容就是第6章、第7章知識的綜合運用,所以沒有記述。第8章和復習課內容對應錄播資源的最后四節,可以自行觀看學習

4.雖然筆記的內容比較多,但實際上32位匯編、C語言與匯編語言的混合編程、總線的大部分內容等等都不是期末考試要求的內容。具體哪些內容不要求在每學期末車老師的復習課里都會說

其他各科筆記匯總

開課介紹

數字電路與邏輯設計:用電路來實現邏輯關系,了解常用的一些模塊和芯片

?

計算機組織與體系結構:這個課以前是計算機組成原理和計算機系統結構兩門課。上學期上課時講過三個概念:計算機系統結構,計算機組成,計算機實現

在設計計算機時,首先要做一個總體的架構,包括指令集,流水線結構等等,這個主體設計就是計算機系統結構要研究的內容

之后要細化為邏輯電路,這就是計算機組成要研究的內容

然后要選擇合適的芯片,芯片之間連接構成電路,最后調試。實實在在地做出來,這是計算機實現要解決的問題

?

單片機電路設計與開發/微機原理與系統設計/嵌入式系統這三門課很像,都對應計算機實現。要構成一個計算機系統,首先要選擇一個CPU,然后增加一些外圍的東西,如存儲器,各種接口芯片。在此基礎上還要設計一些軟件讓它工作,這個整體思路都是一樣的。區別在于:

1.研究的CPU不一樣

單片機的CPU相對來講性能比較弱,像8051是8位CPU,純粹單任務,不支持虛擬存儲管理,多任務,也沒有流水線和高速緩存

嵌入式系統主要研究ARM的Cortex-A系列,有MMU存儲管理單元,支持虛擬存儲管理,多任務,也有流水線和高速緩存,可以移植一些操作系統,如Linux

微機原理則研究Intel和AMD的X86處理器

2.編程用語言不一樣

3.課程教授方式不同

4.涉及領域不一樣

單片機一般用在物聯網,如一些家用電器里面,成本低且可靠性高

ARM的Cortex-A系列一般用在智能手機,平板電腦等手持移動設備上,操作系統以Android為主

x86一般用在筆記本電腦,臺式機,超級計算機等上,操作系統以Linux和Windows為主

?

講了下x86重要性,然后推薦了幾本教材和參考資料

緒論

基本概念

?

要構成一個CPU,得有控制器,運算器和寄存器,然后通過總線連接起來。在早期這些都是分立元件,隨著芯片的集成度提高后,可以把這些構成CPU的東西放在一個芯片里面,這個芯片就叫微處理器。隨著集成度越來越高,芯片里還可以集成一定容量的高速緩存,協處理器,甚至很多個CPU的內核

微處理器還要從內存里取指令然后執行指令。人和計算機交互要通過外設,外設要通過接口才能夠連接到計算機里面。微處理器,內存還有各種各樣的接口放在一起通過系統總線連到一塊就叫微型計算機

想要計算機工作還需要相應的軟件,硬件和軟件加在一塊叫微型計算機系統

?

構成微型計算機的這些東西做到一個芯片里面,好像一個芯片就是一個計算機,這就叫單片機。加上相應的軟件就構成單片機系統

?

從廣義上講,單片機系統就屬于嵌入系統。 狹義上講,嵌入系統指的是性能比較強的專用計算機

SOC (System on Chips) 把一個計算機系統都集成在芯片里面。Intel最新的x86處理器,如i3,i5,i7i3,i5,i7i3i5i7就屬于SOC,里面不僅集成了多個CPU內核,還集成了圖形處理單元,一些高速的總線接口,內存控制器等等,把構成計算機的大多數電路都集成在一個芯片里面

?

微處理器概述

介紹了Intel的x86處理器的歷史,中間比較了幾個處理器的參數

8088微處理器是8086微處理器的簡化版,它的內核仍然是16位的CPU,但是外部系統總線數據線只有8根線。訪問內存和接口時一次只能傳輸8位數據

?

?

微型計算機概述

假設有兩臺CPU是x86指令集兼容,但是如主板,接口連接的外設等底層硬件不同的計算機,為什么可以實現安裝相同的操作系統和軟件?

?

操作系統跟硬件之間隔了一層。 計算機剛一加電,啟動之后最先執行的代碼是固化在計算機主板的ROM里面(現在用的是flash存儲器),那段代碼叫BIOS。這個程序要做的是:

1.硬件的自檢

如檢查一下內存有多大,如何控制內存,有什么外設接口等

2.各種外設接口初始化

接口和外設內也會有一些寄存器,里面的內容決定其工作狀態。 加電之后的內容是隨機的,所以要BIOS程序寫入內容初始化使其正常工作

3.給操作系統提供功能調用

BIOS程序執行完后,它的代碼還會駐留在內存里面,然后再從磁盤的引導扇區裝代碼,引導代碼裝操作系統。操作系統在裝載的過程中是通過BIOS程序提供的編程接口,用調用函數或者軟中斷的形式來調用BIOS程序的代碼來訪問硬件的

BIOS程序給操作系統提供的編程接口是標準化的,這樣在不同的硬件上就可以裝相同的操作系統

?

x86處理器剛加電啟動時處于實模式,實模式相當于是一臺快速的8086,只能夠運行16位的程序。所以BIOS程序全部或者說最開始執行的那段代碼肯定要設計成16位程序,通??赡苓€要用匯編語言來設計。 但是隨著操作系統裝載完成,CPU最終要從實模式切換到32位或64位CPU的保護模式,這時操作系統訪問硬件就要調用設備驅動程序提供的函數,而設備驅動程序給某一操作系統提供的編程接口也是標準的

不同的硬件設備驅動程序不一樣,但它給操作系統提供的編程接口調用方式都是一樣的,這樣在不同的硬件上就可以裝相同的操作系統

?

中間介紹了微型計算機的歷史

Intel 單核/多核處理器

單核處理器8086

8086具有以下特點:

1.最大內存尋址空間可以達到1M(=220)1M(=2^{20})1M(=220)字節

2.內部的通用寄存器都是16位的,因為它是16位的CPU

?

16位的寄存器怎么表示20位的內存地址?

對內存采用分段管理方式。段寄存器保存段的起始地址的高16位,低4位默認是0;指針寄存器內存16位的段內偏移

3.x86處理器采用獨立編址。內存與接口和外設里的存儲器各有獨立的地址空間,各有不同的指令和讀寫信號

8086的接口地址空間只有64K字節,不需要分段

?

?

?

8086的內部框圖:

8086內部有14個程序員可見的16位通用寄存器

8088的指令隊列是4個字節,8086是6個字節

分為BIU和EU。由于有指令隊列,二者可并行工作

總線接口單元BIU (Bus Interface Unit) :負責與存儲器,I/O接口出傳遞數據

執行單元EU (Execute Unit) :負責指令的執行

?

8086的AX~\sim???DX4個寄存器可以拆成2個8位的來用,如低8位叫AL,高8位叫AH

匯編語言中 [SI] 表示寄存器間接尋址

?

?

?

8086的寄存器結構:

SP,BP,SI,DI,IP是指針寄存器,用來存段內偏移。CS,DS,SS,ES是段寄存器,用來存段起始地址的高16位

例題:

這段程序訪問的主存地址是:

MOV DX,0A000H MOV DS,DX MOV SI,9000H MOV AL,[SI]

?

答案:A9000H

解析:

1.數據傳送指令不支持立即數到段寄存器之間的直接傳送,所以要初始化段寄存器必須要先把立即數傳送到某一個通用寄存器

2.16進制的立即數形式如果最高位是英文字母,在它的左側必須要加一個0,編譯程序才會認為這是一個立即數

3.最終DS內容為0A000H,SI內容為9000H。0A0000H + 9000H = 0A9000H

?

代碼段寄存器 (Code Segment):程序執行時內存里會存機器指令,這些機器指令所在的段叫代碼段。代碼段段的起始地址的高16位就存在CS

數據段寄存器 (Data Segment):指令執行的過程中肯定需要一些數據要從內存中取,或者最終的結果要存到內存中去。存儲數據的段叫數據段

堆棧段寄存器 (Stack Segment):執行的指令中會有PUSH壓棧和POP出棧指令,主程序調用時要保護當前的斷點,斷點要保護在堆棧里面,免不了要涉及一些和堆棧有關的操作。堆棧的這些數據所在的段叫堆棧段

附加段寄存器 (Extra Segment):也是用來訪問數據的。默認用DS,也可以指定用ES來訪問數據。一般用于跨段訪問數據

MOV AX,[BX] ;默認段寄存器是DS MOV AX,ES:[BX] ;加段超越前綴,此時段寄存器是ES

?

?

AX~DXAX\sim DXAXDX??????大多數情況下都可以隨便用,但也有特殊用途:

數據寄存器AX (Accumulator):一些特殊的指令,比如說乘法指令,被乘數是隱含尋址,默認在AX。最終結果的一部分也會放在AX,除法指令也有類似的規定。包括后面用來訪問接口的IN指令和OUT指令,寄存器必須得用AX

運算結果的低16位默認存在AX,高16位默認存在DX

數據寄存器BX (Base):也可以當指針寄存器來用,用來間接尋址

AX,CX,DX不可以

數據寄存器CX (Count):在一些特殊的指令中用于計數,如匯編語言中用LOOP指令實現循環時CX會記錄剩余循環次數

數據寄存器DX (Data):純粹用來存數據

?

?

指令指針寄存器 (Instruction Point):為了取得下一條指令的內存地址,需要用到CS和IP,分別存代碼段的起始地址的高16位(低4位默認為0)和16位的段內偏移

堆棧指針寄存器 (Stack Point):SS和SP配合共同確定當前堆棧棧頂的位置

注意x86中棧頂是小地址,棧底是大地址

16位的CPU,堆棧里每一個數據必須是16位的。所以沒有 PUSH AL 和 POP AL,只有 PUSH AX 和 POP AX。32位的x86同理

基址指針寄存器 (Base Point):指針寄存器如果用BX,那默認的段寄存器是DS。如果用BP,那默認的段寄存器是SS。故BP一般是用來間接尋址訪問堆棧當中的任意一個元素的

源變址寄存器 (Source Point) 和目的變址寄存器 (Destination Point):訪問數據,默認的段寄存器是DS,指針寄存器可以用BX,SI,DI,只有這3個寄存器可以用來間接尋址訪問數據段

?

標志寄存器/程序狀態字 (PSW/FLAGS) :

輔助進位標志位 (Auxiliary Carry - BCD):加法運算如果運算結果的第3位向第4位有進位,AF置1。BCD數運算有關的指令里可能會用到

第幾位從低位,從0開始編號

進位/借位標志位 (Carry Flag):加法運算運算結果的最高位向更高位有進位或減法運算最高位向更高位有借位,CF置1

這里的加減法理解為無符號數相加減

奇偶標志位 (Parity Flag):運算結果中1的結果如果為偶數個,PF置1??捎糜诩悠媾夹r炍?/p>

符號標志位 (Sign Flag):反映運算結果的最高位,最高位是什么SF就是什么

零標志位 (Zero Flag):運算結果為0,ZF置1

溢出標志位 (Overflow Flag):運算結果溢出時,OF置1

以上標志位都是運算器的硬件根據運算結果自動管理的

?

中斷允許標志位 (Interrupt Enable Flag):關中斷指令CLI可將IF置0,之后CPU不會響應任何來自外設或者接口的中斷請求。開中斷指令STL可將IF置1

方向標志位 (Direction Flag(Strings) ):CLD可將DF清0,串操作指令在重復執行的時候就會從小地址向大地址的方向訪問數組。STD可將DF置1,串操作指令訪問數組時會從大地址往小地址的方向訪問

陷阱標志位 (Trap-Single Step Flag):跟調試有關,單步跟蹤的時候可能用到。TF置1后CPU每執行完一條指令后就會在內部產生一個單步中斷,最終會跳轉到單步中斷所對應的中斷服務程序,即調試工具代碼的一部分

以上標志位有專門的指令進行管理,讓CPU工作在不同的狀態

?

?

?

8086的主存結構:

先看雙體結構:

8088的內存相對簡單,不分存儲體,只有一個8位的存儲體就夠了,接口也一樣,設計較簡單

?

8086把內存分為兩個存儲體,偶地址存儲體和奇地址存儲體,有各自的存儲體選擇信號以實現8位和16位傳送讀寫。偶地址存儲體的選擇信號如果是低電平有效的話,地址線最低位A0 ̄\overline{A_0}A0???????可當作偶地址存儲體的選擇信號。奇地址存儲體的選擇信號則有專門的引腳信號BHE ̄\overline{BHE}BHE?

給這兩個存儲體的都是字的地址,從A1 ̄\overline{A_1}A1??開始,A0 ̄\overline{A_0}A0?????理解成偶地址存儲體的選擇信號

?

要讀16位數據,會存在一次和分兩次的情況:

一次,

?

必須分兩次,

體現了數據對齊的重要性。16位數據在內存中占2個字節,我們就希望在內存里從偶地址開始存放,這樣一個總線周期就能完成讀寫

?

分段結構方式上面已經多次提到。注意各個分段之間可以重疊

6832H:1280H中6832H是段寄存器的內容,1280H是段內偏移

?

下面再看一些特殊的內存區域:

中斷向量區:00000H~003FFH (1KB),每個中斷向量占4個字節

顯示緩沖區:B0000H~B0F9FH (4000B),B8000H~BFFFFH (32KB)

啟動區:FFFF0H~FFFFFH (16B),內為無條件轉移指令,使啟動時跳轉到BIOS程序的起始地址

操作系統裝載在常規內存中

顯示緩沖區實例不要求

?

?

?

8086芯片引腳:

1.電源引腳

2.地址、數據線

考慮到不管是訪問內存還是訪問接口,都是先送地址然后再傳數據,Intel 把地址信號和數據信號復用以節省引腳,在設計電路時外面會增加一些輔助芯片來把復用的信號分離出來。即16位的數據和低16位的地址是復用的,高4位地址線和狀態信號復用

S6:廢用狀態,輸出一直是低電平

S5:表示當前IF的情況,看該引腳在輸出狀態時是輸出高電平還是低電平可知現在是開中斷還是關中斷

S3,S4:一共有4種組合,表示現在CPU正在使用哪一個段寄存器

3.時鐘、復位

CPU剛一加電之后,里面的內容是隨機的,當電源電壓穩定之后,在RESET引腳加大于4個時鐘周期寬度的正脈沖,就可以把CPU內部的CS置為全1,其他寄存器清0

8086的時鐘信號不是方波,高電平持續時間是低電平持續時間的12\frac1221???。外部的時鐘發生器芯片對一個方波進行三分頻

4.中斷

NMI:不可屏蔽中斷請求輸入引腳

INTR:可屏蔽中斷請求輸入引腳

INTA ̄\overline{INTA}INTA:中斷應答引腳

8086/8088 的計算機系統實現中斷時需要在外面增加一個可編程中斷控制器8259,該芯片可以管理8個中斷源,不夠用還可以多片級聯

x86處理器在管理中斷時,每一個中斷源都有1個8位二進制編碼的編號(中斷向量),所以x86處理器最多可以管理256個中斷源

有一些中斷源的編號是固定的,特別是來自CPU內部的中斷源,比如

0號中斷對應除法錯誤(除數為0,結果溢出)

1號中斷叫單步中斷。調試工具如果把TF置1,那么CPU每執行完一條機器指令之后都會在內部產生一個1號中斷,最終進入到單步中斷的中斷服務程序。那個程序就是調試軟件代碼的一部分

3號中斷叫斷點中斷,也是調試用的

4號中斷叫溢出中斷,一些補碼加法結果溢出

?

這些中斷究竟是怎么運作的?

比如CPU內部現在產生0號中斷,一旦中斷產生,CPU馬上獲取對應中斷向量,再根據中斷向量查找主存中的中斷向量表,讀出對應行的前2個字節賦值給IP,后面2個字節賦給CS,這2個寄存器合起來就相當于上學期講的程序計數器PC,被重新賦值后當然就會跳轉到0號中斷源對應的中斷服務程序執行

注意在賦值前必須要把IP和CS這兩個寄存器原來的內容保護在堆棧里,這叫斷點保護。響應中斷時,需要壓入IP,CS,PSW的內容,然后硬件自動把IF置0,再去查中斷向量表

中斷向量表有256行,行號從0~\sim??????255,每一行對應某一號中斷,占4個字節(前2個字節對應段內偏移,后2個字節是段寄存器的內容),存對應的中斷服務程序。表總共1KB,從內存地址0開始存放,在計算機啟動的過程中由BIOS程序負責初始化

CPU內部的中斷源還有一個,x86處理器的指令集里專門有一條軟中斷指令INT 21H ,21H是立即數,表示某中斷向量。編寫16位匯編語言程序時,經常需要調用DOS操作系統的一些功能,DOS操作系統就是利用軟中斷來給應用程序提供功能調用。上面這條指令在CPU內部一執行就會產生33(=21H)號中斷,對應的中斷服務程序是DOS操作系統代碼的一部分,其目的就是給用戶程序提供各種功能調用

?

以上是CPU內部的中斷源,然后再看來自外部的中斷請求,涉及到INTR和NMI

為什么這兩個一個叫可屏蔽一個叫不可屏蔽?

PSW中有IF,如果通過CLI把IF清0,它實際上就屏蔽來自INTR引腳的中斷請求,對其他的沒有任何影響,這個引腳的中斷請求其實就是來自接口或外設。而NMI不能通過IF屏蔽,通常是非常緊急的中斷請求,比如掉電

INTR和NMI還有一個區別,INTR輸入高電平有效,NMI輸入上升沿有效

?

INTR通過中斷控制器管理來自接口或者外設的好多個中斷源,中斷控制器通過中斷判優決定向CPU發送哪個中斷源的中斷請求。CPU當前指令執行完,并且處在開中斷狀態才會去響應中斷,通過INTA ̄\overline{INTA}INTA??????????發送第一個負脈沖告知中斷控制器其正在響應,同時要準備好中斷向量。接著發送第二個負脈沖,中斷控制器就把中斷向量送到低8位的數據總線上傳給CPU

5.最小模式/最大模式

24~\sim?31號引腳最小模式下是括號里的功能,最大模式下是括號外的功能

工作在最小模式下,所有的控制信號由8086直接產生,不需要再增加其他的外部芯片,電路規模通常較小,并且計算機系統里通常只有8086一個處理器

工作在最大模式下,那些控制信號就不是由這些引腳直接產生的了,需要外面增加一個別的芯片,比如總線控制器8288芯片來產生內存讀寫,接口讀寫有關的控制信號。由省出來的一部分引腳可以多一些狀態信號和DMA相關的信號,這樣整個計算機系統里還可以接更多的主控設備,包括其他的協處理器之類

BHE ̄\overline{BHE}BHE? :上面提過

S7:廢用狀態

TEST ̄\overline{TEST}TEST??????:輸入引腳,8086如果正在執行WAIT指令,該指令會判斷該引腳的狀態,如果是高電平這條指令就一直等待,如果是低電平,這個指令就執行完了。該指令主要用來和數學協處理器8087同步

READY:輸入引腳,講時序時再說

?

?

?

8086在最小模式下的引腳:

INTA ̄\overline{INTA}INTA?:上面提過

RD ̄,WR ̄\overline{RD},\overline{WR}RD,WR:讀內存讀接口都可以用到,通過M/IO ̄M/\overline{IO}M/IO 來區分是訪問內存還是接口

ALE:地址鎖存。地址信號要么和數據線,要么和狀態復用,那怎么知道什么時候輸出的是地址呢?

一旦8086正在輸出地址,并且地址是穩定的,8086會通過該引腳送來正脈沖。它輸出為高電平時,復用的信號正在輸出地址

DEN ̄\overline{DEN}DEN???:輸出允許。低電平表示正在傳遞數據

DT/R ̄\overline{R}R?:方向控制。高電平表示數據傳輸的方向是發送(從CPU內到CPU外),低電平表示數據傳輸的方向是接收

HOLD,HLDA:和DMA有關。DMA控制器如果想直接控制總線實現內存和外設之間的數據傳送,就要求8086釋放總線的控制權。DMA控制器會首先通過HOLD引腳給8086發高電平,若滿足一定條件,8086就通過HLDA告知DMA自己已釋放總線控制權

?

8088和8086的外部引腳的區別在:

1.8088只有低8位地址和數據復用

2.只有一個存儲體,不需要BHE ̄\overline{BHE}BHE,故34號引腳就是一個基本不用的狀態信號

3.28號引腳是IO/M ̄IO/\overline{M}IO/M?,剛好和8086相反

?

最后結合時序來講一下READY引腳,以8088的一個總線周期(總線周期由時鐘周期組成)為例:

?

上圖一個總線周期傳了一個數據,花了4個時鐘周期的時間。該時序有一個前提條件:內存的速度足夠快,讓CPU等一個時鐘周期(T3周期),內存就能把數據準備好。如果內存比較慢,CPU等一個時鐘周期內存還來不及把選中單元的數據取出來放在數據總線上,希望CPU多等幾個時鐘周期,就要用到READY信號

?

?

T3周期時會判斷READY信號的狀態,如果為高電平,則T3周期結束之后會直接進入T4周期。如果內存比較慢,則外面要有一個專門的電路,當CPU訪問內存時該電路必須要在T3周期之前把READY信號置0來通知CPU多等幾個周期,CPU在T3周期開始會采樣READY信號,發現是低電平則T3周期結束之后不會進入到T4周期而是插入等待周期TWT_WTW??

例題:

8086微處理器主頻為5MHZ,在不插入等待周期的情況下,從主存地址80006H讀一個8位數據所需要的時間為:

?

答案:800ns

?

然后講了下總線驅動的原理和重要性

?

?

8086在最小模式下的系統總線形成:

?

8086的引腳數有限,地址信號和其他信號是復用的,外面必須要增加一些電路以保存地址信號,在整個內存或接口讀寫的過程中地址由外加的電路來提供,這樣才能保證在一個總線周期的時間段內地址總是有效的

現在33號引腳接高電平,8086工作在最小模式下

要實現地址和其他信號的分離需要用到鎖存器,鎖存器有存儲功能,可以把在一個總線周期的第一個時鐘周期輸出的地址保存下來,然后在整個總線周期的時間段內由鎖存器來提供地址信號

地址信號一共21根線(20根地址線+BHE ̄\overline{BHE}BHE?????),如果用8位鎖存器74LS373,就要3片。鎖存器里存的內容希望能一直直接輸出,所以輸出允許OE ̄\overline{OE}OE????接地永遠有效。鎖存器的鎖存信號LE由ALE直接提供

在一個總線周期的第一個時鐘周期,當輸出地址并且地址穩定之后,ALE會輸出一個正脈沖

數據線AD0~AD15AD_{0}\sim AD_{15}AD0?AD15?不存地址的時候就當數據線用,直接引出來就是數據線。如果負載很多,數據線想加驅動器,用74LS245雙向驅動器。16位的數據,8位的74LS245要用2片,它有兩個控制信號,方向選擇DIR接DT/R ̄DT/\overline{R}DT/R,輸出允許OE ̄\overline{OE}OEDEN ̄\overline{DEN}DEN

然后剩下單向的控制信號線,如果想加驅動器用單向的74LS244,輸出允許OE1 ̄,OE2 ̄\overline{OE_1},\overline{OE_2}OE1??,OE2?????接地令其永遠有效。這4個信號經過它驅動之后后面可以帶很多的負載

CPU訪問內存和接口的時候最好能有各自獨立的讀寫信號,后面還可以加一些電路,借助數電的知識,這個附加電路的功能不難理解

時鐘發生器8284用來產生時鐘信號

上圖其實不是很嚴謹。READY信號應該由慢速的內存或者接口電路來產生,復位信號也不是由時鐘發生器而是由復位電路來產生,該低電平有效復位信號在8284里反相之后再做為8086的復位信號輸入

現在我們就有了地址,數據和控制信號,系統總線就形成了。各自存儲器芯片和接口芯片就可以直接連接到這些系統總線上

?

對8284工作原理的具體功能講解書上沒有

以8088為例,講了下更具體實際的電路下工作在最小模式下系統總線的形成,不太要求,了解即可

?

?

?

8086在最大模式下的引腳:

33號引腳接地,8086工作在最大模式下

此時所需要的控制信號,比如內存和接口讀寫,中斷應答信號都沒有,所以外面要多加一個總線控制器8288來產生這些信號

S2 ̄,S1 ̄,S0 ̄\overline{S_2},\overline{S_1},\overline{S_0}S2??,S1??,S0??

8288想從8086知道該產生什么控制信號需要三個狀態信號S0,S1,S2,這三根線8種組合分別代表CPU的8種不同狀態

Passive(被動):三根狀態線輸出111,表示CPU已經釋放總線了,它在總線上現在是一個從設備,處于完全被動的狀態?,F在總線的使用權可能是DMA控制器或者是其他的協處理器

教材的表格里翻譯成”無效“

?

QS0 ̄,QS1 ̄\overline{QS0},\overline{QS1}QS0?,QS1?:四種組合,表示當前指令隊列的情況。一般情況下用不到

LOCK ̄\overline{LOCK}LOCK??????:有些時候希望某條指令在執行時不要釋放總線,可以在這條指令前加lock前綴。這條指令在執行時該引腳輸出低電平,表示現在處于總線封鎖狀態

RQ ̄/GT0 ̄,RQ ̄/GT1 ̄\overline{RQ}/\overline{GT0},\overline{RQ}/\overline{GT1}RQ?/GT0,RQ?/GT1?????????????:跟最小模式下的HOLD,HLDA功能類似?。一個引腳是雙向的,既可以當HOLD也可以當HLDA來用。如果DMA控制器想要申請總線的控制權,通過該引腳發一個負脈沖,CPU如果釋放總線會通過相同的引腳再往外送一個負脈沖告知DMA控制器

?

總結一下,最大模式下:

1.可以接更多可以成為總線主控設備的東西,包括DMA控制器,協處理器之類

2.結合8288芯片可以產生更多的控制信號,可以實現更大規模的計算機系統

?

?

?

8086在最大模式下的系統總線形成:

?

最大模式下CPU不直接提供ALE,DT/R ̄,DEN ̄DT/\overline{R},\overline{DEN}DT/RDEN????,這些信號由總線控制器8288產生

注意8288產生的是DEN, 要加反相器

8288芯片產生的控制信號有嚴格的時序關系,也應有一個時間上的基準,它的時鐘信號和CPU用的是同一個。8288本身驅動能力很強,故這些輸出的控制信號后面不需要再加驅動,可直接引出作為系統總線的控制信號

以8088為例,講了下更具體實際的電路下工作在最大模式下系統總線的形成,不太要求,了解即可

?

Intel 處理器體系結構的發展

基本沒講,就舉了個書上沒有的宏融合技術的例子

?

Intel 處理器指令系統及匯編語言

匯編語言基礎(一)

為什么要學習匯編語言:

嵌入式系統:在特定硬件下,對程序的大小和運行速度需要高速優化的情況

BIOS程序的設計者,操作系統內核、設備驅動程序的設計者,編譯程序、調試工具的設計者、硬件檢測/測試/診斷程序的設計者、虛擬機/模擬器的設計者

逆向工程

有助于對計算機硬件、操作系統、應用程序之間交互的整體理解

突破高級語言的局限:高級語言中嵌入匯編

?

?

匯編語言格式主要有Intel和AT&T,上課用的Intel格式,編譯程序用微軟的宏匯編 (MASM)

先以模板程序Hello world為例,大致看下基于8086的16位匯編的整體結構和具體編寫方法:

?

?

?

?

段名:標識段的名字,唯一的或已存在的,可以隨便起

對齊方式:可以是BYTE、WORD、DWORD、PARA(16B對齊,不寫默認)、PAGE(256B對齊)

組合方式:可以是PRIVATE(不寫默認)、PUBIC、MEMORY,STACK、COMMON、AT地址。定義堆棧段時通常寫STACK,告訴編譯程序這個段當堆棧來處理

?

?

堆棧段定義了一個100B的空間。db偽指令表示現在要申請以字節為單位的數據塊,字節數為100。后面跟dup關鍵字和一個括號,如果這100B都想初始化為0,括號里就填0,括號里填 ? 編譯之后這100B仍然被初始化為0

偽指令編譯之后不會產生機器指令,它就是給編譯程序一些信息

?

數據段定義了一個字符串,message就是一個用符號表示的內存地址,本質上就是段內偏移,指向所定義的數據的起始位置,這樣在程序中引用字符串就不用直接引用邏輯地址。字符串以字節為單位,還是用db定義。0dh和0ah分別是回車符和換行符,‘$’ 是字符串的結束標識

?

assume偽指令并不能實現對CS,DS,SS三個段寄存器的賦值。有些代碼需要算地址,比如 mov dx,offset message,offset操作符取message地址的16位段內偏移,而編譯程序需要知道默認的段寄存器DS對應的是你自己定義的哪個段才能算段內偏移。assume偽指令告訴編譯程序編譯后面代碼時要認為此時CS,DS,SS已分別指向了你自己定義的代碼段,數據段,堆棧段

第一條指令必須要給它一個標號,整個程序總的結尾END偽指令跟這個標號,以指明主程序的入口點

接下來初始化數據段寄存器,引用段名把data段起始地址的高16位傳送到通用寄存器AX,再傳送到DS。這樣DS就真正指向了你自己定義的數據段

代碼段寄存器和堆棧段寄存器不需要程序初始化,由操作系統負責初始化。操作系統把數據段指向了別的位置,這個寄存器必須要由程序來初始化

data,offset message經過編譯之后實際上是立即數7和0,以后再解釋

接下來3條指令調用DOS操作系統的功能,負責把定義的字符串顯示到屏幕上

DOS操作系統通過 int 21h 軟中斷指令來給應用程序提供功能調用,執行這條指令之前必須要把功能號放在AH。9號功能就是往屏幕上顯示一條字符串,要求段寄存器DS和存段內偏移的DX共同指向要顯示的字符串的起始位置。故offset操作符取message地址的16位段內偏移傳送到DX寄存器,再執行軟中斷指令顯示字符串

不加offset操作符傳送的是內容而不是地址

最后調用DOS操作系統 int 21h 的4C號功能結束當前進程,回收其占用的內存空間

?

?

以后編寫匯編語言程序時就可以參考這個模板來寫

;1) 完整段定義的程序結構STACK SEGMENT PARA STACK 'STACK'DB 500 DUP(0) STACK ENDS DATA SEGMENT....... DATA ENDS CODE SEGMENTASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK START:MOV AX,DATAMOV DS,AX.......MOV AH,4CHINT 21H CODE ENDSEND START

MASM的高版本還支持簡化段定義的寫法

;2) 簡化段定義的程序結構.MODEL SMALL ;存儲模型:小型,16位匯編 .STACK 100H ;定義堆棧段及其大小 .DATA ;定義數據段 ....... ;數據聲明 .CODE ;定義代碼段START: ;起始執行地址標號MOV AX,@DATA ;數據段地址MOV DS,AX ;存入數據段寄存器....... ;具體程序代碼MOV AH,4CH INT 21HEND START ;程序結束

然后現場演示運行了下Hello world程序

?

?

編譯、鏈接和運行程序

用UltraEdit軟件打開Hellp.exe,對其結構進行了簡單的分析

注意x86處理器數據采用小端存儲

用二進制查看軟件打開可執行文件Hello.exe。后半部分和源程序內容有對應關系,前半部分是DOS操作系統下可執行文件的文件頭,有一些固定的格式,如微軟的操作系統下可執行文件的一個標志就是前兩個字節固定為"4D 5A"

文件頭是編譯程序生成的,會記錄DOS操作系統在執行該可執行文件之前這些寄存器的初值怎么設置。操作系統從磁盤把這個可執行文件往內存裝時,會分析利用文件頭的一些信息,分析完之后可能就會丟棄文件頭。編譯程序用的地址是邏輯地址,它總認為地址是從0開始的,所以他會認為你定義的堆棧段是從地址0開始的,相對應的代碼段就從0080開始,段的起始地址高16位是0008,故CS的初值應為0008。程序的入口點就是代碼段的第一條指令,段內偏移是0,故IP的初值是0000。堆棧段從邏輯地址0開始,故SS的初值應為0。SP的初值為0064,跟x86處理器對堆棧的管理方式有關系

x86處理器棧頂是小地址,棧底是大地址。16位模式下堆棧里的每個數據必須都是16位,占2個字節2個地址。該程序定義堆棧時申請了100B的堆??臻g,邏輯地址從0開始。x86處理器SP永遠指向棧頂上的有用元素,程序剛開始運行堆棧是空的,SP指向邏輯地址100 (64h)

文件頭記錄了堆棧段和代碼段寄存器的初值,但沒有記錄數據段寄存器的初值。DOS操作系統裝載可執行文件之后,DS另作他用,指向用于記錄命令行參數的數據結構程序段前綴PSP,故數據段寄存器得由代碼段里的指令初始化,令其指向自己所定義的數據段

?

將代碼段編譯之后產生的這些機器碼用反匯編工具轉化成匯編語言的形式。代碼段的前3個字節對應的是MOV AX,7,把立即數7傳送到AX。目標寄存器AX16位,故立即數7也用2字節16位來存儲,編譯的機器碼3個字節后2個字節存儲立即數7,第1個字節存的是該指令的操作碼還有AX寄存器的3位編號。后面的也類似

把反匯編的結果跟源代碼比較,可以發現mov ax,data中定義的數據段名稱編譯后變成立即數7,對應數據段起始地址的高16位。這條語句經過編譯程序編譯后產生的機器指令是把立即數7傳送到AX。類似的還有mov dx,offset message

?

操作系統不可能把這個程序從內存地址0開始裝,操作系統從磁盤把該可執行文件讀出來之后會檢查足夠大的內存空閑區域裝入,裝完后這些段寄存器應該怎么賦初值呢?

比如說堆棧段寄存器,它首先查文件頭,文件頭里規定的初值為0,在0的基礎上再加上起始的地址的段寄存器的內容,初始化代碼段寄存器也類似。數據段寄存器的初值文件頭里并沒有規定,操作系統在裝載這個程序到內存,起始地址確定之后需要修改代碼段。文件頭中有重定位項,該程序只有1個重定位項,這2個字節相當于指針,指向文件頭的另外一個位置,從該位置開始的2個16位字分別代表段內偏移和段起始地址的高16位,它們共同指向代碼段中需要重定位的地方

?

8086的內存管理引入分段機制,第一個目的是為了擴大可尋址的范圍,第二個目的是能夠實現程序在內存的任意位置浮動,一個程序在內存里任何一個地址開始裝,只需要重新初始化段寄存器的內容

?

然后驗證了一下可執行文件的具體格式

?

接下來再看32位的Hello world匯編程序,沒有用到通用寄存器,只是2個函數調用

32位應該是不要求的,但是后面講課時涉及的比較多,所以這里簡單記一下

.386 ;告訴編譯程序要產生32位的機器指令 .model flat,stdcall ;定義內存模型,如果這段程序要運行在Windows操作系統下,必須用flat平坦型。平坦的內存模型理解成只分頁不分段 ;函數調用參數傳遞的順序置為stdcall,通過堆棧向函數傳遞參數;利用Windows給應用程序提供的2個函數(子程序),這2個函數在代碼里并沒有,用之前需要聲明原型,比如函數的名稱,函數的參數和參數類型 ;DOS操作系統通過軟中斷給應用程序提供功能調用,Windows通過函數API的形式給應用程序提供功能調用MessageBoxA PROTO, ; 匯編里用PROTO偽指令聲明函數原型 hWnd:DWORD, ; 句柄,指向該窗口所屬的父窗口,沒有父窗口該參數給0lpText:PTR BYTE, ; 指針,指向一個要在窗口內部顯示的字符串lpCaption:PTR BYTE ; 指針,指向一個要顯示在窗口標題欄上的字符串style:DWORD ; 調用時給0,顯示一個最簡單的窗口,只有確定按鈕ExitProcess PROTO,exitCode:DWORD ; 如果程序正常結束,給參數0.data szCaption db 'A MessageBox !',0 szText db 'Hello, World !',0 .code ;4個壓棧指令傳參分別對應style,lpCaption,lpText,hwnd start: push 0 ; MB_OKpush offset szCaption push offset szTextpush 0 ; NULLcall MessageBoxA ; 顯示一個窗口push 0call ExitProcess ; 結束當前進程 end start

然后看了一下該程序編譯、鏈接、運行的過程

?

Intel微處理器的組成結構

部分32位x86處理器的內部寄存器

增加的段寄存器FS和GS也是用來訪問數據的,訪問數據時默認的段寄存器仍是DS。32位匯編里普通應用程序沒有權限修改段寄存器的內容,所以也不用太關心

?

通用寄存器主要用于算術運算和數據傳送

每個寄存器可作32位或16位使用。一些16位的寄存器也可以作為兩個單獨的8位使用,其余通用寄存器的低16位有獨立的名字,但不能進一步細分

?

EAX, EBX, ECX, EDX : 高16位不能單獨使用,低16位可以單獨使用,目的是為了和8086兼容

ESI, EDI, EBP, ESP : 下面列出的16位寄存器通常只在編寫運行于實地址模式下的程序時才使用,即編寫32位匯編,必須得用32位。編寫16位匯編,必須得用16位

?

?

匯編語言基礎(二)

匯編語言的基本元素

1.算術運算符號

匯編語言里面的表達式最終得到的就是一個立即數。如mov AL 15/5*2,這條語句編譯之后并不會產生除法指令和乘法指令,編譯程序會計算表達式,產生機器指令把立即數6傳送到AL寄存器

?

2.標識符

程序員選擇的名字,用來識別變量、常量、過程或代碼標號

這個標識符本質上就是一個用符號表示的內存地址

  • 可包含1~247個字符
  • 大小寫不敏感。(匯編器加“-cp”參數則大小寫敏感)
  • 第一個字符必須是字母(A~Z和a~z)、下劃線(_)、@、? 或 $,后續字符可以是數字
  • 不能與保留字相同
  • 盡量避免用 “@” 和 “_” 作為第一個字符,因為它們即用于匯編器,也用于高級語言編譯器

?

3.指令

程序被加載至內存開始運行后,由處理器執行的語句

?

4.定義數據

?

?

.data value1 BYTE 10h value2 BYTE ? list1 BYTE 10,20,30,40BYTE 50,60,70,80 list2 BYTE 32,41h,00100010b,'a' greeting BYTE "Good afternoon",0dh,0ah,0 array WORD 5 DUP(?) ;五個未初始化的值 value3 DWORD 12345678h

?

PTR操作符

Intel處理器采用小端存儲方式

.data myDouble DWORD 12345678h .code mov ax,myDouble ;錯誤 mov ax,WORD PTR myDouble ;ax = 5678h mov ax,WORD PTR [myDouble+2] ;ax = 1234h mov bl,BYTE PTR myDouble ;bl = 78h

?

5.符號常量

不是變量,不占用任何實際的存儲空間。常量的定義語句編譯之后不會產生任何機器指令,也不會產生任何數據

  • 等號偽指令

    COUNT = 500 ;給編譯程序傳達一個信息,告訴它后面不想直接寫500,用COUNT來代替 .data ...... array WORD COUNT DUP(0) ...... .code......mov cx,COUNT ;產生的機器指令把500立即數傳送到cx寄存器 L1: ............loop L1......
  • EQU偽指令

  • TEXTEQU偽指令

?

;計算數組和字符串的大小 list1 BYTE 10,20,30,40 List1Size = ($-list1) ;數組元素所占的字節數。微軟的宏匯編語法中,'$'代表當前語句的地址myString BYTE "This is a long string,"BYTE " Containing any number"BYTE " of characters",0dh,0ah MyString_len = ($ - myString) ;字符串占的字節數,也就是字符串里字符的個數list2 WORD 1000h,2000h,3000h,4000h ;注意數組元素的類型是WORD,16位占2個字節2個地址 List2Size = ($ - list2)/2

?

數據傳送、尋址和算術運算

數據傳送指令

1.MOV指令

MOV指令需要遵循的規則:

  • 兩個操作數的尺寸必須一致

    .DATA VAR1 WORD 30 VAR2 WORD 50 .CODE......MOV AL,VAR1 ;×MOV DX,AL ;×
  • 兩個操作數不能同時為內存操作數,要通過一個通用寄存器作為中介

    MOV VAR2 VAR1 ;×
  • 目的操作數不能是CS,EIP和IP,想改這幾個寄存器的內容另有專門的指令

  • 立即數不能直接送至段寄存器

    MOV DS,7 ;× MOV DS,@DATA ;×,編譯之后產生的是一個立即數

?

MOV指令格式:

mov reg,reg mov mem,reg mov reg,mem mov mem,imm mov reg,imm

reg --> 寄存器,mem --> 內存變量,imm --> 立即數

x86處理器其他的兩個操作數指令,其實就是支持類似這幾種格式

?

內存之間的移動通過寄存器暫存

.data var1 WORD ? var2 WORD ? .code mov ax,var1 mov var2,ax

?

2.XCHG指令

含義:exchange data,交換兩個操作數的內容

格式:

xchg reg,reg xchg reg,mem xchg mem,reg

?

交換兩個內存操作數:利用寄存器,MOV與XCHG結合使用

mov ax,val1 xchg ax,val2 mov val1 ax

?

RISC結構的處理器沒有這樣的指令,要實現xchg ax,bx這樣兩個寄存器之間的交換,可以有好幾種方法:

;方法一:用另外一個寄存器作為中介 mov cx,ax mov ax,bx mov bx,cx;方法二:通過堆棧 push ax mov ax,bx pop bx;方法三:用異或指令 xor ax,bx xor bx,ax xor ax,bx

?

?

直接偏移操作數(直接尋址)

MOV AL 7 ;把立即數7傳送到AL寄存器

這條指令源操作數是立即數,立即尋址。目的操作數寫的是寄存器的助記符,經過編譯之后產生的機器指令里面存的是這個寄存器的編號,寄存器尋址

要訪問的數據在內存里面,指令中直接給出內存地址,這樣叫直接尋址。我們在寫匯編程序時想直接尋址,后面直接給內存地址太不直觀,還得數究竟它放的邏輯地址是什么,這本來是可以交給編譯程序來做的。所以在定義數據段里那些變量的時候要給變量起名字,用這個名字來表示內存地址,這本質上也屬于直接尋址

變量、數組、字符串、子程序的名字在本質上來講都是一個用符號來表示的內存地址

.data arrayB BYTE 10h,20h,30h,40h,50h ;arrayB這個符號本質上來講就是數組的首地址(邏輯地址),或者說數組第0個元素的地址 .code mov al,arrayB ; AL=10h ;在代碼段里直接引用這個符號地址,它指向數組的第0個元素,把第0個元素傳送到AL寄存器,屬于直接尋址mov al,[arrayB+1] ; AL=20h ;第一個元素。編譯程序完成首地址+偏移量的加法,結果就是一個邏輯地址,仍屬于直接尋址 ;MASM并不要求一定要使用方括號 mov al,[arrayB+2] ; AL=30hmov al,[arrayB+20] ; AL=?? ;匯編語言不管是編譯程序還是執行時,DOS操作系統都不會做數組的越界檢查 ;字和雙字數組 .data arrayW WORD 100h,200h,300h .code mov ax,arrayW ; AX=100h mov ax,[arrayW+2] ; AX=200h 字占2個字節2個地址,數組首地址基礎上+2指向數組第一個元素.data arrayD DWORD 10000h,20000h .code mov eax,arrayD ; EAX=10000h mov eax,[arrayD+4] ; EAX=20000h 雙字32位占4個字節4個地址

?

常用的算術運算類指令

1.ADD指令

將同尺寸的源操作數和目的操作數相加,結果在目的操作數中(不改變源操作數)

格式:同MOV指令,add 目的操作數 源操作數

.data var1 DWORD 10000h var2 DWORD 20000h .code mov eax,var1 add eax,var2 ;30000h

?

2.SUB指令

將源操作數從目的操作數中減掉,結果在目的操作數中(不改變源操作數)

格式:與MOV、ADD指令相同,sub 目的操作數 源操作數

.data var1 DWORD 30000h var2 DWORD 10000h .code mov eax,var1 sub eax,var2 ;20000h

影響的標志位:CF、ZF、SF、OF、AF、PF

?

3.NEG指令

含義:negate, 求負

該指令認為操作數為一個有符號數,是補碼。將操作數按位取反、末位加1

格式:

neg reg meg mem

影響的標志位:CF、ZF、SF、OF、AF、PF

?

;例子:實現算術表達式 Rval = -Xval + (Yval-Zval).data Rval SDWORD ? ;微軟宏匯編高版本新引入的變量類型SDWORD,有符號的32位整數,理解成32位補碼 Xval SDWORD 26 Yval SDWORD 30 Zval SDWORD 40 .code mov eax,Xval neg eax ; EAX = -26 mov ebx,Yval sub ebx,Zval ; EBX = -10 add eax,ebx mov Rval,eax ; -36

?

算術運算影響的標志

1.零標志位

mov cx,1 sub cx,1 ; ZF = 1 mov ax,0FFFFh ; 全1理解成補碼,真值就是-1 inc ax ; ZF = 1 inc ax ; ZF = 0

?

2.符號標志位

mov cx,0 sub cx,1 ; SF = 1 add cx,2 ; SF = 0

?

3.進位標志位

INC和DEC指令不影響進位標志

mov al,0FFh add al,1 ; CF = 1mov ax,00FFh add ax,1 ; CF = 0mov ax,0FFFFh add ax,1 ; CF = 1mov al,1 sub al,2 ; CF = 1。最高位向更高位有進位或借位時置1

?

4.溢出標志位

OF=Cn⊕Cn?1OF=C_n\oplus C_{n-1}OF=Cn?Cn?1?。其中CnC_nCn?為符號位產生的進位,即標志位CFCFCFCn?1C_{n-1}Cn?1?為最高有效位向符號位產生的進位

mov al,+127 add al,1 ; OF = 1mov al,-128 sub al,1 ; OF = 1mov al,-128 ; AL = 10000000b neg al ; AL = 10000000b, OF = 1mov al,+127 ; AL = 01111111b neg al ; AL = 10000001b, OF = 1。

?

CPU如何知道一個數字是有符號的還是無符號的?

CPU并不知道——只有程序員才知道。CPU在執行指令之后機械地設置各種狀態標志,它并不知道那些對程序員是重要的,程序員自己來選擇哪些標志和忽略哪些標志

?

;例子程序(AddSub3).386 .MODEL flat, stdcall .STACK 4096 ExitProcess PROTO,dwExitCode:DWORD ;PROTO偽指令左側跟函數的名字,右側是函數的參數和參數類型.data Rval SDWORD ? Xval SDWORD 26 Yval SDWORD 30 Zval SDWORD 40 .code main PROC ;"主程序的名稱 PROC"開始,"相同的名稱 ENDP"作為結尾;主程序的名稱可以隨便起,本質是一個用符號表示的內存地址,它所定義的就是這個代碼段 ;的第一條指令的地址,是程序的入口點mov ax,1000h ; INC and DECinc ax ; 1001hdec ax ; 1000h; Expression: Rval = -Xval + (Yval - Zval)mov eax,Xvalneg eax ; EAX = -26mov ebx,Yval sub ebx,Zval ; EBX = -10add eax,ebxmov Rval,eax ; -36; Zero flag example:mov cx,1sub cx,1 ; ZF = 1mov ax,0FFFFh inc ax ; ZF = 1; Sign flag example:mov cx,0sub cx,1 ; SF = 1mov ax,7FFFh add ax,2 ; SF = 1; Carry flag examplemov al,0FFhadd al,1 ; CF = 1, AL = 00; Overflow flag examplemov al,+127 add al,1 ; OF = 1mov al,-128sub al,1 ; OF = 1INVOKE ExitProcess,0 ;32位的匯編最后都要調用操作系統結束當前進程的函數,該函數調用前要聲明原型;引入INVOKE偽指令使帶參數的函數在調用的時候可以一行寫完,后面跟函數名和參數main ENDP END main

然后用Visual Studio演示了一下運行該程序

?

間接尋址

1.間接操作數(寄存器間接尋址)

把指針寄存器外加中括號。它其實就是一個指針,指向內存的某一個位置

;32位匯編:三個雙字相加.data arrayD DWORD 10000h,20000h,30000h .code mov esi,OFFSET arrayD ;OFFSET操作符取數組的首地址傳送到指針寄存器,引用數組名,數組名本質上是數組的首地址;指針寄存器里存的是32位的段內偏移,默認的段寄存器仍然是數據段寄存器DS,DS里存的是段表的行號,該指令執行時會根據DS的內容查段表對應的行,從該行得到段的起始地址。段的起始地址加指針寄存器的段內偏移,結果就是內存地址,然后訪問內存中的數組元素;代碼段并沒有初始化數據段寄存器,在32位保護模式下只有最高特權級的代碼,如操作系統內核才有權限修改段寄存器的內容,普通的應用程序運行在最低特權級3下沒有權限修改段寄存器的內容的;16位的匯編段寄存器要由程序自己管理mov eax,[esi] ;寄存器間接尋址,訪問數組的第0個元素add esi,4 ;數組元素32位占4個字節,指針+4指向數組的第1個元素 add eax,[esi] add esi,4 add eax,[esi] ;16位匯編:三個字相加.data arrayW WORD 1000h,2000h,3000h .code mov ax,@data        mov ds,ax ;初始化數據段寄存器mov si,OFFSET arrayW ;OFFSET操作符取數組首地址,或者叫16位的段內偏移傳送到指針寄存器mov ax,[si] ;默認的段寄存器還是數據段寄存器,把數據段寄存器的內容段起始地址的高16位讀出,末尾添4個0構成20位的段起始地址,再加上指針寄存器里的16位段內偏移,結果為20位的內存地址。訪問內存剛好對應數組的第0個元素,從這個地址開始連續傳送2個字節至AXadd si,2 add ax,[si] add si,2 add ax,[si]

?

間接操作數可以是任何用方括號括起來的32位通用寄存器(EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP)。實地址模式下只能用SI,DI,BX,BP。通常盡量避免使用BP(BP默認的段寄存器是SS,常用來尋址堆棧而不是數據段)

?

PTR與間接操作數的聯合使用

inc [esi] ; error: operand must have size. +1指令只有一個操作數,并且還是一個指針,指向一個內存位置,不知道存的是8位還是16位,32位inc BYTE PTR [esi] ; 認為是8位數據

?

2.變址操作數(寄存器相對尋址)

.data arrayB BYTE 10h,20h,30h .code mov esi,0 ; 要訪問的數組元素編號作為偏移量放在指針寄存器 mov al,[arrayB + esi] ; AL = 10h mov al,arrayB[esi] ; 同上另一種格式 mov esi,OFFSET arrayB mov al,[esi] ; AL = 10h mov al,[esi+1] ; AL = 20h mov al,[esi+2] ; AL = 30h

?

實模式下只能使用SI,DI,BX,BP寄存器。(盡量避免使用BP寄存器)

?

?

JMP和LOOP指令

1.JMP指令

top:...jmp top ;repeat the endless loop

?

2.LOOP指令

格式:LOOP 目的地址

LOOP指令的執行:

在實地址模式下,用做默認循環計數器的是CX而不是ECX

?

mov ax,0mov ecx,5 L1: inc ax loop L1 ;循環體的第一條指令必須要給標號。循環體的最后一條指令要用loop,后面跟這個標號;循環結束時,AX=5 ECX=0

?

循環的嵌套

.data count DWORD ? .codemov ecx,100 L1: push ecx ; 將循環計數器的內容,即外層循環的當前次數保存mov ecx,20 ; 重新設置循環計數器的內容 L2: ..loop L2pop ecx ; 恢復循環計數器原來的內容 loop L1

?

;例子:整數數組求和; This program sums an array of words. (SumArray.asm) .386 .MODEL flat, stdcall .STACK 4096 ExitProcess PROTO,dwExitCode:DWORD .data intarray WORD 100h,200h,300h,400h .code main PROCmov edi,OFFSET intarray ; address of intarraymov ecx,LENGTHOF intarray ; loop countermov ax,0 ; zero the accumulator L1: add ax,[edi] ; add an integeradd edi,TYPE intarray ; point to next integerloop L1 ; repeat until ECX = 0INVOKE ExitProcess,0 main ENDP END main

?

;例子:拷貝字符串; This program copies a string. (Copystr.asm) .386 .MODEL flat, stdcall .STACK 4096 ExitProcess PROTO,dwExitCode:DWORD .data source BYTE "This is the source string",0 target BYTE SIZEOF source DUP(0) .code main PROCmov esi,0 ; index registermov esi,SIZEOF source ; loop counter L1: mov al,source[esi] ; get a character from sourcetarget[esi],al ; store it in the targetinc esi ; move to next characterloop L1 ; repeat for entire stringINVOKE ExitProcess,0 main ENDP END main

然后用Visual Studio演示了一下運行該程序

?

過程

與外部庫鏈接

鏈接庫如何工作?

假設程序要調用名為WriteString的過程在控制臺上顯示字符串,這個函數在另外一個庫里,并沒有在源代碼文件中,則:

1.程序中要用PROTO偽指令聲明要調用的程序

例:Irvine32.inc 中包含如下語句

WriteString PROTO

2.用一條CALL指令執行WriteString過程

call WriteString

3.當程序被編譯時,編譯器知道操作碼但不知道地址碼,因為這個函數的代碼不在當前文件中,它為CALL指令的目標地址留出空白,該空白將由鏈接器在鏈接時填充

4.鏈接器在鏈接庫中查找WriteString這個名字,從庫中提取函數代碼,跟編譯產生的目標文件鏈接到一起形成可執行文件,鏈接到一起之后這個函數的首地址邏輯地址才知道,再由鏈接器負責把WriteString的首地址填到CALL指令留的空白的位置

?

鏈接器的命令行選項

之前32位匯編的例子里結束當前程序要調用操作系統的函數,那個函數在kernel32.lib庫文件中

例:

Link32 HelloWin.obj user32.lib kernel32.lib/subsystem:windows

Windows下同一時刻可能有多個程序在運行,免不了要調用各種各樣Windows提供的函數,包括結束當前進程的函數,幾乎所有程序都要調用,每個程序里都會有很多這種重復的函數可執行代碼,實際上是沒有必要的,也浪費內存空間

所以實際在Windows系統里,這些庫文件里存的所謂的這些函數的代碼其實就是函數的鏈接而不是函數真正的代碼,可以理解成庫文件里跟那個函數所對應的代碼就是個跳轉指令,跳轉指令執行后才會真正地跳轉到那個函數的代碼去執行。那個函數的代碼包含在kernel32.dll動態鏈接庫文件中,重復的函數代碼在動態鏈接庫,在內存里只有一個副本

?

?

過程的定義和使用

1.過程的定義

子程序定義一般的結構:用PROC和ENDP偽指令來聲明,另外還必須給過程起一個名字(一個有效的標識符),中間寫代碼,代碼的最后一條指令必須得寫ret子程序返回指令

寫主程序的時候也可以用相同的結構來寫,主程序的結束如果是16位的匯編,通常調用DOS操作系統的4C號功能并且給操作系統返回0表示程序正常結束

如果是32位的匯編主程序結束一般結合INVOKE偽指令。INVOKE偽指令是微軟宏匯編6.0以上引入的,引入的目的就是為了帶參數的函數在調用的時候可以一行寫完,后面跟函數名和參數,多個參數用 ‘,’ 隔開

具體到這個例子,這條語句編譯之后會產生2條機器指令,首先會產生壓棧指令,把參數0壓入堆棧,然后再產生call指令調用子程序

?

2.例子:三個整數之和

SumOf PROCadd eax,ebxadd eax,ecxret SumOf ENDP

?

3.為過程添加文檔

;------------------------------------------------------------------- SumOf PROC ; ;Calculates and returns the sum of three 32-bit integers. ;Receivers: EAX, EBX, ECX, the three integers. May be ; signed or unsigned ;Returns: EAX = sum, and the status flags (Carry, ; Overflow, etc.) are changed. ;-------------------------------------------------------------------add eax,ebxadd eax,ecxret SumOf ENDP

?

4.向過程傳遞寄存器參數

.data theSum DWORD ? .code main PROCmov eax,10000h ; argumentmov ebx,20000h ; argumentmov ecx,30000h ; argumentcall Sumof ; EAX=(EAX+EBX+ECX)mov theSum,eax ; save the sum

?

例子:對整數數組求和

; ArraySum 過程:;------------------------------------------------------------------- ArraySum PROC ; ; Calculates the sum of an array of 32-bit integers ; Receives: ESI points to the array, ECX = array size ; Returns: EAX = sum of the array elements ;-------------------------------------------------------------------push esi ; save ESI, ECXpush ecxmov eax,0 ; set the sum to zero L1:add eax,[esi] ; add each integer to sumadd esi,4 ; point to next integerloop L1 ; repeat for array sizepop ecx ; restore ECX, ESIpop esiret ; sum is in EAX ArraySum ENDP ; 調用 ArraySum.data array DWORD 10000h,20000h,30000h,40000h,50000h theSum DWORD ? .code main PROC mov esi,OFFSET array ; ESI points to arraymov ecx,LENGTHOF array ; ECX = array countcall ArraySum ; calculate the summov theSum,eax ; return in EAX......

?

?

LEA DX,mess2和MOV DX,OFFSET mess2功能上等價,直接引用變量的名字,取該變量的地址而不是內容到DX寄存器。段內偏移放在DX寄存器,而段寄存器主程序已初始化好了

整個程序總的結尾用END跟這個程序的入口點,入口點應該是主程序的名字,本質上是主程序的第一條指令的地址。由于匯編語言用這種方式指明程序的入口點,所以寫的時候也可以把子程序寫在前面,主程序寫在后面

?

運行一下這個16位程序。在32位Windows下新建文本文件,后綴名改成.asm,打開把代碼粘貼進去。保存完之后再用最原始的方法在命令行方式下先后輸入編譯命令和鏈接命令,再輸入產生的可執行文件名字運行

會發現和想象的不太一樣,程序好像是個循環程序,循環到后面報錯了,程序被操作系統強行關閉。為什么會這樣?

問題出在子程序里面用壓棧指令保護現場,但是返回之前沒有出棧指令恢復現場,即返回指令之前少寫了POP DX

CALL指令執行的時候CPU首先會保護當前的斷點,把當前PC的內容壓入堆棧,8086的PC對應兩個寄存器CS和IP。這個程序CALL指令和RET指令默認都屬于靜調用和靜返回,靜調用和靜返回只需要保護IP,段寄存器的內容不需要保護,調用返回都是在同一個段里面。所以CALL指令執行時會首先把當前IP的內容壓入堆棧,它往堆棧里壓的這個地址應該是CALL指令順序的下一條指令的地址,再跳轉到子程序執行。子程序又會把DX原來的內容壓入堆棧,子程序返回指令會從堆棧段棧頂彈出數據到PC,對8086就是彈到IP,少寫POP指令會導致把一個錯的數彈到IP

OFFSET操作符取第一個字符串的首地址傳送到DX,第一個字符串是數據段里最開始定義的字符串,在它之前沒有任何東西,所以它的段內偏移應為0,DX的內容就是0。所以子程序執行到返回指令時,它會從堆棧里把0彈出賦值給IP。代碼段寄存器內容不變,但是段內偏移變為0,就會從主程序的第一條指令開始執行,所以會不停地來回循環,在屏幕上不停地顯示那兩條字符串

而且每調用一次子程序都在堆棧里留了一個數沒有彈出,棧只申請了256B的空間,增長到一定程度就會導致棧溢出,最終堆棧里的數據會覆蓋代碼段里的的指令,CPU再取指令譯碼發現是非法指令就產生中斷讓操作系統強行中止程序

?

條件處理

布爾和比較指令

1.AND指令

功能:在操作數的對應數據位之間執行布爾(位)”與“操作,并將結果保存在目的操作數中

格式:AND 目的操作數 源操作數

允許的操作數形式:

AND reg,reg AND reg,mem AND mem,reg AND reg,imm AND mem,imm

兩個操作數可以是8、16或32位的,但它們的尺寸必須相同

影響的標志位:

  • 總是清除OF和CF
  • 根據結果修改SF、ZF、PF

主要用途:

  • 對特定的位清”0“,同時保留其他的位

    mov al,00111011b mov al,00001111b
  • 大寫字母與小寫字母的ASCII碼之間的關系:

    ‘a’:61h,即 01100001

    ‘A’:41h,即 01000001

    ;例:將字符轉換為大寫形式.data array BYTE 50 DUP(?) .codemov ecx,LENGTHOF arraymov esi,OFFSET array L1:and byte ptr [esi],11011111binc esiloop L1

?

2.OR指令

功能:按位取”或“

格式:與AND指令相同

主要用途:

  • 對特定的位置置”1“,并保留其它位

    mov al,00111011b or al,00001111b

    例:將0到9之間的整數轉換成對應的ASCII碼數字

    方法:將位4和位5置為1

    mov dl,5 ; 二進制值 or dl,30h ; 轉換到ASCII碼

    要調用操作系統的功能在屏幕上顯示必須得以ASCII碼的形式

    也可以用add dl,30h或add dl,'0'

?

3.XOR指令

功能:按位取”異或“

格式:與AND及OR指令相同

XOR指令的用途:

  • 對某些位取反,同時不影響其他的位

    0跟一個數異或還是那個數,1跟一個數異或就是那個數的取反

  • 判斷16位或32位值的奇偶性

    mov ax,64C1h ; 0110 0100 1100 0001 xor ah,al ; PE,奇偶標志被設置

    奇偶標識位只反映運算結果低8位里1的個數是否是偶數個

  • 簡單數據加密

    將某個操作數與同樣的操作數執行兩次異或運算后,其值保持不變
    (X⊕Y)⊕Y=X(X\oplus Y)\oplus Y=X (XY)Y=X

4.NOT指令

功能:將操作數所有數據位取反,結果為反碼

格式:

NOT reg NOT mem

例:

mov al,11110000b not al ; AL = 00001111b

NOT指令不影響任何狀態標志

?

布爾和比較指令

1.TEST指令

功能:兩操作數按位“與”,根據結果設置標志位,但不回送結果(不修改目的操作數)

格式:與AND指令相同

用途:測試操作數的某一位是“0”還是“1”

例子:測試多個位

想知道AL中第0位、第3位是否同時為“0”

test al,00001001b ;test bits 0 and 3

判斷ZF是否等于1

影響的標志:清除OF、CF;修改SF、ZF、PF

?

2.CMP指令

格式:與AND指令相同。cmp 目的操作數 源操作數

功能:與減法指令一樣執行減法操作,即目的操作數-源操作數,但不回送結果,只影響標志位

影響的標志:根據相減結果修改OF、SF、ZF、CF、AF、PF

?

無符號操作數的比較:

有符號操作數的比較:

例:

mov ax,5 cmp ax,10 ; CF = 1mov si,105 cmp si,0 ; ZF=0,CF=0mov ax,1000 mov cx,1000 cmp cx,ax ; ZF = 1

?

條件跳轉

1.條件結構

條件分支的實現:

  • 使用CMP、TEST、AND之類的指令修改CPU標志
  • 使用條件跳轉指令測試標志值,以決定是否向新的分支轉移

例子:

cmp al,0jz L1 ;jump if ZF=1.. L1: and dl,10110000bjnz L2 ;jump if ZF=0.. L2:

?

2.跳轉指令的類型

mov al,7Fh ; (7Fh or +127) cmp al,80h ; (80h or -128) ja IsAbove ; no: 7F not > 80h jg IsGreater ; yes: +127 > -128

?

例:8位內存操作數status中存放著同接口卡相連的外設的狀態信息

1.bit5為“1”時外設處于脫機狀態,跳轉到某標號處

mov al,status test al.00100000b jnz EquipOffline

2.bit0、bit1、bit4任何一位為“1”時跳轉到某標號處

mov al,status test al,00010011b jnz InputDataByte

3.bit2、bit3、bit7全部為“1”時跳轉到某標號處

mov al,status and al,10001100b cmp al,10001100b jz ResetMachine

?

例:比較V1、V2、V3三個無符號變量的值,將最小值送入AX寄存器

.data V1 WORD 23 V2 WORD 0 V3 WORD -1 .codemov ax,V1 ;assume V1 is smallestcmp ax,V2 ;if ax <= V2 thenjbe L1 ; jump to L1mov ax,V2 ;else move V2 to ax L1: cmp ax,V3 ;if ax <= V3 thenjbe L2 ; jump to L2mov ax,V3 ;else move V3 to ax L2: ......

?

然后推薦了https://godbolt.org,可以直接輸入C語言代碼,即時查看反匯編結果

?

整數算數指令

移位 (Shifting) 指令:

記住以下單詞:Shift, Left, Right, Arithmetic, Rotate, Carry

  • SHL 邏輯左移

  • SHR 邏輯右移

  • SAL 算術左移

  • SAR 算術右移

  • ROL 循環左移

  • ROR 循環右移

  • RCL 帶進位的循環左移

  • RCR 帶進位的循環右移

上述移位指令影響OF、CF

?

1.SHL指令:邏輯左移

格式:SHL 目的操作數 移位位數

SHL reg,imm8 SHL mem,imm8 SHL reg,CL SHL mem,CL

8088/8086要求imm8必須等于1。80286以上,imm8可為任意整數

CL方式可用于任何Intel x86處理器

上述格式也適用于SHR、SAL、SAR、ROR、ROL、RCR、RCL指令

源操作數可以是立即數,如果是8088/8086,立即數只能是1。如果想左移多位,得把移位的次數先放到CL寄存器

?

例:無符號數與2的整數次冪做快速乘法

mov dl,5 shl dl,1 ;5*2 = 10 mob dl,10 shl dl,2 ;10*4 = 40

?

2.SAL指令:算術左移,與SHL指令等價

?

3.SHR指令:邏輯右移,最高位總是填0

格式:與SHL相同

?

例:無符號數與2的整數次冪做快速除法

mov dl,32 shr dl,1 ;32/2 = 16 mov dl,01000000b ;AL = 64 shr dl,3 ;64/8 = 8

?

4.SAR指令:算術右移,最高位填充原來的符號位

例1:

mov al,0F0h ; AL = 11110000b (-16) sar al,1 ; AL = 11111000b (-8); CF = 0

例2:有符號數的除法,-128/8=-16

mov dl,-128 ; DL = 10000000b sar dl,3 ; DL = 11110000b

?

5.ROL指令:循環左移

特點:不丟失任何數據位

?

例1:

mov al,40h ;01000000 rol al,1 ;10000000, CF=0 rol al,1 ;00000001, CF=1 rol al,1 ;00000010, CF=0

例2:將一個字節的低4位與高4位進行交換

mov al,26h rol al,4 ;AL = 62h

?

6.ROR指令:循環右移

例:

mov al,01h ;00000001 ror al,1 ;10000000, CF=1 ror al,1 ;01000000, CF=0

?

7.RCL和RCR

RCL指令:帶進位的循環左移

RCR指令:帶進位的循環右移

?

?

移位和循環移位的應用:

  • 多雙字移位

    在數據段里定義3個元素的數組,數組元素的類型是32位雙字,這3個元素連到一塊組成96位的數,小地址對應低位數據,大地址對應高位數據。希望將其整體邏輯右移1位

    移位時從高位開始移。邏輯右移最高位永遠填0,最低位移走到CF。中間的數再移位就可以把剛才高位移走的數從CF再移到這個數里面去

  • 二進制乘法:利用移位、相加實現

  • 顯示二進制位

  • 分離位串

    例:MS-DOS的功能57h在DX中返回文件的修改時間,假設為2019年3月10日,則DX中的文件日期戳如下(年份是相對于1980年的):

    提取月可以將這個數整體地邏輯右移5位,然后再用AND指令將高12位清0只保留低4位

?

乘法和除法指令

1.MUL指令

格式(操作數為乘數):操作數可以是寄存器也可以是內存變量,但不能是立即數。只跟一個操作數,另外一個操作數是隱含的或者說默認的

MUL r/m8 MUL r/m16 MUL r/m32

功能:無符號乘法。將8位、16位或32位的操作數與AL、AX或EAX相乘

乘數和被乘數位數必須相等。兩個8位數相乘運算結果用16位表示,兩個16位數相乘結果是32位,高16位在DX,低16位在AX。32位數相乘同理

作為高級語言來講,32位變量做各種運算后運算結果也會存到一個32位變量里面,但這實際上有溢出的可能,用匯編語言來寫可以更完備。兩個8位數相乘,運算結果用8位表示不了,CF會置1。16位數和32位數相乘同理

例:

mov al,5h mov bl,10h mul bl ; CF = 0 ; 積在AX中,50h .data val1 WORD 2000h val2 WORD 0100h .code mov ax,val1 mul val2 ; CF = 1 ; 積在DX:AX中,00200000h

?

2.IMUL指令

有符號乘法,格式與MUL指令相同。認為被乘數和乘數都是補碼,乘的結果也會用補碼來表示

如果積的高半部分不是低半部分的符號擴展,置CF和OF

例:

mov al,48 ; 48D = 30H mov bl,4 imul bl ; AX = 00C0h, OF = 1mov al,-4 mov bl,4 imul bl ; AX = FFF0h, OF = 0mov ax,48 mov bx,4 imul bx ; DX:AX = 000000C0h, OF = 0

?

3.DIV指令

無符號除法

格式(操作數為除法):

DIV r/m8 DIV r/m16 DIV r/m32

功能:執行8位、16位、32位無符號整數除法運算

除數是8位,被除數必須是16位,商跟余數也得是8位。除數是16位和32位同理

?

例:

; 8003h/100h mov dx,0 ; clear dividend, high mov ax,8003h ; dividend, low mov cx,100h ; divisor div cx ; AX = 0080h, DX = 0003h .data dividend QWORD 0000000800300020h divisor DWORD 00000100h .code mov edx,DWORD PTR dividend + 4 ; high doubleword mov eax,DWORD PTR dividend ; low doubleword div divisor ; EAX = 08003000h, EDX = 00000020h

?

除法運算指令可能溢出,乘法兩個n位數相乘運算結果用2n位表示肯定不會溢出。如:

mov Ax,1000H mov BL,10H DIV BL

結果商為100H,用8位寄存器AL無法表示,除法溢出在CPU內內部產生0號中斷

有符號數的除法運算指令為IDIV,下面幾個具體的例子會說到

?

例1:以匯編語言實現下面的C++語句(使用32位無符號整數):

var4 = (var1 + var2) * var3;

?

mov eax,var1add eax,var2mul var3 ; EAX = EAX * var3jc tooBig ; unsigned overflow?mov var4,eaxjmp next tooBig: ; display error message

?

?

例2:使用32位有符號整數實現下面C++語句:

var4 = (var1 * -5) / (-var2 % var3);

?

mov eax,var2 ; begin right side neg eax ;有符號數,需將被除數符號擴展到EDX,然后用IDIV指令 cdq ; sign-extend dividend idiv var3 ; EDX = remainder mov ebx,edx ; EBX = right sidemov eax,-5 ; begin left side imul var1 ; EDX:EAX = left sideidiv ebx ; final division mov var4,eax ; quotient

cdq 把EAX的最高位符號位擴展到EDX,x86還專門設計了類似的指令

cbw : 把AL寄存器里存的8位補碼擴展到16位,存到AX

cwd : 把AX寄存器里存的6位補碼擴展到32位。高16位存在DX,低16位存在AX

?

?

擴展加法和減法

思考:用C++如何實現兩個128位整數相加?

1.ADC:帶進位加

目的操作數+源操作數+進位標志→\to目的操作數

ADC reg,reg ADC mem,reg ADC reg,mem ADC mem,imm ADC reg,imm

?

2.SBB:帶進位減

目的操作數-源操作數-進位標志→\to目的操作數

?

利用上述指令可方便地實現任意大小數字的減加法運算

?

?

?

高級過程

高級語言如C語言的編譯器把參數傳遞給子程序需要借助堆棧,子程序如何把參數從堆棧里取出來?

?

堆棧框架

內存模式:.MODEL偽指令

例:

.MODEL flat,stdcall

保護模式程序使用平坦內存模式

?

STDCALL關鍵字:指定過程按照從右往左的順序壓入參數。例:

INVOKE ADDTwo,5,6

將生成如下匯編語言代碼:

push 6 push 5 call AddTwo

?

堆棧參數的顯式訪問:

.data sum DWORD ? .codepush 6 ; second argumentpush 5 ; first argumentcall AddTwo ; EAX = summov sum,eax ; save the sum...... AddTwo PROCpush ebp mov ebp,esp ; base of stack frame;把ESP的內容賦值給EBP,這樣EBP和ESP同時指向當前棧頂的位置。如果后面子程序里還有;PUSH,POP這樣對堆棧的操作只會影響ESP的內容,但EBP一旦賦值之后,在整個子程序范圍;內就不會再修改mov eax,[ebp + 12] ; second argumentadd eax,[ebp + 8] ; first argumentpop ebpret 8 ; clean up the stack;首先從堆棧中彈出棧頂元素至指令指針寄存器,然后把ESP的內容加上8,相當于把2個參數占;用的堆??臻g也釋放了 AddTwo ENDP

?

?

子程序中定義的這些臨時變量存儲在堆棧中。在操作系統的角度來講,我們在C語言里寫的這個主程序也是子程序,所以主程序里定義的這些變量其實也是臨時變量,也存儲在堆棧中。這種情況下堆棧應該如何管理?

在主程序之外定義的變量不在堆棧中

?

創建局部變量:

C++例子

void MySub() {char X = 'X';int Y = 10;char name[20];name[0] = 'B';double Z = 1.2; }

訪問這些變量都通過EBP相對尋址

為了對齊,盡管第一個變量X是8位數據,但實際上在堆棧里也會占用4個字節

?

用匯編語言實現

MySub PROCpush ebpmov ebp,espsub esp,36; create variablesmov BYTE PTR [ebp-4],'X' ; Xmov DWORD PTR [ebp-8],10 ; Ymov BYTE PTR [ebp-28],'B' ; name[0]mov DWORD PTR [ebp-32],3ff33333h ; Z(high)mov DWORD PTR [ebp-36],33333333h ; Z(low)…… ……mov esp,ebp ; destroy variablespop ebpret MySub ENDP

z采用IEEE754標準存儲

講了下緩沖區溢出攻擊,并解釋了在https://godbolt.org中查看該例子時存在的一些不同

?

字符串和數組

基本字符串操作指令

5組處理字節、字和雙字數組的指令,成為基本字符串指令,但用法并不限于處理字符串數組

MOV : 數據傳送類 S : 串操作指令 B, W, D : 數組元素的類型是字節,字,雙字

?

使用重復前綴

例:

main PROCmov ax,@data ;get addr of data segmov ds,ax ;initialize DSmov es,ax ;initialize ES cld ; clear direction flag mov si,OFFSET string1 ; SI points to source mov di,OFFSET string2 ; DI points to target mov cx,10 ; set counter to 10 rep movsb ; move 10 bytes

對于串操作指令。段寄存器必須用DS,指針寄存器必須用SI,這兩個寄存器指向源數組/源串。ES和DI指向目的數組/目的串

加了重復前綴rep后,這條指令會重復執行好多次,重復次數要放在CX/ECX。指令每執行一次首先會把CX/ECX的內容減1,如果不為0則重復執行這條指令。串操作指令從DS和SI指向的位置讀一個字節的數據然后把它寫入到ES和DI指向的位置。寫完了之后SI和DI的內容加還是減由方向標志位DF決定,DF=0則ESI、EDI自動增加,DF=1則ESI、EDI自動減少。加減多少取決于數組元素類型

數組元素的類型是字節,并且里面存的是ASCII碼,那就是字符串

方向標志可以通過CLD和STD指令改變:

CLD ; 清除方向標志 STD ; 設置方向標志

?

?

二維數組

1.基址變址操作數(基址+變址尋址)

基址變址 (base-index) 操作數:將兩個寄存器的值相加(稱為基址寄存器、變址寄存器)來產生偏移地址

保護模式程序中,可使用任意32位通用寄存器

實地址模式下,基址寄存器訪問數據段最好用BX(也可以用BP,但是BP一般是用來訪問堆棧的,它的段寄存器默認是SS)。變址寄存器可以用SI和DI

.data array WORD 1000h,2000h,3000h .codemov ebx,OFFSET arraymov esi,2 mov ax,[ebx+esi] ; AX = 2000h

?

表格的例子:

?

2.相對基址變址操作數(基址+變址+相對尋址)

相對基址變址操作數:有效地址偏移=偏移+基址寄存器+變址寄存器

幾種常見的格式:[base + index + displacement], displacement[base + index], displacement[base][index]

偏移 (displacement) : 變量的名字;常量表達式

基址、變址:保護模式為任意32位寄存器,實地址模式為BX、BP和SI、DI

?

表格的例子:

?

結構和宏

宏 (Macro)

命名的匯編語句塊。調用宏的時候,匯編語句塊的一份拷貝被直接插入到程序中

在程序代碼里要重復使用幾條指令,來來回回多次的寫會比較麻煩,就可以用宏來代替這幾條指令。在代碼里多次引用宏,編譯程序編譯到宏后會展開,用實際參數代替它的形式參數

宏的定義

macroname MACRO parameter-1,parameter-2...statement-list ENDM

?

例1:

?

?

?

使用I/O端口控制硬件

x86屬于獨立編址,要訪問接口地址空間只能用IN指令和OUT指令。不管是8086還是32位、64位的CPU,接口地址都是16位的,端口地址范圍為0~\sim?FFFFh

?

IN和OUT指令

IN指令:從端口輸入一個字節、字或雙字

OUT指令:向端口輸出一個字節、字或雙字

?

指令格式:

端口地址:0~\simFFh之間的一個常量(立即數),或是包含0~\sim?FFFFh之間的值的DX寄存器

累加器:AL、AX或EAX

in al,3Ch ; input byte from port 003Ch out 3Ch,al ; output byte to port 003Ch mov dx,2A3Ch ; DX can contain a port number in ax,dx ; input word from port named in DX out dx,ax ; output word to the same port in eax,dx ; input doubleword from port out dx,eax ; output doubleword to same port

?

然后講解了PC聲音程序和實時鐘RTC兩個例子,并現場演示了一下

?

32位/64位處理器擴展指令——多媒體/流媒體SIMD擴展指令集

多媒體擴展 (MMX) 指令集

SIMD : 單指令多數據 Single Instruction Multiple Data

Pentium Ⅱ : 引入MMX (Multiple Media Extensions) 指令集,實現64位并行處理。引入8個64位MMX寄存器mm0~\simmm7

Pentium Ⅲ : 引入SSE (Streaming SIMD Extensions) 指令集,實現128位并行浮點運算。引入8個128位MMX寄存器xmm0~\simxmm7

Pentium 4 : 引入SSE2指令集,實現128位并行定點運算

如果要處理的是32位數據,一個XXM寄存器可以存儲4個這樣的數據,1條SSE2指令可以同時處理4對操作數得到4個結果,這就是所謂的單指令流多數據流

?

SSE2指令集

SSE2數據類型

一個XXM寄存器可以存放4個單精度浮點數、2個雙精度浮點數、16個8位整數、8個16位整數、4個32位整數、2個64位整數。SSE和SSE2指令的操作數就是XXM寄存器,因此可以實現單指令流多數據流,具有高并行度

?

?

匯編語言與高級語言的接口

在C語言中嵌入匯編語言代碼

1.嵌入方法

//“__asm” 關鍵字//單句格式 main() {__asm MOV AH,2;__asm MOV BH,0;__asm MOV DL,20;__asm MOV DH,10; }//模塊格式 main() {__asm {MOV AH,2;MOV BH,0;MOV DL,20;MOV DH,10; } }

?

在Visual C++中使用嵌入匯編的規定:

在用匯編編寫的函數中,不必保存EAX、EBX、ECX、EDX、ESI、EDI寄存器,但必須保存函數中使用的其他寄存器(如ESP、EBP、PSW等)

嵌入式匯編語言語句中,可以使用匯編語言格式表示整數常量(如378H),也可以采用C++的格式(如0x378)

嵌入式匯編中的標號和C++的標號相似,作用范圍是在定義它的函數中有效

?

?

2.程序舉例

例3:使用SSE2指令優化程序運行速度

已知矢量A=(a0,a1,...,aN?1)(a_0,a_1,...,a_{N-1})(a0?,a1?,...,aN?1?)?和矢量B=(b0,b1,...,bN?1)(b_0,b_1,...,b_{N-1})(b0?,b1?,...,bN?1?)?,兩個矢量的點乘定義為:A?B=∑i=0N?1aibiA\cdot B=\sum_{i=0}^{N-1}a_ib_iA?B=i=0N?1?ai?bi??

編寫采用SSE2指令實現求兩個矢量的點積的程序。設N=8N=8N=8?,矢量分量類型為字

采用SSE2指令中的PMADDWD(教材P83,表3.5)完成矢量的分類乘運算和部分和,然后利用移位運算一次求出最終結果

?

程序源代碼:

為了測試代碼運行時間,使用了標準C提供的CLOCK函數,該函數的原型和有關數據類型的聲明在 time.h 頭文件中。程序結尾希望調用操作系統的相關功能讓程序暫停,按任意鍵繼續,因此需要包含 Window.h 頭文件。用CLOCK函數測量時間,精度只能達到毫秒級,因此定義常量N讓被測試代碼執行2億次

主程序中,start, stop變量記錄時間,其數據類型在time.h頭文件中定義。變量X存儲兩個向量點積的最終結果。i, j用于循環計數。兩個數組每個8個元素,元素的數據類型為16位短整型,用一個128位的XXM寄存器可以存儲整個數組。然后顯示數組A和數組B的內容

調用CLOCK函數記錄開始時間

然后令求向量點積的代碼重復執行2億次。兩個下劃線跟asm關鍵字,大括號括起來的部分是匯編語言的代碼,這里大部分指令屬于SSE2指令集

分別取數組A和數組B的所有元素裝載至128位的XXM0和XXM1寄存器。PMADDWD乘法 - 累計指令的兩個操作數都是兩個128位的寄存器,也就是剛剛裝載的A和B兩個數組。這條指令的功能是兩個128位的XXM寄存器中相同位置的16位有符號整數相乘,相鄰的兩個乘積再求和。8對操作數經過一定的運算后得到4個結果。后面只需把這4個結果再求累加和即為2個向量的點積

將運算結果寄存器的低32位也就是4個結果中的一個傳送至EAX,再右移4個字節取第二個結果傳送至EBX。普通加法指令執行后EAX的內容為2個結果之和。右移32位,取第三個結果至EBX,再加到EAX中。右移32位,取第4個結果至EBX,再加到EAX中。此時EAX的內容即為兩個向量的點積,最終結果存入內存的X單元

調用CLOCK函數記錄結束時間

顯示點積結果和代碼運行2億次的時間(結束時間-開始時間除以1000,時間單位為秒)

?

以下部分則是用C語言實現向量的點積。最后屏幕暫停,按任意鍵繼續

?

測試結果及運行環境

可以發現同樣是求兩個向量的點積重復2億次,通過嵌入匯編使用SSE2指令集實現,可以針對特定的硬件,優化程序的性能,其速度是用C語言實現的6.6倍。測試計算機的CPU是2008年第三季度推出的2核2線程的酷睿移動處理器,主頻為2.26GHZ

換1臺計算機測試,這臺計算機的CPU是2007年第一季度推出的4核4線程的酷睿多面處理器,主頻為2.4GHZ,發現和前面的測試結果相差不大。同樣的程序為什么主頻差不多,在4核計算機上的運行速度沒有明顯的提高?

因為這是一個單線程的程序,線程是操作系統調度的最小單位,一個線程只能在一個內核上運行,其運行速度與CPU的總內核數無關

再換一臺計算機測試,這臺計算機是2016年第一季度推出的10核20線程的至強處理器,主頻為2.2GHZ,與前2臺測試機的主頻相差不大,但是程序的運行時間接近前2臺計算機運行時間的一半,這是CPU內部指令流水線進一步優化,引入了很多增強性能的新技術的結果。因此看一個CPU的單核性能,除了主頻之外,其體系結構方面的改進也非常關鍵

?

?

讓C語言從外部調用匯編

兩種實現方法:

1.嵌入匯編——在C語言中嵌入匯編語言代碼

優點:

  • 簡單:無需考慮外部鏈接、命名、參數傳遞協議等問題
  • 高效:不存在過程調用的開銷

缺點:不易維護,不方便移植

2.模塊連接——讓C語言從外部調用匯編

可以采用模塊化的程序設計思路,必須用匯編語言實現的部分可以設計成一個函數,存儲為后綴名為.asm的單獨文件,并將匯編程序文件加入到C語言項目中,在C語言代碼中直接調用這個用匯編語言實現的函數

?

例:

C++語言實現的主程序中需要調用外部的addem函數,這個函數需要三個整型參數,其功能為返回這三個參數之和。這里需要聲明一下這是一個外部的,C風格的函數,同時聲明了函數的原型

輸出字符串到屏幕,提示本程序的功能是求三個數之和。再調用addem函數,傳入三個參數,返回的累加和存入變量total。這條指令編譯后首先會產生3條壓棧指令,按照從右往左的順序分別把三個參數壓入堆棧,然后是一個子程序調用CALL指令調用函數addem,執行時先將當前指令指針寄存器的內容也就是返回地址壓入堆棧,然后跳轉到用32位匯編實現的addem函數去執行

.386偽指令告訴編譯程序產生32位的機器指令。.model偽指令定義內存模型為平坦型。.public跟函數名稱說明這個函數可以被外部的其他程序調用

然后是代碼段?!昂瘮得Q PROC”開始,“函數名稱 ENDP”結束,最后是END偽指令,不跟程序入口點。注意到這里的函數名稱比主程序中引用的多了個下劃線,因為Visual C++編譯器在編譯主程序代碼時會自動給addem函數名稱左側加一個下劃線

將EBP原來的值壓入堆棧,將ESP的值賦給EBP,此時EBP和ESP同時指向棧頂的位置。后面的代碼如果有壓棧出棧指令只會影響ESP的內容,EBP的內容就此固定。通過EBP相對尋址就可以訪問到堆棧中由主程序傳遞來的參數。取第一個參數至EAX,將第二和第三個參數加到EAX。最后恢復EBP原來的值,函數返回

在Visual C的函數調用規范中規定如果函數的返回值是一個32位整數就必須通過EAX返回

最后將函數的返回值,也就是三個參數之和顯示到屏幕上

?

通過程序調試界面的反匯編窗口,從中觀察到主程序的int total = addem( 19, 15, 25 )C++語句經過編譯后產生6條機器指令,包括3個壓棧指令、1個子程序調用指令、1個加法指令和1個數據傳送指令。當程序執行到addem函數內部求三個參數之和的代碼時,堆棧的內容如下圖所示。當執行出棧指令時EBP原來的值從堆棧中彈出,當執行子程序返回指令時返回地址被彈出,在執行加法指令之前,堆棧的棧頂位置如下圖所示。這條加法指令將ESP的內容加12,這就相當于回收了三個參數占用的空間,最后把函數的返回值由EAX傳送至內存的total變量

不同的C語言編譯器,其底層子程序調用的規范、參數傳遞的規則可能不同

?

高級語言編譯器在代碼優化方面是卓有成效的。有些編譯器針對特有的處理器進行了優化,可極大提高被編譯程序的執行速度

但是編譯器通常采用常規的優化處理手段,對個別的特殊應用和安裝的特殊硬件并不了解。而手動編寫的匯編語言代碼可充分利用計算機系統的某些硬件(比如視頻顯示卡、聲卡等)的特性。在某些場合,匯編語言可以很方便地實現高級語言不提供或較難實現的功能

?

?

C語言調用匯編的其他例子

判斷有符號整數加法溢出

盡管結果顯然是錯誤的,但C語言程序運行時沒有任何警告和提示。C編譯器不會做任何有關運算結果溢出的檢查??梢酝ㄟ^C嵌入匯編設計一個函數,來檢查兩個整型變量加法結果是否溢出。函數代碼如下:

函數接收兩個整型變量作為參數。相加后如果OF置位則跳轉返回1表示結果溢出。否則順序執行令EAX清0,也就是函數返回0表示相加結果不溢出

匯編語言實現分支功能,前面分支的末尾必須加跳轉指令跳過后面的分支

修改一下原來做加法的C程序,增加對剛才函數的調用。然后運行驗證

總線技術

總線概述

總線

連接兩個以上數字系統元件的公共的信息通路

這是一般性的概念,實際上還有一種總線叫專用總線,總線上可能只需要連接兩個數字系統或兩個模塊

計算機組件間、計算機間、計算機與設備間連接的信號線和通信的公共通路

?

?

總線的分類——按連接的層次

CPU內部有很多種不同的總線結構,比如說單總線、雙總線、甚至是三總線結構。這種芯片內部的總線就叫片內總線

一般用來連接電路板上各個芯片之間的非標準的總線叫元件級總線。比如說早期的計算機內存芯片是直接焊接到計算機主板上的,連接內存芯片跟CPU芯片之間的這種總線就可以叫元件級總線

當然最新的計算機內存都是以內存條的形式插到計算機主板上的,內存條跟計算機主板之間的總線就屬于系統總線,指的是連接計算機系統內部各個模塊之間,或者說用來連接計算機主板跟各種插件板之間的標準的總線。因為系統總線通常在主機箱的內部,所以也叫內總線

通信總線用來連接計算機系統跟外設,這種總線一般在主機箱外部,所以也叫外總線

也有一些特例,比如現在最普及的PCIe總線

現在CPU內部通常會集成很多個CPU的內核,還集成了內存的控制器,包括一些高速的接口控制器。微處理器芯片內部CPU內核和內存控制器還有高速的總線控制器之間的互聯通常也會采用PCIe總線。盡管最新的微處理器芯片內部也會有PCIe總線,從制定PCIe總線規范的初衷來講,PCIe應該屬于系統總線

輔存,如硬盤一般也會歸到外設里面?,F在比較流行的固態硬盤有多種連接方式,有一種叫M.2和U.2接口,底層的通信協議仍然采用PCIe

?

?

總線的分類——按數據傳輸位數

1.并行總線

采用多條數據線對數據各位進行同時傳輸

僅適宜計算機內部高速部件近距離連接。高頻率使發送端原本同步的數據到達接收端時出現時鐘偏移,也會加劇空間距離很近的多條數據線間的串擾

典型的并行PCI總線,一般時鐘頻率就是33MHZ。后來在服務器或者工作站上采用66MHZ,頻率再高,以上這些問題要解決起來就非常復雜

通信距離較長則信號線線數比較多,也會增加總線的長度進而增加總線的成本

?

2.串行總線

采用一條數據線逐位傳輸各位數據

無需考慮時鐘偏移和串擾問題,故可通過提高頻率來提高數據傳輸率

數據二進制位采用差分的形式來傳遞的話就可以避免線跟線之間,或者說外界對數據線的干擾

常用于長距離通信及計算機網絡

在短距離應用中性能也已超過并行總線

?

?

系統總線 (PCI, PCIe) 和通信總線 (USB) 一般都會有標準化的組織為它制定相應的規范

標準化總線

由IEEE(美國電氣電子工程師協會)或計算機廠商聯盟制定。對總線插槽尺寸、引腳分布、信號分布、時序控制、數據傳輸率、總線通信協議等有明確規定

顯卡電路板跟計算機主板之間相連一般采用標準的PCIe$\times$16系統總線

?

總線標準化的優點:

1.簡化軟硬件設計,簡化系統結構 →\to模塊化

2.使系統易于擴展、便于更新

3.便于調試、維修 →\to各插件板分別調試;一級維修

?

典型的標準化總線——內總線

ISA總線

1981年,IBM PC/XT (8位ISA總線,基于8088)

內存直接焊接在計算機主板上。要對計算機進行功能擴展,可以基于8位的ISA總線來擴展插件板,把設計的板卡直接插到計算機主板8位的ISA總線插槽上,就相當于對計算機系統的硬件進行了一定的擴展

1984年,IBM PC/AT (16位ISA總線,基于80286)

16位的ISA總線為了跟原來的8位兼容,在原來的8位ISA總線基礎上后面增加了一些相應的信號。數據線從原來的8位擴展到了16位,地址線從原來的20位擴展到了24位

即設計的板卡如果基于8位的ISA總線,實際上也可以插,只不過只用到了插槽的前面這一半

1988年,以康柏 (Compaq) 公司為首,EISA (Extended ISA),32位

?

ISA總線可以簡單地理解成就是8088/8086系統總線的延伸,16位的ISA總線也可以理解成是80286系統總線的延伸。常用的讀寫信號,如地址線、數據線、讀寫控制信號ISA總線上面應該都能找得到,電源、時鐘信號、跟中斷有關的信號也有

下圖的兩部分應該在一條上,底下一截平移到了右邊顯示

?

?

PCI總線

特點:

1.不依賴于處理器

PCI總線在制定規范時則并沒有參考任何一款處理器

ISA總線在制定規范的時候針對的就是Intel從8086到80286這一系列的微處理器,基于這樣的微處理器的系統總線信號定義到ISA總線上

?

2.擴充性好

可以通過相應的橋芯片擴展出多條PCI總線,連接更多的外設部件

?

3.支持自動配置

基于PCI總線的設備或板卡插到總線的擴展插槽上,計算機啟動時會自動識別插接到擴展插槽上的設備并且對設備內部的各種資源比如占用的接口地址、內存范圍進行自動配置

ISA總線通常不支持。事先要把ISA總線的板卡(上面一般會有一些撥動開關,開關撥到不同狀態占用的接口地址范圍是不同的)插接到計算機的主板上加電看能不能正常啟動。不能則說明ISA總線的板卡占用的資源跟主板資源沖突

?

4.支持多主控設備

如果某一個PCI總線上的設備成為主控設備之后,實際上它可以主動去訪問這個總線上的其他設備,甚至可以直接主動去訪問主存。不經過CPU能夠實現板卡與板卡之間,設備與設備之間或者說設備與內存之間的直接數據傳送

DMA就是基于這種所謂的多主控設備方式來實現的

?

PCI總線上究竟有哪些總線信號,這些總線信號通過什么方式來實現PCI總線上兩個設備之間的可靠數據通信?下面通過時序來說明,這是傳統的并行PCI總線上常用的信號

PCI總線屬于同步總線,所以總線信號里肯定應該有一個CLK時鐘信號

PCI總線上的仲裁方式采用的是集中式的獨立請求方式。假設現在PCI總線上的某一個設備取得了總線的使用權,成為了PCI總線上的主設備,想要選擇某一個從設備傳輸數據,要從從設備里的存儲器里讀一些數據

主設備先把FRAME ̄\overline{FRAME}FRAME信號置低電平,告知總線上的其他設備做好準備自己要進行通信,同時會把它要訪問的內存地址放在[AD…0] 這32根地址數據復用的信號線上。在C/BE ̄[3..0]C/\overline{BE}[3..0]C/BE[3..0]這4根線上放一個命令,0110表示內存讀命令。此時掛接在PCI總線上的其他設備要檢查一下主設備要訪問的內存地址是否落在自己的管轄范圍內。被選中的從設備會把設備被選中信號DEVSEL ̄\overline{DEVSEL}DEVSEL置為低電平,告知主設備自己在哪并且已經準備就緒

實際上計算機的最大內存尋址空間通常比較大。比如32位系統下內存地址是32位,最大的內存地址空間應該是4GB,但實際上這4GB不可能全部分配給內存條來用。通常在高端的地址要保留一部分給外設來用,相當一部分要保留給PCI設備來用,所以PCI設備內部存儲器通常容量也比較大,一般也會把它映射到內存地址空間

中間隔一個時鐘周期實現總線傳輸信號方向的轉變以避免總線競爭。經過一個總線轉換周期后,后面理論上來講只要主設備和從設備都處于就緒狀態,則每一個時鐘周期時鐘信號的上升沿就可以傳遞一個32位的數據。當然傳遞的過程主設備和從設備內部的地址會自增,所以地址只需要傳一次,后面可以連續傳輸很多的數據,這種方式叫多發數據傳送方式

如果主設備或者從設備內部有時可能內部來不及處理需要等待一下呢?IRDY ̄\overline{IRDY}IRDY是主設備準備好的信號,TRDY ̄\overline{TRDY}TRDY是從設備準備好的信號,這2個信號同時為低電平就可以傳輸一個數據,如在時鐘周期5時鐘信號的上升沿,從設備沒有準備好,此時就不會傳輸數據

主設備把FRAME ̄\overline{FRAME}FRAME?信號置高電平,后面再傳輸一個數據,整個傳輸過程就可以結束

?

通過這個時序可以了解到PCI總線一個時鐘周期就可以傳輸一個32位的數據,通過這點可以算傳統的PCI總線理想情況下的多發數據傳輸率。如33MHZ PCI對應數據傳輸率為33×106×32÷8=132MB/s33\times10^6\times 32\div8=132MB/s33×106×32÷8=132MB/s??

?

PCI總線的局限:

總線上的所有設備共享帶寬,只能分時使用

用并行單端信號,一般通過提高總線位寬和頻率的方法增加總線帶寬。提高總線位寬會增加芯片引腳,影響芯片生產成本。提高總線頻率會產生時鐘偏移和串擾問題,還會影響總線負載能力

高端的工作站或者服務器上PCI總線的數據線的位數一般相比個人計算機更大

?

PCIe總線

PCIe在計算機里面首先會有一個總的控制器根組件,根組件內部通常會集成一個PCIe總線控制器和存儲器控制器,存儲器控制器主要用來實現PCIe總線地址空間跟內存地址空間之間的映射,或者說轉換。同樣根組件內部還提供了多個PCIe端口

如果需要用到傳統的并行的PCI總線可以再接一個PCIe-PCI橋。橋可以實現兩種不同總線協議之間的轉換

如果需要接更多的基于PCIe總線的外設,可以通過一個交換器(和網絡上的交換機類似)擴展更多的端口

?

PCIe總線的特點:

1.串行差分,一次只傳輸一個二進制位

避免了時鐘偏移和串擾問題,總線可達到很高的頻率,從而進一步提高總線帶寬

每一條PCIe數據通路 (Lane) 由兩組串行差分信號(4根信號線,這4根線組成一個通道)構成,可進行全雙工數據傳輸,發送和接收各是一對信號線,發送和接收并行工作

?

2.直流平衡、內嵌時鐘

PCIe1.0和PCIe2.0采用8/10b編碼,將每8位數據編碼成10位傳輸,編碼開銷占總帶寬的20%開銷

串行傳輸的信號如果傳輸的時候連續0和連續1太多,電平長時間沒有變化,很難從信號里把時鐘提取出來。8/10b編碼就是用10個二進制位,從1024種組合里找出256種組合,這256種組合連續0和連續1的個數不會太多,且0的個數和1的個數基本均衡,用它來表示相應的一個字節的信息

PCIe3.0采用128/130b編碼提高了帶寬利用率,編碼開銷占總帶寬的1.538%開銷

總線頻率2.5GHz則每秒鐘可以傳輸2500M個二進制位,10個二進制位用來表示一個字節,所以×1\times1×1單向帶寬為250MB/s (1GT/s=1Gbit/s)。如果發送的同時還在接收的話,則總的帶寬在此基礎上可以再乘2

?

3.多通道

一條PCIe鏈路可以由多條數據通路組成,多通道并行工作提高總線帶寬

目前PCIe鏈路可以支持1、2、4、8、12、16和32個數據通路,即×1、×2、×4、×8、×16、×32\times1、\times2、\times4、\times8、\times16、\times32×1×2、×4×8、×16、×32 數據帶寬

如獨立顯卡一般會通過PCIe×\times×?16的總線連接到主板上,指的就是有16個通道

通道之間不需要同步。比如說這次要傳輸一大批數據,采用PCIe$\times$16的總線傳輸。可以把這一大批數據平均分成16等份,每一等份用一個通道來傳輸,底層會一個個數據包打包之后再傳輸。具體數據包之間按照什么順序來組合內部都有編號。接收方接收到這些數據之后按照數據包內部規定跟順序有關的信息接收方再重新拼裝成原始數據

?

4.端到端(交換結構),實現多模塊同時通信

傳統并行PCI總線所有設備共享帶寬。PCIe總線采用端到端(交換結構)的連接方式,每一條PCIe鏈路中只連接兩個設備

?

5.軟件向下兼容

不管是PCI還是PCIe總線對掛接在這個總線上的設備進行讀寫和控制,軟件的接口是完全一樣的

?

下面這個主板上有很多PCI總線的插槽。為了兼容老的基于并行PCI總線的設備或者說插卡,仍然保留了傳統的32位PCI總線

典型的標準化總線——外總線(通信總線)

通常把這種總線也叫做接口,比如說USB接口

?

RS-232C串行通信接口

打開設備管理器,在端口這一欄有一個通信端口 (COM1),這就是傳統的RS232串行接口。最新的計算機主板可能并沒有把這個接口作為一個插座引出,但是這個接口的資源在計算機主板上仍然存在。打開COM1端口的屬性還可以設置這個端口在通信時的一些參數

早期國際互聯網還沒有出現時想實現遠程的不同地方的計算機之間的通信要借助電話線,電話線上傳輸的是模擬信號,調制解調器把計算機能夠接收的TTL電平轉換為模擬信號,而調制解調器就是通過RS-232C連接到計算機上的

現在如果提到DTE,就理解成計算機。提到DCE就理解成外設

?

?

1.信號

傳送信息信號:

RS-232C能夠實現全雙工的通信,所以數據線有2根,一根用來發送一根用來接收

  • TxD : 發送數據線 (DTE →\to DCE)
  • RxD : 接收數據線 (DTE ←\leftarrow DCE)

?

聯絡信號

  • RTS : 請求發送,計算機告訴外設要發送數據 (DTE →\to? DCE)
  • CTS : 清除發送,外設告訴計算機可以接收數據 (DTE ←\leftarrow?? DCE)
  • DTR : DTE就緒,計算機告訴外設已經準備就緒 (DTE →\to DCE)
  • DSR : DCE就緒,外設告訴計算機已經準備就緒 (DTE ←\leftarrow DCE)
  • DCD : 數據載波檢測。調制解調器如果從電話線上接收到有數據來了就會把數據載波檢測置成有效告訴計算機 (DTE ←\leftarrow? DCE)
  • RI (22) : 振鈴提示,跟電話線有關 (DTE ←\leftarrow DCE)

?

2.電平

?

3.與TTL電平轉換

計算機希望接收發送的信號都是TTL電平,比如低電平就是0V,高電平就是5V。所以中間需要電平轉換

MAX232芯片只需要一個單5V電源供電,單5V電源內部經過升壓之后產生±10V\pm 10V±10V?的電壓。下圖即為該芯片的具體引腳

增壓電路需要一些電容,電容很難集成到芯片內部,特別是一些容量大的電容,需要外接。計算機發送出來的TTL電平信號經過它轉換成RS-232C串行接口所需要的±10V\pm 10V±10V的電平。從串行接口來的±10V\pm 10V±10V的電平信號通過它轉換成計算機能夠接受的TTL電平

?

接下來看一下RS-232串行接口具體的通信格式

首先總線處于空閑狀態,一個啟動位,接下來先傳低位后傳高位,最后是奇偶校驗位和2個停止位

RS-232串行接口有的時候叫異步串行通信。因為它沒有時鐘信號,所以不是同步總線而是異步總線。并且通信之前雙方事先要約定通信的波特率,兩邊設置的參數包括數據的格式必須要一樣,然后才可以通信

比如說發送方要發送數據,必須得從啟動位開始,接收方檢測到啟動位就會從這個位置開始計時,因為雙方約定了數據傳輸的波特率,相鄰兩個數據之間的間隔可以計算得到。從這個啟動位開始,接收方每固定一段時間采樣一次數據線得到一位的二進制數據

當然發送方和接收方具體的定時不可能毫無誤差,但只要保證這一個數據(通常最多只傳輸一個字節)在傳輸的過程中哪怕每一次采樣時稍微有一點點錯位,傳輸到最后一個數據能夠正常接收就可以了。傳輸下一個數據時又會再來一個啟動位重新對齊

?

應用:

1.使用Modem連接

電纜信號一一對應,共10線。

(保護地、信號地、…)

?

2.直接連接:計算機 (DTE) ?\leftrightarrow? 計算機 (DTE)

RS-232串行接口最大的優點在于實現起來非常方便,成本也低。最簡單的實現方式是三線經濟方式 (三線制 RS-232)

計算機跟外設之間首先要共地。發送一根數據線,接收一根數據線,兩邊交叉著直接連

?

3.軟硬件系統調試:控制臺、超級終端

RS-232串行接口相對數據傳輸率較低,現在用的不是很多。最典型的應用主要是硬件調試

比如說現在有一塊嵌入式的開發板,這個電路板在設計的時候為了簡化問題,可能沒有那么多輸入輸出設備可以連接

為了觀察到電路板內部CPU執行程序的過程,或者說發命令來控制它的工作過程,可以通過最簡單的三根線實現的RS-232串行接口實現接口來和計算機連接。在計算機上運行超級終端軟件,通過計算機的鍵盤在超級終端軟件里面直接輸入命令,那個命令就會通過RS-232串行接口傳輸到電路板內部。電路板內部接收到命令,做一定的運算操作之后會把可能的相應輸出信息的ASCII碼再通過串行接口傳輸到計算機上運行的超級終端軟件里面。超級終端軟件會把相應的接收到的字符串顯示到計算機屏幕上

這樣其實就相當于把計算機的顯示器和鍵盤給開發板來用

?

USB總線

特點:

每個USB總線支持127個外設

整個USB系統只用一個端口(接口地址)、一個中斷 →\to 節省系統資源

支持熱插拔、動態加載驅動程序:PnP,自動配置。帶電拔出后自動回收資源

傳輸距離:3~5米,電壓:5V

?

通過信號的名字可以觀察到USB總線采用串行差分的方式來傳送數據。USB1.0和USB2.0只有一對數據線,只能工作在半雙工狀態下,不能同時接收和發送

USB各版本向下兼容。USB3.0為了和USB2.0兼容,原來的+5V電源、+5V地、兩根差分形式傳輸的數據線仍然保留,另外又新增了兩對數據線。USB3.0如果工作在超速模式下,發送和接收分別各用一對,采用差分的形式來傳輸信號,支持全雙工的方式來進行工作

?

?

Low-Speed 低速模式,Full-Speed 全速模式,High-Speed 高速模式,SuperSpeed 超速模式

現在一些低速的外設,比如說USB接口的鍵盤和鼠標,工作在低速模式下應該也完全夠用

USB總線可以通過總線來給外設提供電源,即能夠實現給外設直接供電。USB3.1從第2代開始還支持快充模式,可以提供更大功率的輸出

再來看一下USB具體物理上的接口,計算機端和外設端有A、B、C類型。C類型接口從使用的角度來講最大的方便之處在于不分正反,正著插和反著插都可以。通過信號的分布會發現所有的這些總線信號都是根據中心點鏡像對稱的,不管是正插還是反插對應的都是同一個位置

TX1+和TX1-是一對用來發送的差分信號線,RX1+和RX1-是一對用來接收的信號線

?

Type-C有兩個高速數據通道, (TX1+/TX1-,RX1+/RX1-) 和 (TX2+/TX2-,RX2+/RX2-)

USB3.1僅使用其中一個通道,另一個通道可用于備用模式

USB3.2可以充分使用這兩個高速通道,雙通道20Gbps。要能夠實現最高的數據傳輸率必須得用C型接口

如果這兩個高速通道都用于備用模式,則速度就會下降成USB2.0的High-Speed

?

?

ATA總線

ATA總線連接存儲設備和計算機。早期采用并行的方式傳輸數據,PATA即并行ATA接口,其總線電纜是40芯或者80芯的扁平電纜,線比較寬占主機箱空間,也影響散熱,也不可能過長。后來出現了串行ATA接口,叫SATA或者SATA總線

?

ATA總線設計之初就是用來連接硬盤的,所以它在具體通信時的通信格式,包括邏輯塊地址用多少個二進制位來表示在它的總線規范里有具體表示。比如最早的ATA總線,它在通信時規定邏輯塊地址用22位來表示,這樣硬盤的邏輯塊最多有222=4M2^{22}=4M222=4M?個,一個邏輯塊對應一個扇區,而通常情況下一個扇區是512B,這樣就能算出理論上能支持的最大磁盤容量

1TB=1024TB,1TB=1024GB

?

SATA具有速度高、電壓低(功耗低)、線纜窄、支持熱拔插、傳輸距離長的特點,現已取代PATA

服務器一般配置好,通常是24小時不斷電工作。如果服務器磁盤陣列里的某一個硬盤出問題會希望服務器不要關機,直接帶電將其拆下來,這就要求硬盤的接口必須支持熱插拔

?

總線的驅動與控制

總線的競爭與負載

?

總線競爭:同一總線上,同一時刻,有兩個或兩個以上的器件輸出其狀態

1.對TTL門

有兩個門同時將狀態輸出到信號線上,一個輸出低電平一個輸出高電平,此時總線上會是一種不高不低的非TTL電平,可能會丟失狀態。并且這種情況下可能有一個非常大的電流灌進輸出低電平的引腳,嚴重時會燒壞電路

照著具體的門電路內部看一下。如果這兩個門的輸出引腳接到一起,實際上就相當于兩個門同時把狀態輸出到這一根線上

右邊的與非門只畫了輸出的這部分電路

比如一個輸出低電平一個輸出高電平,輸出低電平的引腳底下的晶體管處于飽和狀態,即集電極和發射極之間導通。輸出高電平的引腳對應的這個晶體管截止,集電級跟發射極之間斷開,上面上拉用的晶體管是導通的。這樣如下圖所示,從正電源到輸出低電平的輸出引腳,內部的晶體管一直到地會有一個相對比較大的電流。長時間維持這種狀態,電流大功耗大,發熱熱量達到一定程度有可能會把這兩個器件的輸出引腳,即它內部對應的晶體管燒壞

這根線上究竟是高還是低呢?

實際上只要有一個引腳輸出為低電平,就相當于把這根線通過這個輸出引腳內部的下拉晶體管直接接地,所以上這根線上呈現的應該是類似低電平的狀態

?

2.特例:集電極開路/漏極開路輸出

OC: Open Collector

有一種門電路,它的輸出引腳集電極開路/漏極開路,相當于輸出引腳上面上拉的部分沒有,輸出引腳到正電源之間什么都沒連,處于開路狀態

下圖只畫了輸出引腳有關的晶體管,內部的其他部分省略

這樣的輸出引腳是可以接到一起的,外面必須加一個阻值相對較大的上拉電阻。如果這幾個引腳都想輸出高電平,每一個晶體管都處于截止狀態,集電極與發射極之間不導通,線上呈現高電平。若某一個輸出引腳想要輸出低電平,其三極管處于飽和狀態,相當于把這根線通過晶體管接地,會產生如下圖所示的電流,但因為上拉電阻阻值較大,所以這個電流比較小,不會燒壞器件,但B輸出的“1”信息會丟失

在數字電路中三極管當作電子開關來用,要么導通要么斷開

只有所有的輸出引腳都輸出電平時,這根線才會是高電平,任何一個輸出引腳只要輸出低電平,這根線就呈現低電平狀態,這就是線與邏輯

?

?

3.用三態電路,嚴格控制邏輯

這根線接了兩個負載也就是兩個輸出引腳,都具有三態功能,可以控制是否能輸出。三態門的輸出狀態有高電平、低電平、高阻三種。高阻相當于電阻無窮大,相當于輸出引腳跟總線之間脫開

?

?

總線的負載

1.直流負載

如果驅動門輸出高電平時,沒有能力提供負載需要吸收的電流,會導致高電平電壓高不上去。輸出低電平時如果吸收電流的能力不夠,會導致低電平電壓低不下來。都會造成邏輯上的問題

2.交流負載

對MOS電路,IILI_{IL}IIL?、IIHI_{IH}IIH?很小 →\to 主要考慮電容負載

所有的這些負載輸入引腳對地之間都有一個分布電容。接的負載多了后,這些電容是并聯關系,一端同時接到線上,另外一端同時接地,總電容越來越大,會產生較大的電容負載,濾掉高頻分量

且如果想從低電平變到高電平,電容電壓無法突變,充電需要過程,電容越大過程越緩慢,從高電平變到低電平也一樣。一些窄的正脈沖可能會被濾掉,產生邏輯問題

?

所有的負載輸入引腳到地到會有一個電容。信號線在電路板上走,信號線本身到地之間也會有電容,這是元件級總線、內總線帶來的電容。信號線要從一個電路板引到另外一個電路板上,或者連接到某一個外設上,傳輸線長了也會用更大的分布電容

故要求輸出門的負載電容CPC_PCP?滿足如下條件:

?

驅動門和負載的原始參數都可以通過查芯片手冊得到

?

總線驅動設計

單向總線信號的驅動設計

如果連接到總線上的模塊很多,也就是總線的負載很重,就需要加驅動器。對于單向的總線控制信號,比如地址、讀寫控制信號,情況相對簡單。雙向數據總線如果要加驅動,稍有不慎就會引起總線競爭

?

比如要設計一個由兩塊電路板(主板CPU板,擴展板電路板1)組成的產品。擴展板上需要從CPU板引過來很多信號,包括地址線的最低位A0。地址線實際上需要接很多負載,比如CPU板需要擴展內存,主板上可能會有很多內存芯片,每個內存芯片都有地址線,可能都要跟CPU的地址線相連,A0這根線本身在CPU板上就要接很多負載?,F在這根線要引出來到擴展板上,擴展板很多地方也要用到這個信號,又要有很多負載

最好不要直接把這根線引出來而是加一個驅動器。經過驅動器再輸出,不管它輸出之后后面接了多少個負載,對CPU來講也只是增加了1個負載而已

把該信號引入后最好也不要直接用而是加緩沖器。下圖從驅動器的角度來講它后面只接了3個負載,每個緩沖器后面又加了5個負載

緩沖器和驅動器功能類似,只是叫法不一樣

驅動器和緩沖器也能起到緩沖作用,保護硬件

?

74LS244可以當驅動器或者說緩沖器來用,它主要用來實現單向的總線信號驅動。其內部有8個三態門,4個一組,總共2組,每組三態門的控制端接到一起引出來,低電平有效。把允許信號,即三態門的控制端接地令其永遠有效,這樣8個輸入和8個輸出永遠一樣

?

雙向總線信號的驅動設計

雙向數據總線驅動器可以選擇74LS245芯片實現,通過控制允許信號和方向控制信號來避免總線競爭。允許信號低電平,A邊和B邊導通。然后方向控制信號給高電平,信號傳遞的方向從A到B,給低電平則從B到A

注意74LS245不是一個開關,它是把一邊接收的信號原封不動地復制到另一邊輸出

?

例3:某微型機電路板上有內存C0000H~\simEFFFFH和接口A000H~\simBFFFH,試畫出該電路板板內雙向數據總線驅動與控制電路

1.防止總線競爭原則:只有當CPU讀板內內存或讀板內接口時,才允許雙向數據驅動器指向系統總線的三態門是導通的

2.地址分析(內存地址、接口地址)

設計的插件板板卡內部有很多存儲器,插在計算機主板插槽上占用資源,希望占用一部分的內存地址空間和接口地址空間。計算機主板CPU運行某一程序時訪問內存或接口,訪問的內存或接口地址落在這個范圍之內,訪問板卡內部的存儲器,驅動器74LS245的允許信號就應該給低電平讓兩邊接通,然后根據讀板卡還是寫板卡控制方向信號。設計雙向數據總線驅動時,要設計相應的內存和接口地址譯碼電路判斷計算機主板要訪問的內存和接口是否在范圍內

C0000H~\simEFFFFH低4位全0到全F所有的組合都包含在內,故只需分析從C到E的最高位。觀察高位地址發現A18、A17、A16是4、5、6這3種組合之一,如果該譯碼電路用3-8譯碼器實現,那Y4、Y5、 Y6任何一個是低電平,這三根線肯定就是這三種狀態之一。此外A19必須是1。

對A000H~\sim???BFFFH的分析過程也類似,高三位地址只要是“101”地址就落在范圍內

3.畫驅動與控制電路

74LS138是3-8譯碼器

內存地址譯碼電路限定了高位地址A19必須是1,A18、A17、A16必須是4、5、6三種組合之一,CPU此時正在訪問內存的條件

接口地址譯碼電路限定了A15、A14、A13分別是高電平、低電平、高電平,CPU此時正在訪問接口地址空間,CPU此時正在控制總線不是DMA狀態(AEN信號給低電平)的條件

這兩部分任何一個條件全部滿足74LS245的兩邊就應該接通

方向控制信號用讀信號,內存讀和接口讀信號任何一個給低電平經過與門輸出就是低,方向從B到A。寫時讀信號肯定無效,兩個信號都是高電平,經過與門輸出高電平,方向從A到B

存儲技術

常用存儲器芯片及連接使用

?

靜態隨機讀/寫存儲器 (SRAM) 及接口設計

SRAM的優點是可以直接連接到系統總線上,有獨立的地址線,數據線,讀信號,寫信號和片選,并且讀寫速度都很快。是易失性存儲器,掉電之后內容就沒了,剛一加電內容是隨機的

?

用單個SRAM芯片構成8088的內存

可以認為這些信號都是8088工作在最大模式下的系統總線信號,或者認為這些信號都是8位ISA總線的信號,反正都一樣

?

有的電路高位地址會留幾根不連,這樣連線較少但會浪費內存地址空間

?

用多片SRAM芯片構成8088的內存

存儲器的字擴展:

1.地址線并聯

2.數據線并聯

3.OE― 并 → MEMR―,WE― 并 → MEMW―

4.CS― → 地址譯碼器(高位地址譯碼)的不同輸出

8088系統總線數據線有8根,要求內存是8位的

如果SRAM芯片只有4根數據線,則不管構成什么內存都要進行位擴展,因為CPU訪問內存最小內存就是8位,不可能一次訪問4位的數據

?

存儲器的位擴展:

1.地址線并聯

2.數據線:1號芯片D0~D7,2號芯片D8~D15

3.OE― 并 → MEMR―,WE― 并 → MEMW―

4.CS―并聯 → 地址譯碼器(高位地址譯碼)

8086要求內存必須是16位的,下圖中SRAM芯片是8位的,要進行位擴展

連接地址線時,SRAM芯片的A0~A10要連接到系統總線的A1~A11。因為2個8位存儲器位擴展之后構成1個16位存儲器,給16位存儲器地址要給字地址。x86按字節編址,如果給字的地址要從A1開始。這兩個芯片可以同時被選中,同時被選中時CPU就對內存進行16位讀寫

?

若現在想用匯編語言編一個程序訪問它里面的某一個單元,如從80002H地址讀一個16位數據:

先初始化DS,將段的起始地址高16位傳送到DS。再將16位段內偏移送到指針寄存器BX

然后寄存器間接尋址從指向的內存單元讀一個數。默認段寄存器為DS,CPU會從DS讀出段起始地址的高16位,末尾添4個0,再加上BX里存的16位段內偏移,加的結果就是要訪問的內存地址

MOV AX,8000H MOV DS,AX MOV BX,2 MOV AX,[BX]

?

如要讀一個8位數據,只需要把目標寄存器改為8位

從偶地址讀BHE―為高電平,A0為低電平。從奇地址讀BHE―為低電平,A0為高電平

?

如要讀一個16位數據,目的寄存器就應該寫16位

從偶地址開始讀,BHE―和A0均為低電平,連續讀2個字節傳送到目的寄存器,2個字節占2個地址,小地址傳送到低8位,大地址傳送到高8位

從奇地址開始讀,必須分兩次來讀,先讓BHE―引腳為低電平,A0為高電平,讀8位數據傳送到目的寄存器的低8位。再讓BHE―為高電平,A0為低電平,讀8位數據傳送到目的寄存器的高8位

?

數據在內存中要對齊存放,如果按字節編址,16位數據起始地址是2的整數倍,32位數據起始地址是4的整數倍,64位數據起始地址是8的整數倍

如果不對齊存放,像x86處理器,如8086,16位數據從奇地址開始放照樣可以處理,只是速度會變慢,如果對齊一個總線周期就能夠完成,如果不對齊得花兩個總線周期。時間變長,但是功能照樣能實現

這里也體現出CISC結構處理器對軟件要求不是很高,硬件能干的活盡量硬件都干了,有一些RISC結構的處理器就要求數據在內存里面必須對齊存放,不對齊指令就無法執行,不同的CPU處理方式不一樣

現在計算機內存并不是用SRAM來構成的,包括最早的個人計算機內存也是用DRAM構成的。講課用SRAM是因為這個簡單,因為它從信號上來講有獨立的地址線數據線讀寫信號和片選,可以直接連接到系統總線,電路包括控制方式最簡單

用SRAM構成單片機內存完全夠用。如51單片機芯片內部會集成一定容量的內存,就存儲一些臨時變量用的,如果太小外面可能還要再擴展內存,擴展內存一般不大

?

如果用DRAM構成內存,進行一次讀寫地址得分兩次來送,先送一個行地址,再送一個列地址,然后才能讀寫,還有定時刷新。DRAM后來發展出現了SDRAM(同步動態隨機訪問存儲器),再發展出現了雙倍速的SDRAM就是DDR的SRAM,現在主流用的比較多的是DDR4

這種雙倍速的SDRAM在讀寫時時序更復雜,對它進行讀寫首先要發激活命令,同時送行地址。發激活命令相當于把它里面的某一行打開,然后把這一行的所有內容讀到行緩沖區中,然后再給它發相應的讀寫命令,同時給它列地址,對打開的行緩沖區進行讀寫。在訪問其他行之前要把當前這一行關閉,也就是把行緩沖區的內容回寫到原來的位置,這要給它發一個預充電命令

SDRAM存儲器在控制時涉及到很多比較復雜的命令,沒有辦法直接連接到系統總線。一般要設計一個比較復雜的電路現在都會有一些現成的芯片,或者說現成的IP核可以直接用。你可以理解成CPU系統總線上必須要通過一個SDRAM控制器間接地才可以訪問到SDAM。從這個角度來講,現在計算機的內存其實和外設很像,CPU通過相應的接口訪問,而不是直接訪問,實現的電路非常復雜

現在的內存,如DDR的SDAM在進行讀寫時采用突發的讀寫方式,一次突發讀寫傳送幾個數據,并不是隨機訪問。CPU內核要取得某一個數據最終從CPU內部的Cache得到,數據如果在內存中對齊存放,最終以塊為單位裝載到Cache內,它在Cache內也是對齊存放的。CPU內核可以直接訪問Cache,Cache就是用SRAM實現的

?

計算機的存儲器現在分層較細,如果只算寄存器組,控制器和運算器之外的那些存儲器,最頂層的是用SRAM構成,可以直接訪問的Cache,再往下是用DDR的SRAM實現的主存,再往下有一些計算機有如Intel的奧騰存儲器的介于主存和固態硬盤之間的層次,再往下是固態硬盤,再往下是機械硬盤

?

?

除了用基本的邏輯門和3-8譯碼器,也可以用ROM作譯碼器。ROM能根據輸入選中對應存儲單元并輸出該存儲單元的內容

?

現在要用4片6264構成一個存儲容量為32KB的8位存儲器(字擴展),其地址空間為E0000H~E7FFFH。用一塊512×4(即512個存儲單元,每個存儲單元為4位)的PROM芯片63S241作為ROM譯碼器

給單向信號(A0~A12,MEMR―,MEMW―)和雙向數據信號(D0~D7)加驅動

CPU沒有訪問內存時MEMR―,MEMW―均為高電平,經過與門之后輸出是高。ROM芯片片選和讀信號都是高電平,數據線輸出是高阻。高阻就是電阻無窮大,相當于4片6264芯片的片選信號懸空哪都沒有接,輸入引腳是高電平還是低電平是不定的。加上拉電阻能保證這4根線輸出高阻時仍然會呈現高電平狀態

?

?

也可以用數據比較器作譯碼器

兩路8位輸入數據相等,輸出低電平。否則輸出高電平

?

一路輸入直接接開關置于固定狀態。開關斷開時由于上拉電阻呈現高電平,閉合時相當于把這根線通過開關接地,這根線就是低電平

另一路接到系統總線的高位,不用的線也直接接高電平。高位地址和開關撥的狀態一樣時才會輸出低電平選中這個芯片

數據線還是要加雙向驅動

?

也可以用PLD作譯碼器。知道有這種辦法就可以了

?

SRAM設計舉例1:

現有容量為 8K×8bit 和 4K×8bit 的SRAM芯片。在8086系統中,

1.利用這樣的芯片構成地址范圍為C2000H~C7FFFH的內存,畫出最大模式下包括總線驅動在內的此芯片與系統總線的連接圖(譯碼器件自行選擇,盡量選擇容量大的芯片)

2.試編寫8086匯編語言程序,從地址C2000H開始,依次寫入數據,直到地址C7FFFH。要求數據從0開始,每寫入一個字節后數據加1,即寫入數據依次為:00H、01H、02H、03H、… 、FEH、FFH、00H、01H、…… 。然后逐個單元讀出比較,若有錯,則在DL中寫入01H,退出檢測;若每個單元均對,則在DL寫入00H

順便介紹了下檢查內存的幾種方法和原理

?

?

首先確定要用多少片芯片

C8000H-C2000H=6000H,即24K

盡量選擇容量大的芯片,首先要用8K×8bit的芯片。但考慮到要構成8086的內存,如果用8位的SRAM必須是偶數片,2片8位的SRAM位擴展之后才能夠構成1個16位的存儲器。折中一下:

需要8K×8bit芯片2片、4K×8bit芯片2片

8K×8bit芯片地址線:A0~A12,數據線:D0~D7

4K×8bit芯片地址線:A0~A11,數據線:D0~D7

?

考慮內存地址譯碼電路應該有幾個輸出

作為8086的內存來講,每2片8位芯片位擴展之后構成1個16位的存儲器,各對應地址譯碼電路的1個輸出。所以應該有2個輸出

?

然后根據地址范圍分析內存地址譯碼電路應該怎么設計

C8000H-C2000H 16進制地址的低3位從全0到全F,所有組合都有,可以不用考慮,直接分析高8位地址C2~C7

先看經過位擴展之后構成一個16位存儲器的2片8K×8bit的芯片,它的內部地址應該是什么

8K×8bit芯片地址線是A0~A12,16位存儲器要給字的地址。所以連系統總線時從A1開始連,連接系統總線的A1~A13。下圖的表格中每一行低12位地址A0~A11是任意的,對應4KB,2片8KB的芯片位擴展之后總容量是16KB,對應前4行。前4行對應內存地址譯碼電路的1個輸出,用來選擇這2片8KB的芯片

后2行對應另外一個輸出,選擇的是2片4KB芯片位擴展之后的16位存儲器

內存地址譯碼電路的輸入應該是高位地址,A13雖然是SRAM內部地址的高位,也要參與地址譯碼,這樣才能保證不參與地址譯碼的A0~A12能包含全0到全1的所有組合

?

然后畫具體電路

首先畫SRAM芯片

先畫2片8KB的芯片。第一片8KBSRAM芯片的引腳首先是數據線D0~D7,這8根線直接連8086系統總線的低8位D0′~D7′,這樣連它就是偶地址存儲體。然后地址線A0~A12連8086的系統總線A1′~A13′(注意從A1′開始連)。讀信號OE―連內存讀MEMR′―,寫信號WE―連內存寫MEMW′―。最后一個是片選CS―,偶地址存儲體要被選中應該有一個或門,或門的輸出是它的片選,或門的一個輸入是偶地址存儲體的選擇信號A0′,另外一根線接地址譯碼電路的第一個輸出

片選和地址譯碼電路的輸出有關,可以留到最后畫

第二片8KBSRAM芯片作為奇地址存儲體,或門的輸出是它的片選,或門的輸入是奇地址存儲體的選擇信號BHE′―和和第一片相同的地址譯碼電路輸出,數據線D0~D7連接系統總線數據線高8位D8′~D15′,地址線,讀信號OE―,寫信號WE―的連法和第一片一樣

因為2個芯片是位擴展的,這2個芯片受地址譯碼電路同一個輸出的控制。所以為了畫起來方便下圖把這個芯片的片選畫在上面2個挨著

再看2片4KB的芯片,畫法幾乎一樣。同樣數據線8根線D0~D7一個作為偶地址存儲體連系統總線的低8位D0′~D7′,一個作為奇地址存儲體連系統總線的高8位D8′~D15′。地址線12根線A0~A11連系統總線A1′~A12′。讀信號OE―和寫信號WE―所有芯片的連法都一樣。片選的套路也一樣,用或門輸出,輸入端是A0(偶地址存儲體)或BHE′―(奇地址存儲體)和地址譯碼電路的另外一路輸出

?

再畫內存地址譯碼電路

限定高位地址要滿足的規律。按照剛才的分析,內存地址譯碼電路的輸入應該從A13′開始一直到A19

上表中A15,A14,A13′這3根線一共就3種組合,用3-8譯碼器74LS138實現較方便,分別接C,B,A這3根線。2種組合對應Y1―和Y2―,Y1―和Y2―任何一個輸出低電平,地址譯碼電路的第一路輸出都應該是低令2片8KB芯片的片選有效,故Y1―和Y2―這2根線經過一個與門之后合成一個信號輸出。Y3―是另外一路輸出,用來選中2片4KB的芯片

畫的時候如果不希望線連的太長,可以給輸出信號起名字(如下圖的CS8K表示8KB芯片的片選信號),另一邊起相同的名字,默認兩根連在一起

高4位地址A16~A19限定上表的條件就可以。高2位地址A19,A18都得是高電平,用一個與門接到高有效的允許G1。A17,A16都得是低電平,用或門接到低有效的允許G2A。此外這是一個內存地址譯碼電路,只有當CPU訪問內存時它輸出才有可能是低電平,此時內存讀MEMR′―和內存寫MEMW′―必然有一個是低電平,經過一個與門接到低有效的允許G2B

不用的Y―可以不畫

?

如果要求畫驅動,則還需要再增加一些東西驅動那些接了好幾處的信號

驅動單向信號A0~A13,BHE―,MEMR―,MEMW―用單向驅動器74LS244,允許接地令其永遠有效

驅動雙向數據總線D0~D7用雙向驅動器74LS245。需要2片,一片A邊接系統總線低8位D0~D7,B邊是驅動后的D0′~D7′,把需要通過低8位數據線傳輸數據的芯片的片選信號CS1―和CS3―加一個與門接到其輸出允許OE―。一片A邊接系統總線高8位D8~D15,B邊是驅動后的D8′~D15′,把需要通過高8位數據線傳輸數據的芯片的片選信號CS2―和CS4―加一個與門接到其輸出允許OE―。方向控制DIR都接內存讀MEMR′―

經過驅動的信號可以加一撇

?

在這個基礎上編寫匯編程序

如果按8位字節來寫和比較。首先初始化段寄存器DS和指針寄存器DI,循環次數放到CX,每次寫入的數據內容放在AL,初值為0。然后循環,每寫一個數據DI和AL的內容加1指向下一個字節。再循環比較,循環之前的準備基本和上面一樣,初始化指針寄存器SI,循環次數放到SI,比較的數據內容放在AL。比較過程中如果發現不一樣就跳轉到錯誤程序,如果一樣則AL和SI加1繼續循環,如果循環正常退出說明所有單元正確,置一個正確標志后跳到最后

如果按16位字,在剛才的基礎上稍微改一點。循環次數減半,每次寫入的數據內容放在AX,初始低8位是全0高8位是全1。每次循環寫入后DI加2指向下一個字,AX低8位和高8位分別加2。比較時也類似

?

?

?

只讀存儲器 (ROM) 及接口設計

非易失性存儲器,掉電之后內容不丟失

?

紫外線可擦除只讀存儲器EPROM

這里對一些應該不太重要的硬件細節記得比較簡略

?

若利用全地址譯碼將EPROM2764接在8088內存首地址為A0000H的內存區,試畫連接圖

擦除時用紫外線照石英窗口15~20min,擦干凈時每單元里內容均為FFH,編程寫入時把期望變成0的那些位變成0

?

?

例:利用2732(8K×8bit SRAM,A12~A0)和6264(4K×8bit EPROM,A11~A0)構成從00000H~02FFFH的ROM存儲區和從03000H~06FFFH的RAM存儲區。畫出與8088系統總線的連接圖。(不考慮板內總線驅動)

?

ROM區:(2FFF+1) / 400 = C,共12KB → 需3片

RAM區:4000 / 400 = 10,共16KB → 需2片

?

如果將SRAM芯片改成8K×4bit,則

?

?

電可擦除只讀存儲器EEPROM (E2PROM)

?

98C64寫之前不需要擦除,直接給寫的時序就能夠把原來的內容覆蓋掉寫入新的數據

讀的時序和SRAM,EPROM都一樣,主要看怎么寫入

下圖是一個寫的時序,在整個寫的過程中讀信號OE―必須無效,首先A12~A0這13根地址線給地址選中內部的某一單元,整個過程中片選信號CE―有效選中該芯片。然后D7~D0數據線上給要寫的數據,地址數據穩定后在寫信號WE―上給負脈沖,該負脈沖的最小寬度是100ns。在負脈沖的上升沿把地址還有數據寫入到芯片內部的一個緩存,上升沿結束之后,芯片內部才真正開始把數據寫入到指定的單元,這個寫的過程是比較慢的,大概需要5~10ms,忙信號READY/BUSY―會輸出低電平,READY/BUSY―再次變成無效時數據才真正寫完

?

?

?

用98C64構成8088的內存

把芯片內部所有的單元寫入55H

?

如果想要提高效率,可以設計一個輸入接口讀READY/BUSY―信號當前的狀態,如果為低電平忙則等待,如果為高電平不忙就馬上寫下一個數據。把READY/BUSY―信號通過一個三態門連接到數據線,CPU要查詢這根線時三態門才打開把狀態輸出到數據線上,以防止總線競爭

控制端控制這個三態門什么時候該打開,什么時候該關閉。如果把這個輸入接口映射到內存地址空間就給內存地址譯碼電路,要映射到接口地址空間就給接口地址譯碼電路。下圖顯然是接口地址譯碼電路

READY/BUSY―是一個漏極開路的引腳,輸出應該加上拉電阻。此外下圖還加了一個不太重要的濾波電容

這里和下一章有點關系??梢韵瓤春竺?#xff0c;回頭再看會比較好理解

這樣原來的延時程序就可以改成查詢方式。通過IN指令從內存地址7000H讀進8位數據到AL,最低位即反映READY/BUSY―信號的狀態。再用TEST指令將AL高7位清0(只影響標志位,不回送結果),若結果為0,說明READY/BUSY―信號為低電平,芯片正忙,則跳轉繼續循環等待。直到芯片真正把數據寫入到對應單元,READY/BUSY―變為高電平,結果為1時才不再跳轉順序執行下面的指令

然后講了下為什么要把忙信號設計成漏極開路

?

?

?

閃速E2PROM : Flash

對于E2PROM,需要快寫必須一次寫一頁,按字節寫速度慢。編程時間長、容量小

Flash : 容量大,編程速度快。成本低、密度大。應用廣泛

本章后面的內容都是了解性的,可以自己看對應的錄播(10.18后半節)和課件

?

輸入/輸出技術

程序查詢 I/O 方式

無條件傳送方式

有一些最簡單的外設不需要查詢,可以隨時給它發命令,隨時讀它的狀態,這種外設可以采用無條件傳送的方式

?

輸入:開關、…

輸出:發光二極管、繼電器、步進電機、…

?

輸入設備

下圖中外設是開關,10K的上拉電阻經過開關接地,電容起到消抖的作用。要讀該外設的狀態,不能直接連接到系統總線,要經過三態門以避免總線競爭

CPU要訪問該外設時才允許把這根線的狀態輸入到系統總線的某一根數據線上,否則這根線應該和系統總線沒有任何關系

74LS244有8個三態門,我們只需要接到其中某一個的輸入,該三態門的輸出接到系統總線數據線的最低位D0

三態門的控制端,允許信號OE―接一個或門。或門的一個輸入端接接口讀信號IOR―,另外兩個輸入端接譯碼的輸出,譯碼的輸入是低16位地址線

下圖連的是8088的總線。但不管是8086還是8088訪問接口都只需要用到低16位地址線

這里簡化了AEN信號,AEN應為低電平表示CPU在控制總線而不是處在DMA狀態

?

不難得接口地址是FFF7H。有了該接口地址之后可以寫一段匯編程序。首先接口地址FFF7H傳送到DX,因為通常不管是IN指令還是OUT指令都要求接口地址得在DX,然后執行IN指令,從地址為FFF7H的接口讀8位數據到AL,AL的最低位反映的就是開關的狀態。接下來用AND指令將高7位清0,如果結果為0說明A開關閉合,跳轉到ON標號執行,否則說明開關斷開,跳轉到OFF標號執行

?

輸出設備

下圖中反相器加發光二極管加限流電阻是一個外設,總共有8個外設。雖然直接連到系統總線的數據線不會造成總線競爭,但是系統總線是分時使用的公共信號線,故必須要接具有存儲能力的鎖存器

鎖存器74LS273的輸出Q0~Q7接8個外設,輸入D0~D7分別接系統總線數據線的D0~D7

鎖存信號(寫信號)CLK接一個或門?;蜷T的一個輸入端接接口寫信號IOW―,另外兩個輸入端接接譯碼的輸出,譯碼的輸入是低16位地址線

?

不難得接口地址是0000H。具體的控制程序先把接口地址送到DX,然后把要往接口寫的數據送到AL,再執行OUT指令把數據寫入鎖存器,其輸出在下次改寫前都保持不變

?

剛才針對的都是8088的8位總線,現在要設計16位總線的8086的接口

下圖中有16個外設,用2片74LS273構成一個16位的接口

上面的74LS273作為偶地址存儲體,輸入D0~D7連系統總線數據線的低8位D0~D7,譯碼時加A0必須為低電平的條件

下面的74LS273作為奇地址存儲體,輸入D0~D7連系統總線的高8位D8~D15,譯碼時加BHE―必須為低電平的條件

用3-8譯碼器做接口地址譯碼,輸入為地址A1~A15和IOW―

?

不難得偶地址存儲體的地址為3804H,奇地址存儲體的地址為3805H。程序首先做偶地址8位寫。把偶地址存儲體的地址放在DX,然后把要寫入的數據放在AL。再執行OUT指令,該指令執行時用的是8位的AL,是8位接口寫,并且接口地址是偶地址,會把數據寫入到上面的74LS273,不會影響到下面的74LS273

然后做奇地址8位寫和16位寫

?

?

?

查詢方式

查詢方式的基礎是必須要有能讀取外設當前狀態的輸入接口,根據外設的不同狀態決定應該對外設采取什么樣的操作

?

下圖中外設引腳有8根數據線D0~D7,鎖存信號(寫信號)STB―,忙信號BUSY。忙信號為高電平則等待,忙信號為低電平則把要寫入的下一個數據放在8根數據線上,當數據穩定之后在STB―給一個寬度大于100μs的負脈沖,在負脈沖的上升沿把數據寫入到外設。寫入的數據內部需要花一定時間處理,一旦寫完則BUSY馬上變為高電平。當忙信號再次變為低電平,說明上一個數據已經處理完,然后再重復上面的過程

?

現在要設計基于該外設的接口

要設計輸出接口來給外設提供8位數據和鎖存信號,輸入接口讀外設BUSY信號當前的狀態。輸出接口用鎖存器實現,輸入接口用三態門實現

第一個輸出接口要提供8位的數據,需要一個74LS273,一邊D0~D7接系統總線數據線D0~D7,一邊Q0~Q7接外設,CLK接一個或門,或門的一個輸入端接IOW―,另外一端接地址譯碼電路的一個輸出

另一個輸出接口的74LS273只用到其中的一位,其輸入接某一根系統總線數據線,輸出接STB―,CLK接一個或門,或門的一個輸入端接IOW―,另外一端接地址譯碼電路的一個輸出

輸入接口的74LS244只用到其中的一個三態門,其輸入接BUSY,輸出接某一根系統總線數據線。OE―接一個或門,或門的一個輸入端接IOR―,另外一端接地址譯碼電路的一個輸出

再用3-8譯碼器實現接口地址譯碼電路,需要的3個輸出為Y0―~Y2―,輸入為低16位地址A0~A15

?

不難得Y0―~Y2―對應的接口地址分別為02F8H,02F9H,02FAH

?

編程首先把段的起始地址的高16位D200H通過通用寄存器傳到DS,然后用寄存器間接尋址就可以訪問到內存從這個單元開始的這些數據。指針寄存器可以是BX,SI,DI,這里用BX,將BX初值置為0。循環次數1000放在CX

初始化STB―,STB―寫時給負脈沖,不寫時應該是高電平。OUT指令把AL的內容01H寫入到接口地址02F9H對應的中間的74LS273令Q0=1,將STB―置為高電平為后面寫數據做準備

判斷BUSY的狀態。IN指令讀地址為02FA的接口,讀取的數據放在AL。再用AND指令將低7位清0只保留最高位。如果結果不為0,說明BUSY為高電平,就跳轉回上面再讀,一直循環到結果為0,BUSY變為低電平才順序執行后面的指令

數據輸出。利用寄存器間接尋址,DS為默認段寄存器,BX存段內偏移,從內存D2000H取數據放在AL。OUT指令將該數據寫入接口地址02F8H對應的上面的74LS273,給外設提供數據

數據已經準備好,將STB―置為低電平,延時100μs后再將STB―置為高電平。在STB―的上升沿將數據寫入到外設

寫完之后BX內容加1指向內存的下一個單元,然后繼續循環。總共循環1000次,每次都先判斷BUSY忙則等待,不忙再寫下一個數據

然后引申講了下輸出接口和輸入接口占用同一個接口地址等簡化軟硬件的方法

?

多外設的查詢控制

這種方式不好。因為如果某一個外設壞了永遠處于沒準備好的狀態,CPU就會老是等待,其他外設也永遠得不到服務

?

這種方式有優先級的概念,會偏向認為先查詢的外設更重要

?

如果不需要優先級,機會均等。采用這種方式

?

中斷方式

x86處理器處理中斷的過程在第二章講CPU引腳時已經介紹過,可以查閱當時的筆記。這里介紹來自INTR引腳的中斷請求,一般對應的都是外設或接口的中斷請求

?

?

假設CPU執行到某條指令,通過INTR引腳來一個中斷請求。這種情況下若滿足中斷響應的條件:標志寄存器中中斷允許標志位IF為1處于開中斷狀態,當前這條指令執行完才會響應中斷請求

首先要保護當前的斷點,依次將Flags,CS,IP的內容壓入堆棧,并將標志寄存器中的中斷允許標志位IF和陷阱標志位IF清0關中斷,這樣再從這個引腳來中斷請求CPU就不會響應了

標志寄存器教材叫程序狀態字PSW,即下圖的Flags。子程序調用則不需要保護Flags的內容

1413:0105表示內存地址,左側是段寄存器的內容,右側是段內偏移

然后CPU會通過INTA―連續送出兩個負脈沖。8259接收到第一個負脈沖就知道CPU正在響應剛才的中斷請求,它會準備好發出中斷請求的中斷源的8位中斷向量碼,等第二個負脈沖來時將其放在低8位數據線上讓CPU采樣得到

CPU會根據中斷向量查從內存地址0開始放的中斷向量表的對應行,獲取對應的中斷服務程序的入口地址。中斷向量表每一行4個字節,前2個字節存段內偏移賦值給IP,后2個字節存段寄存器的內容賦值給CS,下一條指令就會跳轉到從中斷服務程序的第一條指令的地址開始取并執行

注意是小端存儲,小地址對應低字節,大地址對應高字節

中斷服務程序的結構和子程序很像,也要保護現場,將要修改的控制寄存器的內容先壓入堆棧,用完之后再恢復現場,然后再中斷返回。執行中斷返回指令IRET時會從堆棧彈出3個數恢復Flags,CS,IP,返回到剛才被打斷的指令的下一條指令繼續執行

CPU硬件在響應中斷時會自動關中斷。如果中斷服務程序允許中斷嵌套,在保護現場之后加開中斷指令STI,恢復現場之前再用關中斷指令CLI

這里內部中斷理解成中斷源在CPU內部,跟調試無關的那些中斷,如除法錯誤中斷。跟調試有關的那些中斷,如單步中斷和斷點中斷通常優先級最低

?

?

?

可編程中斷控制器8259

可對8個中斷源實現優先級控制

支持多片級聯,一個主片可以有8個從片,可擴展至對64個中斷源實現優先級控制

可編程設置不同工作方式

根據中斷源向x86提供不同中斷類型碼

可編程就是該芯片內部有一些寄存器,往寄存器里面寫入不同的內容就可以具有不同的功能,可以工作在不同的模式下

?

8259內部結構

8259的引腳:

中斷源中斷請求輸入IR0~IR7

雙向數據總線D0~D7

中斷請求INTR,中斷應答INTA―

讀信號RD―,寫信號WR― : 要對內部寄存器進行讀寫,讀寫時傳數據通過8根數據線

片選信號CS― : 支持多片級聯,要看訪問哪一片

地址A0 : 8259只有一根地址線,只需要占用2個接口地址

上圖中還有4個引腳,這幾個引腳和級聯有關,如果只是單片使用用不上

?

需要了解3個寄存器:

中斷請求寄存器IRR (INTERRUPT REQUEST REG):保存從IR0~IR7來的中斷請求信號,某位=1表示對應的IRi有中斷請求

中斷屏蔽寄存器IMR (INTERRUPT MASK REG):存放中斷屏蔽字,某位=1表示對應的IRi輸入被屏蔽

中斷服務寄存器ISR (IN - SERVICE REG):保存正在服務的中斷源,某位=1表示對應的IRi中斷正在被服務

?

中斷優先權判別電路 (PRIORITY RESOLVER): 確定是否向CPU發出中斷請求,中斷響應時確定ISR的哪位應置位及把相應中斷的類型碼放到數據總線上

?

?

下圖中即表示8086/8088 CPU正在執行IR6和IR4兩個引腳所對應的中斷源的中斷服務程序,CPU同時執行兩個中斷源的中斷服務程序,很顯然發生了中斷嵌套。引腳IR2,IR3,IR5同時發中斷請求,作為8259如果是固定優先級,編號小的優先級高??紤]到IR2被屏蔽,且IR3優先級高于IR6和IR4,8259會通過INT向CPU發一個IR3的中斷請求

CPU通過一系列過程響應中斷,再通過INTA―給8259送連續2個負脈沖。8259接收到第一個負脈沖后,因為CPU馬上要執行到IR3對應的中斷源的中斷服務程序,會將ISR的第3位置1,IRR的第3位清0

?

CPU在中斷服務程序執行完之后通知8259可以將ISR的相應位清0。在中斷服務程序的最后恢復現場之前要給8259發一個EOI中斷結束命令。要實現EOI功能可能需要3條指令,先將8259的偶地址(8259只有一根地址線,地址線給0是偶地址,給1是奇地址)放到DX,要寫入的內容放在AL,再用OUT指令把AL的內容寫入到DX所指向的接口

MOV DX,8259偶地址 MOV AL,20H OUT DX,AL

寫的數是20H,是一般EOI命令。允許中斷嵌套并且是正常優先級的情況下就會在在中斷服務程序的末尾向8259發一個一般EOI命令。8259接收到命令后將ISR中優先級最高的那一位清0,因為有正常優先級概念的情況下,如果允許中斷嵌套,最先執行完的中斷服務程序肯定是優先級最高的

?

8259工作方式

緩沖方式可以設成非緩沖和緩沖。如果設置成工作在緩沖方式,雙向數據線需要加一個74LS245驅動器,其OE―信號由8259的SP―/EN―作為輸出引腳提供。如果沒有工作在緩沖模式下,SP―/EN―作為輸入引腳讓多片級聯時8259可以知道自己是主片還是從片,其接到高電平為主片,接地為從片

書上后面的例子都沒有讓8259工作在緩沖模式下

?

中斷是否允許嵌套即中斷程序是否允許被優先級更高的中斷源打斷。如果不允許中斷嵌套就設置中斷結束方式為自動EOI方式。在接收到中斷應答的第二個負脈沖時就會將ISR的內容清0,此時可以簡單地認為ISR的內容總是0,不會記錄CPU正在執行哪一個中斷源的中斷服務程序,所以也就無法實現帶優先級的各種中斷嵌套。這樣在編寫中斷服務程序時就不用加STL指令,末尾也不需要向8259發EOI命令

?

屏蔽方式可以設成一般屏蔽和特殊屏蔽。一般屏蔽就是正常優先級的概念,即如果CPU正在執行某一個中斷源的中斷服務程序,同級的和優先級更低的中斷源是不能打斷當前的中斷服務程序的,這樣在中斷服務程序的末尾要向8259發一個一般EOI命令。如果設置成特殊屏蔽方式就沒有優先級的概念,只要不是同級的,任何一個其他的中斷源都可以打斷當前的服務程序,究竟哪一個中斷服務程序最先執行完不一定, 這樣在中斷服務程序的末尾要向8259發一個特殊EOI命令,里面包含清0的那一位的編號,明確告訴8259應該把ISR的哪一位清0

教材上后面的例子都讓8259工作在一般屏蔽方式

?

剛才舉的這些例子都默認8259工作在固定優先級,優先級順序從高到低為IR0~ IR7,還可以設置成循環優先級

自動循環優先級:

中斷源輪流處于最高優先級,即自動中斷級循環

初始優先級順序可由編程改變

某中斷請求IRi被處理后,其優先級別自動降為最低,原來比它低一級的優先級上升為最高級

指定循環優先級:

優先級排列順序可編程改變

加電后8259A的默認方式,默認優先級順序從高到低為IR0~IR7

?

最后看8259是否需要多片級聯。如果不需要級聯單片工作設置成一般嵌套方式。如果是多片級聯主片設置成特殊嵌套方式,從片設置成一般嵌套方式

8259級聯:

單片8259A可支持8個中斷源

采用多片8259A級連,可最多支持64個中斷源。n片8259A可支持7n+1 (n≤9) 個中斷源

級聯時只有一片8259A為從片,其余的均為從片。只有主片有能力向CPU發中斷請求。從片的中斷請求連到主片的某一個IRi引腳,從片所有引腳發的中斷請求都得從該引腳走,從片再向主片發中斷請求,主片再向CPU發中斷請求

涉及到的8259A引腳包括:CAS0?CAS2,SP―/EN―,IRi,INT

?

通過SP―/EN―引腳8259得知自己是主片還是從片,其接高電平是主片,接地是從片。ICW3寫什么內容和級聯狀態下怎么連有關系,通過初始化過程向ICW3寫入適當的內容,讓主片知道IRi引腳接的是從片還是中斷源,讓從片知道接的是主片的IRi引腳

8259有4個初始化命令字ICW1~ICW4,還有3個操作命令字OCW1~OCW3。OCW1其實就是IMR,所以8259內部總共有9個寄存器

連電路時INTA―接主片和從片,所有8259都能接收到CPU從INTA―發來的兩個連續負脈沖。主片通過INTA―接收到第一個負脈沖后會對ISR和IRR置位。主片替IRi向CPU發中斷請求,就會通過CAS0~CAS2這3根線送級聯地址i給兩個從片,兩個從片在中斷應答的第一個負脈沖會檢查這3根線的狀態與ICW3內容作比較,一致則對ISR和IRR置位,并在第二個負脈沖來時提供中斷向量

一般嵌套方式與特殊全嵌套方式的區別:

主片能夠區分引腳哪一個接中斷源,哪一個接從片。只有接從片的引腳才允許同級的中斷源打斷當前的中斷服務程序

?

?

8259編程使用

內部寄存器的尋址方式:

需要CS―,A0,RD―,WR―和D4,D3的配合。內部寄存器的訪問方法如下表

?

為了能夠區分內部究竟訪問的是哪一個寄存器,寫入數據的某一位在8259內部也是當地址來用的

如8259要能正常工作必須要有初始化的過程,往4個ICW里寫入事先設計好的內容。首先要寫ICW1,ICW1對應的是8259的偶地址,即A0=0的情況。所以如果想要初始化8259,第一步就要往8259的偶地址里寫入D4位為1的一個數據

Icw1的結構如下。D2和D5~D7這幾位沒有用到,LTIM表示IR0~IR7這8根線是高電平還是上升沿有效,SNGL表示是單片工作(級聯控制字ICW3不需要寫)還是多片級聯,IC4表示是否要寫ICW4

一旦ICW1被寫就啟動了一個初始化的過程,緊接著要馬上寫后面這幾個ICW,往奇地址里面連續寫入若干個數:

若現在寫ICW1,將其配置成多片級聯并且要寫ICW4就要寫3個數,分別自動寫入到ICW2~ICW4

如果寫的內容規定是單片工作且要寫ICW4,就要寫2個數,分別自動寫入到ICW2和ICW4

如果寫的內容規定是單片工作且不要寫ICW4,就要寫1個數,到ICW2

一旦初始化的過程完成之后,后面這些OCW隨時都可以寫,按什么順序寫都無所謂,寫不寫都可以

電路連好后怎么檢查8259能否正常工作,或者說它的寄存器能否正常讀寫?

OCW1是8259內部唯一一個既可以寫又可以讀的寄存器,它對應奇地址

初始化完之后往8259的奇地址里面寫入全0,再讀出來比較一下是否為全0。再寫入全1,讀出來比較一下是否為全1。如果都對就認為8259內部的這些寄存器能夠正常寫入,數據線和地址線的連法應該也沒有問題

?

ICW1:初始化字

上面已經進行了說明

ICW2:中斷向量碼

ICW3:級聯控制字

ICW4:中斷結束方式字

?

OCW1:中斷屏蔽字

OCW2:中斷結束和優先級循環

OCW3:屏蔽方式和讀出控制字

?

?

中斷方式實現方法

1.8259連接(硬件)

若要連接到8086的系統總線。8259地址線只有一根,占用2個接口地址,如果想把它映射到偶地址上,或者說作為一個偶地址存儲體,其8根數據線要連接到系統總線數據線的低8位。A0是偶地址存儲體的選擇信號,地址線從A1開始,故這塊應該連到A1上,A1作為芯片的內部地址,高位地址從A2開始

?

如果要映射到偶地址最好讓A0也參與譯碼,限定A0是0。下圖中因為A0沒有參與譯碼其實應該占用4個接口地址FF00H~FF03H,但實際上如FF00H和FF01H這兩個地址中只能用FF00H,因為FF01H對8086來講是奇地址,8086不管是訪問內存還是接口,如果訪問的是奇地址就會通過高8位的數據線來傳遞數據。所以如果你用FF01H這個地址讀8259的某一個寄存器,IN指令執行時8086只會采樣數據線的高8位,雖然8259芯片已經輸出了寄存器的內容,但它放在了數據線的低8位,得不到數據

所以我們在連數據線時這8根線連接到系統總線的低8位,8086在訪問該8259芯片時就必須要用偶地址,用奇地址訪問不到芯片內部的寄存器。FF01H和FF03H這2個接口地址雖然被占用但是不能用,如果不想浪費,就應該加限定A0是0的條件,這樣電路就只占用2個接口地址,對于8086來講這兩個都是偶地址,對于8259來講,FF00H是8偶地址,FF02H是奇地址

如果計算機中有DMA存在,應該有限定AEN―是低電平的條件

?

2.編寫初始化程序:8259初始化,設置中斷向量表

在有了硬件的基礎上。計算機剛一加電啟動的過程中,通常由BIOS程序負責對8259的ICW寫入事先設計好的內容來進行初始化讓它工作在期望的模式下

初始化8259:

SET59A:MOV DX,0FF00H ;8259的地址A0=0MOV AL,13H ;寫ICW1,邊沿觸發,單片,需要ICW4OUT DX,ALMOV DX,0FF02H ;8259的地址A0=1MOV AL,48H ;寫ICW2,設置中斷向量碼OUT DX,ALMOV AL,03H ;寫ICW4,8086/88模式,自動EOI;非緩沖,一般嵌套OUT DX,ALMOV AL,0E0H ;寫OCW1,屏蔽IR5、IR6、IR7;(假定這3個中斷輸入未用)OUT DX,AL

?

下例檢查硬件電路能否正常工作,可以認為和前面的初始化沒有關系

;將00H與FFH分別寫入IMR,并將其讀出比較 MOV DX,0FF02H MOV AL,0 OUT DX,AL ;寫OCW1,將00H寫入IMR IN AL,DX ;讀IMR OR AL,AL ;判斷IMR內容為00H否 JNZ IMRERR MOV AL,0FFH OUT DX,AL IN AL,DX ADD AL,1 JNZ IMRERR

?

設置中斷碼:

中斷向量碼初始化位48H,中斷處理程序入口地址的標號為CLOCK,設置中斷向量表

法1 直接寫中斷向量表

INTITB: MOV AX,0MOV DS,AX ;將內存段設置在最低端MOV SI,0120H ;n=48H, 4×n=120HMOV AX,OFFSET CLOCK ;獲取中斷處理程序首地址的段內偏移地址MOV [SI],AX ;段內偏移地址寫入中斷向量表4×n地址處MOV AX,SEG CLOCK ;獲取中斷處理程序首地址的段地址MOV [SI+2],AX ;段地址寫入中斷向量表4×n+2地址處

?

法2 利用DOS功能調用

MOV AH,25H ;功能號 MOV AL,48H ;中斷向量碼 MOV DX,SEG CLOCK MOV DS,DX ;段地址→DS MOV DX,OFFSET CLOCK ;偏移地址→DX INT 21H

?

3.編寫中斷處理程序

中斷嵌套的實現:

保護現場 (PUSH reg’s)

開中斷 (STI)

中斷服務

中斷服務

關中斷 (CLI)

產生EOI命令

恢復現場 (POP reg’s)

中斷返回

?

產生EOI命令:

上例初始化時設置成自動EOI模式,所以中斷服務程序的末尾沒有必要向8259發EOI命令。如果允許中斷嵌套,工作在一般EOI方式,往8259偶地址中寫入20H相當于發一個一般EOI命令,8259會把ISR置1位中優先級最高的那一位清0

中斷方式實現示例

初始化8259:SET59A

初始化中斷向量表:INTITB

?

中斷處理程序:CLOCK

假設在內存中有連續這么幾個字節的數據,第一個字節由標號TIMER指向,存1/50秒的信息,下一個字節存秒的信息,再下一個字節存分鐘的信息,最后一個字節存小時的信息。并且后三個字節的內容采用壓縮的BCD碼的形式存,1/50秒直接用二進制的形式存

DAA指令會根據當前標志寄存器里面的一些信息決定要不要加6修正

?

DMA的過程之前講過,DMA控制器8237不具體講

可編程8237芯片有4個通道,可以實現內存到接口,內存到內存之間的數據傳送,但是不能實現接口到接口之間的數據傳送

?

到此這章的內容就結束了。后面還講了下TSR時鐘顯示程序和比較新的計算機如何實現中斷和DMA

常用接口器件

思考:計算機和外設之間如何通過接口傳送數據(非DMA)?

最簡單的方式是上一章講的程序查詢或者說直接控制

想讀輸入設備當前的狀態,通過三態門實現接口。給三態門接口地址,只有用IN指令讀地址為這個的接口時,三態門才打開把外設的狀態輸出到系統總線數據線,IN指令最后采樣數據線把外設的狀態讀到CPU內部寄存器

用OUT指令輸出數據,數據只在OUT指令執行的瞬間呈現在數據線上,所以輸出接口需要用鎖存器實現存儲功能

下圖中輸入接口只能讀不能寫,只需要IOR―信號參與地址譯碼。輸出接口只能寫不能讀,只需要IOW―信號參與地址譯碼

?

這種方式CPU利用率較低,大部分時間都花在不停地循環查詢外設。如果想要提高CPU的利用率,外設或者說接口能夠引入中斷功能,外設不忙需要CPU參與時再給CPU發中斷請求

輸出接口里有可以暫存數據的緩沖寄存器,可以判斷該寄存器內容是否為空,即數據是否已被外設取走。如果為空應該向通過INTR―信號向CPU發中斷請求通知CPU緩存已空,能否寫入新的數據。CPU經過一定過程響應中斷,最終進入中斷服務程序,中斷服務程序把要傳輸給外設的下一個數據寫入到接口內部的緩沖寄存器,寫完直接返回。接口檢測到緩沖寄存器寫入新數據,將OBF―信號置低通知外設拿走數據,外設采樣數據線拿走數據處理完后通過ACK―信號發一個負脈沖通知接口數據已被取走。接口將OBF―信號置高,同時再次向CPU發中斷請求重復剛才的過程

輸入接口里也有可以暫存數據的寄存器,可以通知外設緩沖寄存器內容為空可以寫下一個數據。外設通過數據線提供數據,數據穩定后通過STB―信號發一個負脈沖,在負脈沖的上升沿把數據寫入到接口的暫存器中。接口寫入新數據后把IBF信號置高表示輸入緩沖區滿,通過INTR―信號向CPU發中斷請求,CPU響應中斷進入到中斷服務程序,從接口把數據讀走。接口將IBF信號置低,重復剛才的過程

ACK―和STB―不是狀態信號而是脈沖信號

設計雙向的具有中斷功能的輸入/輸出接口,結合上述兩種情況

輸入/輸出接口內部有2個寄存器,從CPU角度一個只能寫不能讀一個只能讀不能寫,可以占用同一個寄存器地址。CPU通過讀狀態寄存器得知產生中斷的原因并做相應處理

?

要實現上述接口,可以直接用可編程并行接口8255

8255一共有3種工作方式:

工作在方式0的輸入相當于三態門,工作在方式0的輸出相當于鎖存器

工作在方式1的輸出相當于具有中斷功能的輸出接口,工作在方式1的輸入相當于具有中斷功能的輸入接口

工作在方式2相當于雙向的輸入/輸出接口

?

8255:可編程并行接口

內部結構及外部引線

8255有A,B,C三個并行接口

每個并行接口都有8根線,A口為PA7~PA0,B口為PB7~PB0,C口分成相互獨立,可以分別配置的高4位PC7~PC4和低4位PC3~PC0

任何一個口都可以工作在方式0,A口還可以工作在方式1和方式2,B口還可以工作在方式1。方式0和方式1可以配置成輸入也可以配置成輸出

工作在方式1和方式2需要借用C口的信號線

若配置8255的A口工作在方式2。PA7~PA0這8根線跟外設之間是雙向的,此外構成其他的一些握手信號STB―,IBF,ACK―,OBF―和INTR―還需要分別借用C口的信號線PC4~PC7和PC3。如果B口剛好工作在方式1,還可以借用C口的另外3根線

A口,B口,C口各有1個8位的緩沖寄存器,此外還有1個控制字,加電啟動后通過寫控制字可以初始化8255,配置具體的哪一個口應該工作在哪種方式下。對這些寄存器進行讀寫和總線間要有地址線A0~A1,數據線D0~D7和讀信號RD―,寫信號WR―,片選信號CS―

另外還多了1個復位信號RESET,直接接到計算機主板的復位電路引腳。計算機剛一加電后復位電路工作產生負脈沖,將8255內部的控制字自動置成事先設置好的狀態即A,B,C口均為輸入以避免總線競爭

?

8255的方式控制字及狀態字

8255的地址線有2根,A,B,C三個口的緩沖寄存器和控制字分別占用地址00,01,10和11

寫地址11,最高位用來區分現在是寫控制字還是將C口寄存器的某一位清0或置1

C口寄存器具體的某一位跟C口的引腳之間一般有對應關系。如C口寄存器的第3位置1,則PC3輸出引腳直接輸出高電平

?

8255的工作方式

?

?

?

8255的尋址和連接使用

方式0:

易得A,B,C口寄存器和控制字的具體接口地址分別是380H,381H,382H,383H

看地址線A0,A1怎么連確定連的是8086還是8088。8259的A0,A1連系統總線的A0,A1連的是8088的系統總線。A0,A1連系統總線的A1,A2連的是8086的系統總線,數據線如果連到系統總線低8位必須要給偶地址,地址譯碼電路加偶地址存儲體選擇信號A0必須是低電平的條件

?

?

8255初始化及應用舉例:方式0 - 打印機接口

除了數據線,外設還要求有鎖存信號STROBE―,要用B口或C口的某一根線提供(負脈沖寬度要求≥1us,無法直接通過較快的總線信號提供)。對外設來講STOROBE―信號是輸入,BUSY信號是輸出,而C口較為靈活,高4位和低4位可以分別配置。可以讓C口的高4位配置成輸出,只能寫不能讀,再隨便選一根線如PC6,C口的低4位配置成輸入,只能讀不能寫,再隨便選一根線如PC1,剛好既可以判斷BUSY信號的狀態,又可以給它送STROBE―信號

?

8255地址:380H~383H

初始化程序:

?

利用8255方式0以程序控制(查詢)方式實現打印機接口

?

?

8255初始化及應用舉例:方式1 - 打印機接口

單穩觸發器將下降沿轉換為寬度為1us的負脈沖

同樣這種情況下PC6輸入引腳和C口寄存器的第6位沒有關系,C口寄存器的第6位是中斷允許位

8255地址:380H~383H

初始化程序:

?

利用8255方式1程序控制(查詢)方式實現打印機接口:

?

利用8255方式1以中斷方式實現打印機接口:

8253:可編程定時器

外部引線及功能

頻率已知的時鐘信號,對時鐘信號進行計數就能達到定時的效果,所以所謂的定時器還有另外一個名字:計數器。8253芯片內有3個計數器,要求寫入計數初值,開始計數后每來一個時鐘信號的下降沿計數值減1

?

3個計數器都有相應的16位寄存器用于寫入計數初值。8根數據線D0~D7寫計數初值時分兩次寫,先寫的對應低8位,后寫的對應高8位

要區分讀或寫的是哪一個寄存器還要有地址線A0~A1。系統總線可見或者說可以訪問的寄存器還有控制字,往控制字寫入不同的內容就可以讓每一個計數器工作在不同的模式下。4個寄存器用2位地址訪問。2根地址線4種組合。00,01,10,11分別對應計數器0,1,2的1計數值寄存器和控制字。地址0,1,2這3個寄存器可寫可讀,地址3寄存器可寫不可讀

此外8253和系統總線這邊的信號還有讀寫信號RD―,WR―,片選信號CS―

?

計數器i有時鐘信號輸入引腳CLKi,用于通知計數值減到0的輸出引腳OUTi,用于暫停計數的門控信號GATEi。GATEi高電平正常計數,低電平暫停計數)

?

?

工作方式

每一個計數器可以工作在6種不同的模式下

?

方式0和方式1產生一個負脈沖

方式0:計數結束產生中斷

寫控制字規定某計數器工作在方式0下后OUT引腳馬上就變為低電平。寫入計數初值n后開始定時計數,計數值減到0后OUT引腳變為高電平。其他方式只要寫控制字規定工作方式后OUT引腳馬上變為高電平

可將其接到8259的一個中斷請求輸入引腳,定時向CPU發出中斷請求

?

方式1:可編程單穩

與方式0不同,方式1寫完計數初值后要等到GATE信號來一個上升沿后才開始計數

可將一個上升沿轉換成一個寬度可編程的負脈沖

?

?

方式2和方式3產生周期信號,方式2產生周期性負脈沖。方式3產生方波

方式2:頻率發生器

方式3:方波發生器

?

?

方式4和方式5隔一定時間后產生寬度為一個時間周期的負脈沖

方式4:軟件觸發旁通

方式5:硬件觸發旁通

?

?

8253的控制字

開始計數時,第一個時鐘下降沿會把計數值從計數值寄存器傳送到減1寄存器,此時不會判斷計數值是否為0。在下一個時鐘周期下降沿才把減1寄存器的內容減1,然后判斷是否為0。故計數初值如果寫0對應的是最大計數值

減1計數器的每次改變都會同步到計數鎖存器,正常工作時這兩個寄存器的內容總是一樣的。計數值寄存器和計數鎖存器占用同一個地址,寫這個地址將計數初值寫入計數值寄存器,讀這個地址讀當前計數鎖存器的內容。減1計數器則不能讀也不能寫。讀之前要給計數器發鎖存命令 ,一旦發鎖存命令后減1計數器和計數鎖存器切斷聯系,計數鎖存器內容不再變化

從系統總線的角度來講,每個計數器好像只有1個相應的16位寄存器,但其實有3個

8253的地址3對應控制字,看起來8253內部好像也只有一個控制字,但實際上內部對應每一個計數器都有其專有的控制字

故每一個計數器內部都有4個寄存器:計數值寄存器,減1計數器,計數鎖存器和控制字

?

8255的尋址及連接

?

8253的初始化及應用

然后講了下以前CPU為8088時計算機主板上跟8253有關的部分電路和電源掉電檢測的例子

?

可編程定時/計數器8253的串聯使用

單個定時/計數器的限制:

?

多個定時/計數器串聯使用:

要求輸出為指定寬度的周期性負脈沖,如何設計?

方法1:

方法2:

?

基于總線的I/O接口設計

總結

以上是生活随笔為你收集整理的西电计科院微机原理与系统设计课程笔记(车向泉版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

1000部夫妻午夜免费 | 日本在线高清不卡免费播放 | 欧洲vodafone精品性 | 日日碰狠狠躁久久躁蜜桃 | 99久久精品无码一区二区毛片 | 欧美黑人性暴力猛交喷水 | 丰满少妇弄高潮了www | 妺妺窝人体色www在线小说 | 亚洲色成人中文字幕网站 | 国产精品.xx视频.xxtv | 免费人成在线视频无码 | 高潮毛片无遮挡高清免费视频 | 国产真人无遮挡作爱免费视频 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲 欧美 激情 小说 另类 | 亚洲国产精品美女久久久久 | 免费乱码人妻系列无码专区 | 久久综合给久久狠狠97色 | 九九热爱视频精品 | 亚洲国产精品久久人人爱 | 夜夜躁日日躁狠狠久久av | 人妻互换免费中文字幕 | 动漫av一区二区在线观看 | 亚欧洲精品在线视频免费观看 | 中文无码成人免费视频在线观看 | a在线亚洲男人的天堂 | 大屁股大乳丰满人妻 | 国产成人综合在线女婷五月99播放 | 久久人人爽人人爽人人片ⅴ | 成 人影片 免费观看 | 国内精品一区二区三区不卡 | 国产精品无码一区二区桃花视频 | 丰满护士巨好爽好大乳 | 强辱丰满人妻hd中文字幕 | 欧美兽交xxxx×视频 | 国产亚洲精品久久久ai换 | 动漫av一区二区在线观看 | 中文字幕乱码中文乱码51精品 | 久久久久久a亚洲欧洲av冫 | 久久熟妇人妻午夜寂寞影院 | 亚洲日韩精品欧美一区二区 | 少妇无套内谢久久久久 | 黑人巨大精品欧美黑寡妇 | 国产真实伦对白全集 | 一本大道久久东京热无码av | 强伦人妻一区二区三区视频18 | 亚洲国精产品一二二线 | av无码久久久久不卡免费网站 | 欧美日韩一区二区综合 | 精品无人区无码乱码毛片国产 | 18精品久久久无码午夜福利 | 精品乱码久久久久久久 | 丰满肥臀大屁股熟妇激情视频 | 一本色道婷婷久久欧美 | 欧美第一黄网免费网站 | 国产亚av手机在线观看 | 免费看男女做好爽好硬视频 | 日韩无套无码精品 | 精品久久久久久亚洲精品 | 日本欧美一区二区三区乱码 | 国产极品美女高潮无套在线观看 | 亚洲国产精品久久久久久 | 亚洲一区二区三区播放 | 中文字幕亚洲情99在线 | 一本久道久久综合婷婷五月 | 男女下面进入的视频免费午夜 | 日韩欧美成人免费观看 | 性色av无码免费一区二区三区 | 乱人伦人妻中文字幕无码 | 乌克兰少妇性做爰 | а√资源新版在线天堂 | 天海翼激烈高潮到腰振不止 | 亚洲色偷偷偷综合网 | 中文字幕人妻无码一夲道 | 国产乡下妇女做爰 | 性史性农村dvd毛片 | 波多野结衣 黑人 | 香港三级日本三级妇三级 | 国产亚洲精品久久久闺蜜 | 国产亚洲精品久久久久久国模美 | 欧美兽交xxxx×视频 | 精品一区二区三区无码免费视频 | 国产女主播喷水视频在线观看 | 夜夜影院未满十八勿进 | 色婷婷香蕉在线一区二区 | www一区二区www免费 | 亚洲中文字幕无码一久久区 | 国产精品人人爽人人做我的可爱 | 欧美阿v高清资源不卡在线播放 | 曰本女人与公拘交酡免费视频 | 久久熟妇人妻午夜寂寞影院 | 欧美肥老太牲交大战 | 特级做a爰片毛片免费69 | 国产色在线 | 国产 | 亚洲狠狠色丁香婷婷综合 | 日本在线高清不卡免费播放 | 九月婷婷人人澡人人添人人爽 | 国产免费久久久久久无码 | 国产亚洲视频中文字幕97精品 | 欧美日韩精品 | 精品国产成人一区二区三区 | 丰满妇女强制高潮18xxxx | av无码不卡在线观看免费 | 成人无码精品一区二区三区 | 东京无码熟妇人妻av在线网址 | 正在播放东北夫妻内射 | 妺妺窝人体色www婷婷 | 欧美大屁股xxxxhd黑色 | 高清无码午夜福利视频 | 无套内射视频囯产 | 97久久精品无码一区二区 | 四虎影视成人永久免费观看视频 | 国产午夜福利亚洲第一 | 在线看片无码永久免费视频 | 亚洲人成网站在线播放942 | 粉嫩少妇内射浓精videos | 亚洲人成影院在线无码按摩店 | 亚洲色欲色欲天天天www | 天天躁夜夜躁狠狠是什么心态 | 男人和女人高潮免费网站 | 国产超级va在线观看视频 | 精品国产精品久久一区免费式 | 国产一精品一av一免费 | 99久久久无码国产aaa精品 | 国产99久久精品一区二区 | 亚洲国产精品一区二区第一页 | 中文字幕色婷婷在线视频 | 曰韩无码二三区中文字幕 | 日本熟妇浓毛 | a在线观看免费网站大全 | 青青草原综合久久大伊人精品 | 久久99热只有频精品8 | 免费观看激色视频网站 | 精品无人国产偷自产在线 | 亚洲 a v无 码免 费 成 人 a v | 色综合久久久无码中文字幕 | 日韩欧美群交p片內射中文 | 国内揄拍国内精品人妻 | 精品aⅴ一区二区三区 | 性开放的女人aaa片 | 午夜嘿嘿嘿影院 | 捆绑白丝粉色jk震动捧喷白浆 | 亚洲精品成a人在线观看 | 亚洲日韩av一区二区三区中文 | 亚洲中文字幕乱码av波多ji | 成人动漫在线观看 | 99国产欧美久久久精品 | 性色欲情网站iwww九文堂 | 亚洲国产精品成人久久蜜臀 | 夜夜影院未满十八勿进 | 自拍偷自拍亚洲精品10p | 东京热男人av天堂 | 日韩 欧美 动漫 国产 制服 | 欧美野外疯狂做受xxxx高潮 | 国产欧美精品一区二区三区 | 精品 日韩 国产 欧美 视频 | 97资源共享在线视频 | 亚洲 日韩 欧美 成人 在线观看 | 天天做天天爱天天爽综合网 | 精品成在人线av无码免费看 | 中国女人内谢69xxxx | 国精产品一区二区三区 | 免费观看又污又黄的网站 | av无码久久久久不卡免费网站 | 一本色道久久综合亚洲精品不卡 | 夜先锋av资源网站 | 在线观看国产一区二区三区 | 亚洲国产精品一区二区第一页 | 内射爽无广熟女亚洲 | 久久久av男人的天堂 | 国产精品美女久久久网av | av无码久久久久不卡免费网站 | 日日干夜夜干 | ass日本丰满熟妇pics | 又粗又大又硬又长又爽 | 亚洲va中文字幕无码久久不卡 | 一本色道久久综合亚洲精品不卡 | 欧美国产日产一区二区 | 无遮挡国产高潮视频免费观看 | 免费人成在线观看网站 | 国产一区二区三区日韩精品 | 亚洲自偷精品视频自拍 | 人人妻人人澡人人爽欧美一区 | 国产亚洲精品久久久ai换 | 亚洲自偷精品视频自拍 | 国产一区二区三区四区五区加勒比 | 午夜精品一区二区三区在线观看 | 亚洲欧美中文字幕5发布 | 中国女人内谢69xxxxxa片 | 18禁黄网站男男禁片免费观看 | 人妻插b视频一区二区三区 | 久久99精品国产麻豆 | 国产成人亚洲综合无码 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 中文字幕av伊人av无码av | 日韩精品无码一本二本三本色 | 欧美zoozzooz性欧美 | 黑人粗大猛烈进出高潮视频 | 亚洲国产精品久久人人爱 | 又大又黄又粗又爽的免费视频 | 男女超爽视频免费播放 | 欧美 亚洲 国产 另类 | 欧洲熟妇精品视频 | 久久综合色之久久综合 | 日本乱偷人妻中文字幕 | 国产办公室秘书无码精品99 | 在教室伦流澡到高潮hnp视频 | 色综合久久中文娱乐网 | 国产麻豆精品精东影业av网站 | 内射老妇bbwx0c0ck | 女人被爽到呻吟gif动态图视看 | 国产精品永久免费视频 | 国产高潮视频在线观看 | 成熟女人特级毛片www免费 | 久久综合网欧美色妞网 | 1000部啪啪未满十八勿入下载 | 水蜜桃亚洲一二三四在线 | 成人欧美一区二区三区黑人免费 | 99国产欧美久久久精品 | 捆绑白丝粉色jk震动捧喷白浆 | a在线观看免费网站大全 | 大肉大捧一进一出视频出来呀 | 中国大陆精品视频xxxx | 亚洲 激情 小说 另类 欧美 | 日韩亚洲欧美中文高清在线 | 色诱久久久久综合网ywww | 亚洲色www成人永久网址 | 伊人色综合久久天天小片 | 欧美放荡的少妇 | 国产精品办公室沙发 | 午夜无码人妻av大片色欲 | 欧美成人高清在线播放 | 免费观看激色视频网站 | 丰满岳乱妇在线观看中字无码 | 欧美第一黄网免费网站 | 高潮毛片无遮挡高清免费 | 欧美黑人性暴力猛交喷水 | 乱人伦中文视频在线观看 | 伊人久久婷婷五月综合97色 | 狠狠色噜噜狠狠狠7777奇米 | 国产精华av午夜在线观看 | 特黄特色大片免费播放器图片 | 草草网站影院白丝内射 | 国产亚洲精品久久久久久国模美 | 丝袜人妻一区二区三区 | 色婷婷久久一区二区三区麻豆 | 亚洲国产日韩a在线播放 | 久久综合给久久狠狠97色 | 天天燥日日燥 | 午夜性刺激在线视频免费 | 日韩无套无码精品 | 国内精品人妻无码久久久影院 | 国产成人无码av在线影院 | 国内揄拍国内精品人妻 | 午夜熟女插插xx免费视频 | 国产区女主播在线观看 | 乱码午夜-极国产极内射 | 4hu四虎永久在线观看 | 成人无码影片精品久久久 | 亚洲 日韩 欧美 成人 在线观看 | 最新国产乱人伦偷精品免费网站 | 欧美精品无码一区二区三区 | 日本一卡2卡3卡四卡精品网站 | 国产精品人人妻人人爽 | 美女毛片一区二区三区四区 | 少妇激情av一区二区 | 亚洲人成网站色7799 | 日本乱偷人妻中文字幕 | 国精产品一品二品国精品69xx | 人妻无码αv中文字幕久久琪琪布 | 精品无码国产自产拍在线观看蜜 | 亚洲国产av精品一区二区蜜芽 | 成人aaa片一区国产精品 | 国产亚洲精品久久久久久久久动漫 | 国产乱人伦av在线无码 | 宝宝好涨水快流出来免费视频 | 欧美阿v高清资源不卡在线播放 | 久久久久免费看成人影片 | 欧美怡红院免费全部视频 | 国产精品久久久久久久9999 | 国产精华av午夜在线观看 | 在线视频网站www色 | 久久人人爽人人人人片 | 亚洲爆乳精品无码一区二区三区 | 久久久久se色偷偷亚洲精品av | 日韩人妻少妇一区二区三区 | 人人妻人人澡人人爽精品欧美 | 麻豆成人精品国产免费 | 玩弄中年熟妇正在播放 | 天天燥日日燥 | 国产国语老龄妇女a片 | 国产av无码专区亚洲awww | 2020久久香蕉国产线看观看 | 国产网红无码精品视频 | 强奷人妻日本中文字幕 | 久久精品中文字幕一区 | 中文字幕日韩精品一区二区三区 | 中文精品无码中文字幕无码专区 | 中文字幕乱码人妻无码久久 | 色五月丁香五月综合五月 | 亚洲 日韩 欧美 成人 在线观看 | 亚洲精品综合五月久久小说 | 国产农村妇女高潮大叫 | 亚洲色欲色欲天天天www | 亚洲精品一区二区三区在线观看 | 久久天天躁狠狠躁夜夜免费观看 | 色欲av亚洲一区无码少妇 | 中文字幕av伊人av无码av | 狠狠色噜噜狠狠狠7777奇米 | 亚洲一区二区三区播放 | 国产精品igao视频网 | 国产精品国产三级国产专播 | 亚洲精品国产精品乱码不卡 | 欧美丰满少妇xxxx性 | 性欧美大战久久久久久久 | 国产口爆吞精在线视频 | 色欲综合久久中文字幕网 | 亚洲精品国偷拍自产在线观看蜜桃 | 波多野42部无码喷潮在线 | 亚洲人成网站免费播放 | 欧美黑人巨大xxxxx | 九九在线中文字幕无码 | 人妻体内射精一区二区三四 | 女人高潮内射99精品 | www国产亚洲精品久久久日本 | 精品国产成人一区二区三区 | 免费无码一区二区三区蜜桃大 | 老司机亚洲精品影院无码 | 天天做天天爱天天爽综合网 | 午夜理论片yy44880影院 | 久久久婷婷五月亚洲97号色 | 精品国产乱码久久久久乱码 | 樱花草在线社区www | 日本熟妇人妻xxxxx人hd | 成在人线av无码免观看麻豆 | 任你躁国产自任一区二区三区 | 欧美人妻一区二区三区 | 亚洲中文字幕无码一久久区 | 亚洲а∨天堂久久精品2021 | 人人澡人人透人人爽 | a国产一区二区免费入口 | 久久久成人毛片无码 | 久久午夜无码鲁丝片秋霞 | 久久久精品成人免费观看 | 午夜精品久久久内射近拍高清 | 日日天日日夜日日摸 | 日本成熟视频免费视频 | 奇米影视7777久久精品人人爽 | www国产亚洲精品久久网站 | 色狠狠av一区二区三区 | 九九久久精品国产免费看小说 | 午夜精品一区二区三区在线观看 | 欧美刺激性大交 | 香蕉久久久久久av成人 | 国产精品无码mv在线观看 | 无码乱肉视频免费大全合集 | 色综合视频一区二区三区 | 日本熟妇人妻xxxxx人hd | 国产人妻久久精品二区三区老狼 | 婷婷色婷婷开心五月四房播播 | 亚洲中文字幕va福利 | 中文字幕乱码亚洲无线三区 | 波多野结衣av一区二区全免费观看 | 中文久久乱码一区二区 | 亚洲狠狠色丁香婷婷综合 | 国产成人无码午夜视频在线观看 | 成人综合网亚洲伊人 | 少妇高潮喷潮久久久影院 | 成人精品视频一区二区 | 粗大的内捧猛烈进出视频 | 亚洲欧美国产精品专区久久 | 美女扒开屁股让男人桶 | 狂野欧美性猛xxxx乱大交 | 亚洲午夜久久久影院 | 99久久精品日本一区二区免费 | 国产成人无码av片在线观看不卡 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 久久人人爽人人人人片 | 久久无码专区国产精品s | 国产精品欧美成人 | 无码人妻出轨黑人中文字幕 | 亚洲精品中文字幕乱码 | 国产精品人人爽人人做我的可爱 | 中文字幕 亚洲精品 第1页 | 国产亚洲精品久久久久久大师 | 中文字幕精品av一区二区五区 | 给我免费的视频在线观看 | 国精产品一品二品国精品69xx | 精品 日韩 国产 欧美 视频 | 无码任你躁久久久久久久 | 色婷婷综合激情综在线播放 | 天堂亚洲2017在线观看 | 国产猛烈高潮尖叫视频免费 | 国产无套粉嫩白浆在线 | 精品国产av色一区二区深夜久久 | 中文字幕无码热在线视频 | 亚洲va中文字幕无码久久不卡 | 国产又爽又黄又刺激的视频 | 日韩少妇内射免费播放 | 久久久久se色偷偷亚洲精品av | 动漫av网站免费观看 | 精品久久久久久亚洲精品 | 久久午夜无码鲁丝片秋霞 | 麻花豆传媒剧国产免费mv在线 | 亚洲第一网站男人都懂 | 亚洲色欲色欲欲www在线 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲天堂2017无码 | 国产成人综合在线女婷五月99播放 | 2019午夜福利不卡片在线 | 午夜精品一区二区三区在线观看 | 亚洲の无码国产の无码步美 | 2020最新国产自产精品 | 国产真实乱对白精彩久久 | 欧美色就是色 | 狂野欧美性猛xxxx乱大交 | 日本又色又爽又黄的a片18禁 | 中国女人内谢69xxxxxa片 | 少妇无码一区二区二三区 | 久久午夜无码鲁丝片午夜精品 | 亚洲一区av无码专区在线观看 | 久久久久99精品国产片 | 亚洲欧洲日本无在线码 | 蜜桃av抽搐高潮一区二区 | 永久免费精品精品永久-夜色 | 免费网站看v片在线18禁无码 | 亚拍精品一区二区三区探花 | 国产免费无码一区二区视频 | 性做久久久久久久免费看 | 日韩视频 中文字幕 视频一区 | 亚洲精品欧美二区三区中文字幕 | 97久久精品无码一区二区 | 亚洲成a人片在线观看无码3d | 在线欧美精品一区二区三区 | 少妇厨房愉情理9仑片视频 | 亚洲国产成人a精品不卡在线 | 色狠狠av一区二区三区 | 国产精品无码mv在线观看 | 动漫av一区二区在线观看 | 午夜精品一区二区三区在线观看 | 色噜噜亚洲男人的天堂 | 黄网在线观看免费网站 | 在线成人www免费观看视频 | 三上悠亚人妻中文字幕在线 | 熟女俱乐部五十路六十路av | 十八禁视频网站在线观看 | 中文字幕乱码人妻无码久久 | 麻豆md0077饥渴少妇 | 精品成人av一区二区三区 | 国产精品无码久久av | 久久精品无码一区二区三区 | 国产精品无码成人午夜电影 | 成在人线av无码免费 | 久久久av男人的天堂 | 国产午夜无码精品免费看 | 性开放的女人aaa片 | 国内精品人妻无码久久久影院蜜桃 | 久久精品视频在线看15 | 国产猛烈高潮尖叫视频免费 | 老司机亚洲精品影院无码 | 亚洲精品一区二区三区四区五区 | 熟妇人妻激情偷爽文 | 亚洲经典千人经典日产 | 亚洲色欲久久久综合网东京热 | 无码午夜成人1000部免费视频 | 国色天香社区在线视频 | av人摸人人人澡人人超碰下载 | 色婷婷久久一区二区三区麻豆 | 成人aaa片一区国产精品 | 日韩少妇白浆无码系列 | 亚洲成a人片在线观看无码 | 中文字幕av日韩精品一区二区 | 青青青手机频在线观看 | 久久久久久国产精品无码下载 | 国产九九九九九九九a片 | 日韩精品无码一本二本三本色 | 午夜精品一区二区三区在线观看 | 日产精品99久久久久久 | 日本又色又爽又黄的a片18禁 | 性色欲网站人妻丰满中文久久不卡 | 亚洲理论电影在线观看 | 欧美变态另类xxxx | 东京热无码av男人的天堂 | 亚洲综合在线一区二区三区 | 天堂一区人妻无码 | 蜜臀aⅴ国产精品久久久国产老师 | 国产美女极度色诱视频www | 永久黄网站色视频免费直播 | 女人被爽到呻吟gif动态图视看 | 国产成人午夜福利在线播放 | 国产一区二区三区精品视频 | 国产成人无码午夜视频在线观看 | 亚洲中文字幕久久无码 | 18禁黄网站男男禁片免费观看 | 狂野欧美性猛xxxx乱大交 | 精品一区二区三区波多野结衣 | 国产美女极度色诱视频www | 久久zyz资源站无码中文动漫 | 精品久久久无码人妻字幂 | 色综合久久88色综合天天 | 自拍偷自拍亚洲精品10p | 国产精品毛片一区二区 | 女人被男人躁得好爽免费视频 | 麻豆国产丝袜白领秘书在线观看 | 无码av中文字幕免费放 | 久久无码专区国产精品s | 国产人成高清在线视频99最全资源 | 精品国偷自产在线 | 国产亲子乱弄免费视频 | 成人性做爰aaa片免费看 | 女人被男人爽到呻吟的视频 | 欧美熟妇另类久久久久久不卡 | 亚洲乱码国产乱码精品精 | 日本精品人妻无码77777 天堂一区人妻无码 | 激情内射亚州一区二区三区爱妻 | 欧美xxxxx精品 | 无码福利日韩神码福利片 | 国产成人无码av一区二区 | 国产亚洲日韩欧美另类第八页 | 99视频精品全部免费免费观看 | 免费国产黄网站在线观看 | 亚洲精品国产品国语在线观看 | 俺去俺来也www色官网 | 97夜夜澡人人双人人人喊 | 国产乱人伦偷精品视频 | 午夜理论片yy44880影院 | 东京一本一道一二三区 | 台湾无码一区二区 | 麻豆md0077饥渴少妇 | 在线观看国产午夜福利片 | 欧美黑人乱大交 | 国产特级毛片aaaaaaa高清 | 超碰97人人射妻 | 色一情一乱一伦一视频免费看 | 波多野结衣av一区二区全免费观看 | 青青久在线视频免费观看 | 久久国产精品精品国产色婷婷 | 波多野结衣aⅴ在线 | 亚洲人成网站免费播放 | 久久伊人色av天堂九九小黄鸭 | 亚洲色成人中文字幕网站 | 亚洲乱码中文字幕在线 | 国内少妇偷人精品视频 | 中文字幕色婷婷在线视频 | 丰满人妻翻云覆雨呻吟视频 | 波多野结衣 黑人 | 高潮毛片无遮挡高清免费视频 | 国产精品久久久久影院嫩草 | 久久精品丝袜高跟鞋 | 国产精品99爱免费视频 | www国产亚洲精品久久网站 | 97se亚洲精品一区 | 俺去俺来也在线www色官网 | 亚洲乱码国产乱码精品精 | 最新国产麻豆aⅴ精品无码 | 丝袜足控一区二区三区 | 一本色道婷婷久久欧美 | 玩弄少妇高潮ⅹxxxyw | 亚洲成av人在线观看网址 | 久久精品国产大片免费观看 | 欧美午夜特黄aaaaaa片 | 国产精品久久久久久亚洲毛片 | 日日干夜夜干 | 天堂а√在线地址中文在线 | 性生交片免费无码看人 | 人妻少妇精品无码专区二区 | 亚洲一区二区三区四区 | 久久人人爽人人爽人人片ⅴ | 久久精品中文字幕一区 | 色欲av亚洲一区无码少妇 | 永久免费精品精品永久-夜色 | 成人综合网亚洲伊人 | 人妻夜夜爽天天爽三区 | 久久精品一区二区三区四区 | 成熟女人特级毛片www免费 | 97夜夜澡人人双人人人喊 | 99在线 | 亚洲 | 精品国产福利一区二区 | 亚洲の无码国产の无码影院 | 激情内射日本一区二区三区 | 久久久久99精品成人片 | 性色av无码免费一区二区三区 | 日日躁夜夜躁狠狠躁 | 国产性生大片免费观看性 | 香蕉久久久久久av成人 | 久青草影院在线观看国产 | 夜夜躁日日躁狠狠久久av | 少妇性l交大片欧洲热妇乱xxx | 亚洲 日韩 欧美 成人 在线观看 | 人人爽人人澡人人人妻 | 亚洲精品综合一区二区三区在线 | 国产亚洲精品久久久久久大师 | 无码午夜成人1000部免费视频 | 亚洲色无码一区二区三区 | 国产麻豆精品精东影业av网站 | 亚洲gv猛男gv无码男同 | 亚洲国产av精品一区二区蜜芽 | 99视频精品全部免费免费观看 | 亚洲 a v无 码免 费 成 人 a v | 99国产精品白浆在线观看免费 | 色情久久久av熟女人妻网站 | 男女猛烈xx00免费视频试看 | 亚无码乱人伦一区二区 | 夜夜高潮次次欢爽av女 | 国产亚洲欧美在线专区 | 图片小说视频一区二区 | 亚洲日本va中文字幕 | 色一情一乱一伦一视频免费看 | 国产内射老熟女aaaa | 亚洲第一网站男人都懂 | 东京热男人av天堂 | 丰满少妇高潮惨叫视频 | 夜夜高潮次次欢爽av女 | 亚洲中文字幕乱码av波多ji | 给我免费的视频在线观看 | 亚洲中文字幕乱码av波多ji | 5858s亚洲色大成网站www | 97夜夜澡人人双人人人喊 | 国产免费观看黄av片 | 成熟妇人a片免费看网站 | 精品亚洲韩国一区二区三区 | 扒开双腿疯狂进出爽爽爽视频 | 999久久久国产精品消防器材 | 国产精品久久久av久久久 | 亚洲综合伊人久久大杳蕉 | 国产av剧情md精品麻豆 | 国产明星裸体无码xxxx视频 | 欧美激情综合亚洲一二区 | 午夜无码人妻av大片色欲 | 99精品无人区乱码1区2区3区 | 中文字幕人妻无码一区二区三区 | 国产精品成人av在线观看 | 亚洲爆乳大丰满无码专区 | 精品一二三区久久aaa片 | 久久亚洲a片com人成 | 在线精品亚洲一区二区 | 国产成人无码av在线影院 | 天下第一社区视频www日本 | 精品乱码久久久久久久 | 国产亚洲精品久久久久久大师 | 国产精品久久久久久无码 | 久久久久久久人妻无码中文字幕爆 | 国产超碰人人爽人人做人人添 | 国产在线无码精品电影网 | 成人精品一区二区三区中文字幕 | 一个人看的www免费视频在线观看 | 少妇高潮喷潮久久久影院 | 国产精品视频免费播放 | 国产精品成人av在线观看 | 亚洲娇小与黑人巨大交 | 久久久久成人片免费观看蜜芽 | 精品国产国产综合精品 | 中文字幕无码免费久久99 | 久久综合激激的五月天 | 国产97色在线 | 免 | 欧美精品在线观看 | 国产精品内射视频免费 | 青青青手机频在线观看 | 久久精品人人做人人综合试看 | 久久亚洲a片com人成 | 麻豆果冻传媒2021精品传媒一区下载 | 国产乱人伦av在线无码 | 成人精品一区二区三区中文字幕 | 漂亮人妻洗澡被公强 日日躁 | 一本久道久久综合婷婷五月 | 成人综合网亚洲伊人 | 日本护士毛茸茸高潮 | 久久综合狠狠综合久久综合88 | 国产人妻精品一区二区三区不卡 | 精品久久久久久人妻无码中文字幕 | 国产亚洲人成a在线v网站 | 国精品人妻无码一区二区三区蜜柚 | 欧美日韩视频无码一区二区三 | 免费无码的av片在线观看 | 国产精品无码mv在线观看 | 国产av一区二区三区最新精品 | 久久久亚洲欧洲日产国码αv | 撕开奶罩揉吮奶头视频 | 中文字幕无码免费久久99 | 国产激情综合五月久久 | 人人妻在人人 | 无码av免费一区二区三区试看 | 中文字幕色婷婷在线视频 | 思思久久99热只有频精品66 | 小鲜肉自慰网站xnxx | 精品国产麻豆免费人成网站 | 99麻豆久久久国产精品免费 | 日韩精品一区二区av在线 | 婷婷丁香五月天综合东京热 | 亚洲一区二区观看播放 | 中文字幕无码热在线视频 | 男人的天堂av网站 | 99er热精品视频 | 成熟人妻av无码专区 | 欧美精品一区二区精品久久 | 波多野结衣 黑人 | 初尝人妻少妇中文字幕 | 国产精品高潮呻吟av久久 | 青草青草久热国产精品 | 偷窥村妇洗澡毛毛多 | 女人被爽到呻吟gif动态图视看 | 激情人妻另类人妻伦 | 国产成人无码一二三区视频 | 亚洲一区二区三区在线观看网站 | 久久午夜夜伦鲁鲁片无码免费 | 亚洲国产精品一区二区第一页 | 久久人人爽人人爽人人片ⅴ | 亚洲欧美日韩综合久久久 | 久久国产自偷自偷免费一区调 | 国产口爆吞精在线视频 | 久久久久亚洲精品中文字幕 | 夫妻免费无码v看片 | 色综合视频一区二区三区 | 久久亚洲中文字幕精品一区 | 成人免费视频在线观看 | 久久亚洲日韩精品一区二区三区 | 色狠狠av一区二区三区 | 波多野42部无码喷潮在线 | 亚洲爆乳精品无码一区二区三区 | 鲁大师影院在线观看 | 免费视频欧美无人区码 | 18无码粉嫩小泬无套在线观看 | 亚洲国产精品无码久久久久高潮 | 国产亚av手机在线观看 | 国产精品免费大片 | 两性色午夜视频免费播放 | 欧美人与禽猛交狂配 | 人人爽人人爽人人片av亚洲 | 国产精品人人爽人人做我的可爱 | 全球成人中文在线 | 久久久久国色av免费观看性色 | 久久久久国色av免费观看性色 | 在线精品国产一区二区三区 | 国产成人无码区免费内射一片色欲 | 宝宝好涨水快流出来免费视频 | 成人无码视频在线观看网站 | 丰满少妇弄高潮了www | 亚洲色无码一区二区三区 | 欧美兽交xxxx×视频 | 成人影院yy111111在线观看 | 日韩欧美中文字幕公布 | 婷婷色婷婷开心五月四房播播 | 熟妇人妻无乱码中文字幕 | 亚洲中文字幕无码中文字在线 | 国产午夜无码精品免费看 | 久久精品国产日本波多野结衣 | 欧洲极品少妇 | 一本一道久久综合久久 | 欧洲精品码一区二区三区免费看 | 久久精品一区二区三区四区 | 国产成人无码区免费内射一片色欲 | 色综合久久久无码中文字幕 | 国产一区二区三区影院 | 欧美性黑人极品hd | 亚洲日韩精品欧美一区二区 | 成人亚洲精品久久久久 | 人妻中文无码久热丝袜 | 久久久久久久女国产乱让韩 | 国产内射爽爽大片视频社区在线 | 精品厕所偷拍各类美女tp嘘嘘 | 国产精品无码mv在线观看 | 国产成人人人97超碰超爽8 | 无码人妻黑人中文字幕 | 日日天日日夜日日摸 | a国产一区二区免费入口 | 久久伊人色av天堂九九小黄鸭 | 国产精品人人爽人人做我的可爱 | 亚洲男人av香蕉爽爽爽爽 | 无码免费一区二区三区 | 日欧一片内射va在线影院 | 女人高潮内射99精品 | 在线 国产 欧美 亚洲 天堂 | 欧美性生交xxxxx久久久 | 国产精品久久久久久亚洲毛片 | 日韩亚洲欧美精品综合 | 国产精品久久久久久亚洲毛片 | 少妇一晚三次一区二区三区 | 成人亚洲精品久久久久软件 | 久久亚洲精品中文字幕无男同 | 久久人人爽人人爽人人片ⅴ | 久久99精品久久久久久 | 装睡被陌生人摸出水好爽 | 熟女少妇在线视频播放 | 无码播放一区二区三区 | 日本一卡二卡不卡视频查询 | 久久综合色之久久综合 | 国内精品一区二区三区不卡 | 国产精品资源一区二区 | 国产熟妇另类久久久久 | 2020久久香蕉国产线看观看 | 国产激情艳情在线看视频 | 天堂亚洲免费视频 | 亚洲成在人网站无码天堂 | av无码久久久久不卡免费网站 | 国产乱人无码伦av在线a | 特级做a爰片毛片免费69 | 亚洲精品一区二区三区婷婷月 | 欧美大屁股xxxxhd黑色 | 中文无码伦av中文字幕 | 性色欲网站人妻丰满中文久久不卡 | 国产香蕉97碰碰久久人人 | 四十如虎的丰满熟妇啪啪 | 国产成人精品视频ⅴa片软件竹菊 | 午夜肉伦伦影院 | 4hu四虎永久在线观看 | 亚洲人交乣女bbw | 日韩在线不卡免费视频一区 | 国产精品亚洲а∨无码播放麻豆 | 亚洲性无码av中文字幕 | 国产无遮挡吃胸膜奶免费看 | 中文字幕日韩精品一区二区三区 | 亚洲精品综合一区二区三区在线 | 亚洲狠狠色丁香婷婷综合 | 人妻熟女一区 | 男女猛烈xx00免费视频试看 | yw尤物av无码国产在线观看 | 成在人线av无码免观看麻豆 | 久久天天躁狠狠躁夜夜免费观看 | 俺去俺来也在线www色官网 | 国产av剧情md精品麻豆 | 免费男性肉肉影院 | 荫蒂被男人添的好舒服爽免费视频 | 久久综合网欧美色妞网 | 久久精品成人欧美大片 | 午夜不卡av免费 一本久久a久久精品vr综合 | 欧美精品免费观看二区 | 国精产品一品二品国精品69xx | 国产真人无遮挡作爱免费视频 | 国产午夜无码精品免费看 | 久久精品99久久香蕉国产色戒 | 狠狠综合久久久久综合网 | 熟妇激情内射com | 色 综合 欧美 亚洲 国产 | 久久午夜夜伦鲁鲁片无码免费 | 狠狠色欧美亚洲狠狠色www | 永久免费精品精品永久-夜色 | 4hu四虎永久在线观看 | 波多野结衣av在线观看 | 国产精品亚洲综合色区韩国 | 又黄又爽又色的视频 | 激情人妻另类人妻伦 | 97夜夜澡人人爽人人喊中国片 | 5858s亚洲色大成网站www | 伊人色综合久久天天小片 | 亚洲精品成人福利网站 | 18无码粉嫩小泬无套在线观看 | 国产成人精品久久亚洲高清不卡 | 亚洲欧美色中文字幕在线 | 亚洲中文字幕va福利 | 国产精品爱久久久久久久 | 无遮挡啪啪摇乳动态图 | 无码精品国产va在线观看dvd | 九月婷婷人人澡人人添人人爽 | 久久99热只有频精品8 | 亚洲精品成人av在线 | 扒开双腿疯狂进出爽爽爽视频 | 俺去俺来也在线www色官网 | 亚洲人成影院在线无码按摩店 | 日日鲁鲁鲁夜夜爽爽狠狠 | 性色av无码免费一区二区三区 | 鲁大师影院在线观看 | 一个人看的视频www在线 | www国产亚洲精品久久久日本 | 中文字幕色婷婷在线视频 | 午夜无码人妻av大片色欲 | 免费中文字幕日韩欧美 | 久久久亚洲欧洲日产国码αv | 1000部夫妻午夜免费 | 亚洲精品鲁一鲁一区二区三区 | 97久久国产亚洲精品超碰热 | 国产情侣作爱视频免费观看 | 国产综合在线观看 | 香港三级日本三级妇三级 | 老司机亚洲精品影院 | 亚洲成av人影院在线观看 | 免费人成在线视频无码 | 免费无码一区二区三区蜜桃大 | 午夜精品久久久内射近拍高清 | 性欧美熟妇videofreesex | 久久zyz资源站无码中文动漫 | 久久久久99精品国产片 | 捆绑白丝粉色jk震动捧喷白浆 | 午夜熟女插插xx免费视频 | 老司机亚洲精品影院无码 | 中文字幕无码av波多野吉衣 | 国产激情艳情在线看视频 | 精品一区二区不卡无码av | 国产精品人人妻人人爽 | 久久久久av无码免费网 | 日韩视频 中文字幕 视频一区 | 精品国产一区二区三区四区在线看 | 国产成人综合美国十次 | 兔费看少妇性l交大片免费 | 一个人看的www免费视频在线观看 | 亚洲人成无码网www | 婷婷综合久久中文字幕蜜桃三电影 | 影音先锋中文字幕无码 | 漂亮人妻洗澡被公强 日日躁 | www成人国产高清内射 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 中文字幕精品av一区二区五区 | 无码国模国产在线观看 | 亚洲狠狠色丁香婷婷综合 | 一本久道高清无码视频 | 日韩 欧美 动漫 国产 制服 | 色诱久久久久综合网ywww | 精品欧洲av无码一区二区三区 | 亚洲爆乳精品无码一区二区三区 | 无码毛片视频一区二区本码 | 老子影院午夜精品无码 | 狂野欧美激情性xxxx | 国产偷自视频区视频 | 99久久精品无码一区二区毛片 | 色一情一乱一伦一区二区三欧美 | 欧美亚洲国产一区二区三区 | 日日橹狠狠爱欧美视频 | 正在播放老肥熟妇露脸 | 牲欲强的熟妇农村老妇女视频 | a片在线免费观看 | 国产午夜手机精彩视频 | 国产精品亚洲а∨无码播放麻豆 | 国产熟女一区二区三区四区五区 | 无套内射视频囯产 | 日本熟妇浓毛 | 国产69精品久久久久app下载 | 国产精品久久久久7777 | 久久综合给合久久狠狠狠97色 | 久久精品中文字幕一区 | 女人被爽到呻吟gif动态图视看 | 精品无码国产一区二区三区av | 日本熟妇乱子伦xxxx | 婷婷五月综合缴情在线视频 | 亚洲欧洲无卡二区视頻 | 日本护士xxxxhd少妇 | 亚洲国产成人a精品不卡在线 | 少妇性荡欲午夜性开放视频剧场 | 成人无码影片精品久久久 | 国产电影无码午夜在线播放 | 国产艳妇av在线观看果冻传媒 | 欧美亚洲日韩国产人成在线播放 | 少妇邻居内射在线 | 人妻无码αv中文字幕久久琪琪布 | 亚洲综合精品香蕉久久网 | 成 人影片 免费观看 | 好屌草这里只有精品 | 精品无码一区二区三区爱欲 | 兔费看少妇性l交大片免费 | 日韩精品久久久肉伦网站 | 自拍偷自拍亚洲精品10p | 国产深夜福利视频在线 | 国产成人综合色在线观看网站 | 欧洲vodafone精品性 | 久久综合九色综合欧美狠狠 | 狠狠噜狠狠狠狠丁香五月 | 国产精品毛片一区二区 | 天海翼激烈高潮到腰振不止 | 精品亚洲韩国一区二区三区 | 欧洲美熟女乱又伦 | 亚洲 日韩 欧美 成人 在线观看 | 欧美第一黄网免费网站 | 日韩少妇白浆无码系列 | 久久久久久久久888 | √8天堂资源地址中文在线 | 蜜桃臀无码内射一区二区三区 | 无码人妻久久一区二区三区不卡 | 亚洲日韩乱码中文无码蜜桃臀网站 | 丝袜 中出 制服 人妻 美腿 | 亚洲精品综合一区二区三区在线 | 亚洲一区av无码专区在线观看 | 国产精品igao视频网 | 成人无码视频在线观看网站 | 高清无码午夜福利视频 | 精品国产一区二区三区av 性色 | 中文字幕无码av波多野吉衣 | 日韩精品成人一区二区三区 | 中文字幕无码av激情不卡 | 国产成人人人97超碰超爽8 | 无码人妻丰满熟妇区毛片18 | 中国大陆精品视频xxxx | 亚洲欧美日韩综合久久久 | 精品国产一区二区三区四区在线看 | 国产极品视觉盛宴 | 夜夜影院未满十八勿进 | 亚洲精品一区二区三区大桥未久 | 老熟女乱子伦 | 丰满人妻翻云覆雨呻吟视频 | 欧美午夜特黄aaaaaa片 | 一本久道久久综合婷婷五月 | 国产精品18久久久久久麻辣 | 亚洲成a人片在线观看无码3d | 欧美老熟妇乱xxxxx | 久久精品一区二区三区四区 | 装睡被陌生人摸出水好爽 | 久久www免费人成人片 | 麻豆蜜桃av蜜臀av色欲av | 免费无码肉片在线观看 | 亚洲热妇无码av在线播放 | 99久久久无码国产aaa精品 | 国产另类ts人妖一区二区 | 国产在线一区二区三区四区五区 | 免费无码的av片在线观看 | 日韩av无码一区二区三区不卡 | www国产亚洲精品久久网站 | 国产一区二区三区精品视频 | 国产精品理论片在线观看 | 国产精品免费大片 | 成人片黄网站色大片免费观看 | 在线播放无码字幕亚洲 | 乱人伦中文视频在线观看 | 99久久亚洲精品无码毛片 | 国产明星裸体无码xxxx视频 | 国产乱人无码伦av在线a | 国产精品欧美成人 | 伊人久久大香线蕉午夜 | 国产精品无码永久免费888 | 丰满少妇弄高潮了www | 日本护士毛茸茸高潮 | 无套内谢的新婚少妇国语播放 | 婷婷五月综合激情中文字幕 | 蜜桃av抽搐高潮一区二区 | 女人高潮内射99精品 | 暴力强奷在线播放无码 | 丰满人妻被黑人猛烈进入 | 国模大胆一区二区三区 | 四十如虎的丰满熟妇啪啪 | 六十路熟妇乱子伦 | 精品偷拍一区二区三区在线看 | 爱做久久久久久 | 国产在线无码精品电影网 | 中文精品无码中文字幕无码专区 | 无码精品国产va在线观看dvd | 久久综合网欧美色妞网 | 中文字幕无码热在线视频 | 免费看男女做好爽好硬视频 | 久9re热视频这里只有精品 | 亚洲呦女专区 | 精品国偷自产在线 | 欧美日本日韩 | 亚洲精品www久久久 | 人人妻人人澡人人爽欧美精品 | 国产成人精品无码播放 | 国产精品永久免费视频 | 99久久精品午夜一区二区 | 久久综合狠狠综合久久综合88 | 色婷婷久久一区二区三区麻豆 | 天天躁日日躁狠狠躁免费麻豆 | 国内综合精品午夜久久资源 | 国产亚洲人成a在线v网站 | 亚洲 高清 成人 动漫 | 中文字幕av日韩精品一区二区 | 精品国精品国产自在久国产87 | 东京热一精品无码av | 在线播放亚洲第一字幕 | 久久国产精品二国产精品 | 亚洲第一网站男人都懂 | 丰满少妇女裸体bbw | 久久久成人毛片无码 | 国产精品人妻一区二区三区四 | 玩弄人妻少妇500系列视频 | 美女扒开屁股让男人桶 | 欧美国产亚洲日韩在线二区 | 鲁大师影院在线观看 | 青草视频在线播放 | 亚洲 高清 成人 动漫 | 日产精品99久久久久久 | 欧美精品免费观看二区 | 午夜不卡av免费 一本久久a久久精品vr综合 | 人人妻人人澡人人爽欧美精品 | 人妻少妇精品无码专区动漫 | 亚洲中文字幕乱码av波多ji | 红桃av一区二区三区在线无码av | 国产亚洲精品久久久久久国模美 | 亚洲色偷偷男人的天堂 | 漂亮人妻洗澡被公强 日日躁 | 国产乱人偷精品人妻a片 | 欧美高清在线精品一区 | 国产熟女一区二区三区四区五区 | 日本在线高清不卡免费播放 | 国产精品久久久久久亚洲毛片 | 国产内射爽爽大片视频社区在线 | 国产免费久久久久久无码 | 国产精品久久久久9999小说 | 国产精品亚洲五月天高清 | 97人妻精品一区二区三区 | 精品一区二区三区无码免费视频 | 欧美丰满少妇xxxx性 | 99精品国产综合久久久久五月天 | 国产真实伦对白全集 | 亚洲中文字幕在线无码一区二区 | 亚洲精品午夜无码电影网 | 一本色道久久综合狠狠躁 | 成人亚洲精品久久久久 | 国产凸凹视频一区二区 | 人妻互换免费中文字幕 | 欧美老熟妇乱xxxxx | 亚洲春色在线视频 | 久久久久成人片免费观看蜜芽 | 人妻少妇精品无码专区动漫 | 亚洲色www成人永久网址 | 日韩精品a片一区二区三区妖精 | 国内少妇偷人精品视频免费 | 自拍偷自拍亚洲精品10p | 亚洲啪av永久无码精品放毛片 | 国产人妻人伦精品1国产丝袜 | 中文字幕乱码亚洲无线三区 | 国内精品人妻无码久久久影院 | 日本大乳高潮视频在线观看 | 国产精品丝袜黑色高跟鞋 | 中文字幕人成乱码熟女app | 亚洲中文字幕成人无码 | 成人免费视频在线观看 | 国产亚洲精品久久久久久久 | 亚洲国产精品成人久久蜜臀 | 露脸叫床粗话东北少妇 | 国产在线aaa片一区二区99 | 国产电影无码午夜在线播放 | 久久婷婷五月综合色国产香蕉 | 丰满妇女强制高潮18xxxx | 久久国产劲爆∧v内射 | 水蜜桃色314在线观看 | 国产激情无码一区二区 | 波多野结衣av一区二区全免费观看 | 久久精品成人欧美大片 | 久久综合九色综合97网 | 人人妻人人藻人人爽欧美一区 | 未满成年国产在线观看 | 亚洲精品午夜国产va久久成人 | 欧美 日韩 亚洲 在线 | 精品夜夜澡人妻无码av蜜桃 | 人妻无码久久精品人妻 | 露脸叫床粗话东北少妇 | 蜜臀av无码人妻精品 | 亚洲成av人在线观看网址 | 无码毛片视频一区二区本码 | 欧美熟妇另类久久久久久不卡 | 日本精品人妻无码免费大全 | 一二三四在线观看免费视频 | 免费人成在线视频无码 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 亚洲精品一区二区三区大桥未久 | 欧美亚洲日韩国产人成在线播放 | av在线亚洲欧洲日产一区二区 | 免费中文字幕日韩欧美 | 久久99精品久久久久婷婷 | 国产综合在线观看 | 国产午夜无码视频在线观看 | 天堂一区人妻无码 | 午夜精品久久久内射近拍高清 | av小次郎收藏 | 麻豆蜜桃av蜜臀av色欲av | 四虎永久在线精品免费网址 | 麻豆国产人妻欲求不满谁演的 | 精品国产一区av天美传媒 | 精品国偷自产在线视频 | 未满成年国产在线观看 | 免费国产黄网站在线观看 | 中文亚洲成a人片在线观看 | 99久久99久久免费精品蜜桃 | 伊人久久大香线蕉亚洲 | 99久久亚洲精品无码毛片 | 国产激情一区二区三区 | 久久成人a毛片免费观看网站 | 国产亚洲美女精品久久久2020 | 欧美日韩一区二区三区自拍 | 一个人看的视频www在线 | 久久99热只有频精品8 | 国内精品九九久久久精品 | 99久久久无码国产精品免费 | 久久精品国产大片免费观看 | 欧美性生交活xxxxxdddd | 精品国偷自产在线视频 | 国产精品永久免费视频 | 日本精品高清一区二区 | 中文精品无码中文字幕无码专区 | 在线 国产 欧美 亚洲 天堂 | 色欲久久久天天天综合网精品 | 欧洲熟妇色 欧美 | 狂野欧美激情性xxxx | 少妇无码av无码专区在线观看 | 国产免费久久久久久无码 | 欧美性生交xxxxx久久久 | 伊在人天堂亚洲香蕉精品区 | 鲁一鲁av2019在线 | 欧美大屁股xxxxhd黑色 | 日本又色又爽又黄的a片18禁 | 欧美性猛交xxxx富婆 | 国产手机在线αⅴ片无码观看 | 久久这里只有精品视频9 | 婷婷丁香六月激情综合啪 | 成人免费视频在线观看 | 久久久国产一区二区三区 | 成人欧美一区二区三区 | 成在人线av无码免观看麻豆 | 天天躁日日躁狠狠躁免费麻豆 | 亚洲中文字幕成人无码 | 亚洲 a v无 码免 费 成 人 a v | 久久久久av无码免费网 | 欧美zoozzooz性欧美 | 久久99精品久久久久久 | 美女毛片一区二区三区四区 | 伊人久久大香线蕉av一区二区 | 国产亚洲精品久久久久久久久动漫 | 人人妻人人澡人人爽精品欧美 | 久久精品国产大片免费观看 | 强奷人妻日本中文字幕 | 欧洲熟妇色 欧美 | 欧美日韩一区二区综合 | 精品无码成人片一区二区98 | 久久99热只有频精品8 | 荫蒂添的好舒服视频囗交 | 四虎国产精品一区二区 | 2019午夜福利不卡片在线 | 欧美肥老太牲交大战 | 九九综合va免费看 | 九九在线中文字幕无码 | 亚洲无人区一区二区三区 | 无码人妻精品一区二区三区不卡 | 亚洲日韩精品欧美一区二区 | 国产麻豆精品一区二区三区v视界 | 国产精品人人爽人人做我的可爱 | 扒开双腿疯狂进出爽爽爽视频 | 六十路熟妇乱子伦 | 欧美黑人性暴力猛交喷水 | 一本大道伊人av久久综合 | 中国女人内谢69xxxxxa片 | 人妻插b视频一区二区三区 | 5858s亚洲色大成网站www | 色综合久久久无码中文字幕 | 十八禁视频网站在线观看 | 亚洲爆乳精品无码一区二区三区 | a国产一区二区免费入口 | 中文精品无码中文字幕无码专区 | 成人无码视频免费播放 | 日本肉体xxxx裸交 | 久久午夜无码鲁丝片 | 国产精品久久精品三级 | 老头边吃奶边弄进去呻吟 | 国精品人妻无码一区二区三区蜜柚 | 国产亚洲美女精品久久久2020 | 秋霞成人午夜鲁丝一区二区三区 | 在线观看国产一区二区三区 | 色狠狠av一区二区三区 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 久久久无码中文字幕久... | 狠狠色噜噜狠狠狠狠7777米奇 | 国产人妖乱国产精品人妖 | 日产精品99久久久久久 | 亚洲熟妇色xxxxx欧美老妇 | 波多野结衣乳巨码无在线观看 | 国产午夜无码视频在线观看 | 欧美兽交xxxx×视频 | 综合人妻久久一区二区精品 | 久久久久人妻一区精品色欧美 | 国产九九九九九九九a片 | 日本大乳高潮视频在线观看 | 日本一卡2卡3卡四卡精品网站 | 国产一区二区三区精品视频 | 国产精品无码mv在线观看 | 男女爱爱好爽视频免费看 | 色婷婷久久一区二区三区麻豆 | 99麻豆久久久国产精品免费 | 久久久亚洲欧洲日产国码αv | 美女极度色诱视频国产 | 极品嫩模高潮叫床 | 亚洲国产成人a精品不卡在线 | 久久精品国产一区二区三区肥胖 | 精品午夜福利在线观看 | 日韩欧美中文字幕在线三区 | 少妇一晚三次一区二区三区 | 窝窝午夜理论片影院 | 亚洲国产精品一区二区美利坚 | 国产麻豆精品一区二区三区v视界 | 亚洲精品综合五月久久小说 | 天堂а√在线中文在线 | 免费无码午夜福利片69 | 丁香花在线影院观看在线播放 | 丰满少妇高潮惨叫视频 | 人妻有码中文字幕在线 | 成人试看120秒体验区 | 国产成人无码午夜视频在线观看 | 老司机亚洲精品影院 | 国产色xx群视频射精 | 十八禁真人啪啪免费网站 | 97精品国产97久久久久久免费 | 久久99精品久久久久久 | 亚洲综合无码一区二区三区 | 中文字幕无码乱人伦 | 亚洲中文字幕无码中文字在线 | 少妇无码一区二区二三区 | 久在线观看福利视频 | 人人妻人人藻人人爽欧美一区 | 久久国产精品精品国产色婷婷 | 欧美日韩亚洲国产精品 | 日韩亚洲欧美中文高清在线 | 性色欲网站人妻丰满中文久久不卡 | 天海翼激烈高潮到腰振不止 | 少妇邻居内射在线 | 精品无码一区二区三区的天堂 | 欧美 日韩 亚洲 在线 | 麻豆国产人妻欲求不满谁演的 | 日韩精品久久久肉伦网站 | 色婷婷香蕉在线一区二区 | 好男人社区资源 | 色妞www精品免费视频 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 久久精品一区二区三区四区 | 人人妻人人澡人人爽精品欧美 | 人人妻人人澡人人爽欧美精品 | 国产av人人夜夜澡人人爽麻豆 | 性做久久久久久久免费看 | 九九热爱视频精品 | 亚洲色在线无码国产精品不卡 | 日本va欧美va欧美va精品 | 丰满人妻翻云覆雨呻吟视频 | 久久午夜无码鲁丝片 | 强伦人妻一区二区三区视频18 | 亚洲国产一区二区三区在线观看 | 真人与拘做受免费视频一 | 日韩在线不卡免费视频一区 | 奇米影视888欧美在线观看 | 免费中文字幕日韩欧美 | 中国大陆精品视频xxxx | 国产麻豆精品精东影业av网站 | 久久精品丝袜高跟鞋 | 国产亚洲tv在线观看 | 99精品无人区乱码1区2区3区 | 日韩欧美成人免费观看 | 精品偷拍一区二区三区在线看 | yw尤物av无码国产在线观看 | 高清国产亚洲精品自在久久 | 中文字幕无码乱人伦 | 色婷婷久久一区二区三区麻豆 | 国产亚洲精品久久久闺蜜 | 亚洲一区二区三区在线观看网站 | 日日天日日夜日日摸 | 亚洲色大成网站www | 日本又色又爽又黄的a片18禁 | 日韩人妻无码中文字幕视频 | 国产成人无码a区在线观看视频app | 啦啦啦www在线观看免费视频 | 色欲av亚洲一区无码少妇 | 久久国产精品_国产精品 | 亚洲人亚洲人成电影网站色 | 午夜熟女插插xx免费视频 | 亚洲爆乳无码专区 | 少妇被粗大的猛进出69影院 | 久久综合久久自在自线精品自 | 国产又爽又黄又刺激的视频 | 亚洲七七久久桃花影院 | 人妻aⅴ无码一区二区三区 | 色一情一乱一伦 | 精品欧美一区二区三区久久久 | 51国偷自产一区二区三区 | 大肉大捧一进一出好爽视频 | 水蜜桃色314在线观看 | 中国女人内谢69xxxx | 日韩精品无码一本二本三本色 | 最近的中文字幕在线看视频 | 日韩精品无码一本二本三本色 | 思思久久99热只有频精品66 | 亚洲精品综合一区二区三区在线 | 午夜成人1000部免费视频 | 精品国偷自产在线视频 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲色欲久久久综合网东京热 | 欧美freesex黑人又粗又大 | 免费男性肉肉影院 | 国产精品久久久久9999小说 | 日产精品高潮呻吟av久久 | 亚洲国产精品成人久久蜜臀 | 国产精品亚洲一区二区三区喷水 | 在线观看免费人成视频 | 亚洲成av人片天堂网无码】 | 国产熟妇高潮叫床视频播放 | 国产精品无码成人午夜电影 | 精品乱码久久久久久久 | 色情久久久av熟女人妻网站 | 女人高潮内射99精品 | 亚洲自偷精品视频自拍 | 国产国产精品人在线视 | 国产成人精品一区二区在线小狼 | 亚洲综合另类小说色区 | 亚洲日本va午夜在线电影 | 国内精品人妻无码久久久影院蜜桃 | 中文字幕日韩精品一区二区三区 | 久在线观看福利视频 | 成人无码视频免费播放 | 亚洲国产欧美在线成人 | 正在播放东北夫妻内射 | 99麻豆久久久国产精品免费 | 国产精品无码成人午夜电影 | 国产三级久久久精品麻豆三级 | 中文无码成人免费视频在线观看 | 粉嫩少妇内射浓精videos | 欧美人妻一区二区三区 | 久久综合网欧美色妞网 | 影音先锋中文字幕无码 | 内射欧美老妇wbb | 久久99久久99精品中文字幕 | 亚洲国产欧美国产综合一区 | 欧美人与物videos另类 | 国产亚洲精品久久久闺蜜 | 欧美精品国产综合久久 | 亚洲国产精品成人久久蜜臀 | 动漫av网站免费观看 | 18禁止看的免费污网站 | 无码帝国www无码专区色综合 | 国产成人精品三级麻豆 | 中文字幕乱码中文乱码51精品 | 欧美熟妇另类久久久久久多毛 | 国产人成高清在线视频99最全资源 | 亚洲成熟女人毛毛耸耸多 | 乱人伦中文视频在线观看 | 人人爽人人澡人人高潮 | 丝袜足控一区二区三区 | 丁香啪啪综合成人亚洲 | 在线精品国产一区二区三区 | 国产高潮视频在线观看 | 在线精品国产一区二区三区 | 亚洲中文字幕在线观看 | 欧洲美熟女乱又伦 | 色五月五月丁香亚洲综合网 | 青青久在线视频免费观看 | 亚洲日韩av一区二区三区中文 | 亚洲综合色区中文字幕 | 久久国产精品萌白酱免费 | 高潮毛片无遮挡高清免费 | 青草视频在线播放 | 久久久婷婷五月亚洲97号色 | 日欧一片内射va在线影院 | 日韩精品无码一本二本三本色 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 国产激情一区二区三区 | 国产97人人超碰caoprom | 欧美成人高清在线播放 | 亚洲国产av精品一区二区蜜芽 | 亚洲国产一区二区三区在线观看 | 国产午夜福利亚洲第一 | 国产真实伦对白全集 | 久久久久se色偷偷亚洲精品av | 97夜夜澡人人爽人人喊中国片 | 精品无码成人片一区二区98 | 亚洲 另类 在线 欧美 制服 | 亚洲第一网站男人都懂 | 亚洲欧美日韩国产精品一区二区 | 亚洲日本在线电影 | 日日摸天天摸爽爽狠狠97 | 精品久久综合1区2区3区激情 | 国产sm调教视频在线观看 | 免费视频欧美无人区码 | 日本熟妇浓毛 | 少妇人妻av毛片在线看 | 国产精品视频免费播放 | а√资源新版在线天堂 | 国产精品高潮呻吟av久久 | 久久成人a毛片免费观看网站 | 亚洲精品一区二区三区四区五区 | 国产av剧情md精品麻豆 | 久久aⅴ免费观看 | 99er热精品视频 | 两性色午夜视频免费播放 | 日本精品少妇一区二区三区 | 国産精品久久久久久久 | 鲁一鲁av2019在线 | 一二三四社区在线中文视频 | 精品无人国产偷自产在线 | 婷婷综合久久中文字幕蜜桃三电影 | 狠狠cao日日穞夜夜穞av | 亚洲欧洲日本综合aⅴ在线 | 免费国产成人高清在线观看网站 | 最近中文2019字幕第二页 | 性欧美熟妇videofreesex | 国产亚洲视频中文字幕97精品 | 麻豆av传媒蜜桃天美传媒 | 日产精品高潮呻吟av久久 | 精品国产aⅴ无码一区二区 | 东北女人啪啪对白 | 国产真实乱对白精彩久久 | 亚洲日韩av片在线观看 | 网友自拍区视频精品 | 久久午夜夜伦鲁鲁片无码免费 | 又大又硬又爽免费视频 | 伊人久久大香线蕉av一区二区 | 激情内射亚州一区二区三区爱妻 | 在线观看欧美一区二区三区 | 国产香蕉尹人视频在线 | 久久久久久a亚洲欧洲av冫 | 一本大道伊人av久久综合 | 一本久久a久久精品亚洲 | 久久综合九色综合97网 | 久久精品人人做人人综合试看 | 在线播放亚洲第一字幕 | 装睡被陌生人摸出水好爽 | 亚洲高清偷拍一区二区三区 | 图片小说视频一区二区 | 国产乱子伦视频在线播放 | 少妇一晚三次一区二区三区 | 人人爽人人爽人人片av亚洲 | 成人试看120秒体验区 | 国产 精品 自在自线 | 国产免费久久精品国产传媒 | 亚洲成av人影院在线观看 | 亚洲中文字幕在线无码一区二区 | 国产精品久久久久久久9999 | 国产亚洲精品久久久久久大师 | 国产网红无码精品视频 | 中文字幕无码av波多野吉衣 | 国产激情一区二区三区 | 国产午夜无码视频在线观看 | 日韩精品a片一区二区三区妖精 | 无码人妻av免费一区二区三区 | 欧美野外疯狂做受xxxx高潮 | 激情五月综合色婷婷一区二区 | 天天做天天爱天天爽综合网 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产乱人伦偷精品视频 | 夜夜躁日日躁狠狠久久av | 亚洲区欧美区综合区自拍区 | 欧美亚洲日韩国产人成在线播放 | 久青草影院在线观看国产 | 精品日本一区二区三区在线观看 | 99精品视频在线观看免费 | 99riav国产精品视频 | 国产疯狂伦交大片 | 又粗又大又硬又长又爽 | 久久午夜无码鲁丝片 | 欧美日韩色另类综合 | aⅴ亚洲 日韩 色 图网站 播放 | 无码av岛国片在线播放 | 久久亚洲a片com人成 | 亚洲精品欧美二区三区中文字幕 | 一区二区三区乱码在线 | 欧洲 | 男女性色大片免费网站 | 欧美老妇交乱视频在线观看 | 欧美zoozzooz性欧美 | 亚洲精品一区国产 | av人摸人人人澡人人超碰下载 | 无码人妻丰满熟妇区五十路百度 | 国产综合色产在线精品 | 黑森林福利视频导航 | 国色天香社区在线视频 | 亚洲gv猛男gv无码男同 | 欧美丰满少妇xxxx性 | 国产一区二区三区影院 | 中文毛片无遮挡高清免费 | 欧美精品在线观看 | 国产特级毛片aaaaaa高潮流水 | 又色又爽又黄的美女裸体网站 | 亚洲国产精品无码一区二区三区 | 水蜜桃亚洲一二三四在线 | 欧美猛少妇色xxxxx | 国产成人无码专区 | 国产精品办公室沙发 | 欧美老妇与禽交 | 欧美三级不卡在线观看 | 国产精品久久久久无码av色戒 | 荡女精品导航 | 麻豆av传媒蜜桃天美传媒 | 亚洲精品国偷拍自产在线观看蜜桃 | 免费无码一区二区三区蜜桃大 | 中文字幕乱码人妻二区三区 | 日韩欧美群交p片內射中文 | 亚洲国产午夜精品理论片 | 日韩欧美中文字幕公布 | 国産精品久久久久久久 | 久久精品女人天堂av免费观看 | 亚洲经典千人经典日产 | 欧美 日韩 人妻 高清 中文 | 在线亚洲高清揄拍自拍一品区 | 日韩成人一区二区三区在线观看 | 国产真人无遮挡作爱免费视频 | 国产精品久久国产精品99 | 日产精品高潮呻吟av久久 | 亚洲国产精品久久久天堂 | 特黄特色大片免费播放器图片 | 色综合视频一区二区三区 | 亚洲 日韩 欧美 成人 在线观看 | 精品 日韩 国产 欧美 视频 | 色综合视频一区二区三区 | 国产艳妇av在线观看果冻传媒 | 免费无码av一区二区 | 狠狠色丁香久久婷婷综合五月 | 一个人免费观看的www视频 | 久久国产精品偷任你爽任你 | 国产人成高清在线视频99最全资源 | 日日干夜夜干 | 亚洲成av人影院在线观看 | 天下第一社区视频www日本 | 国产亚洲精品久久久久久 | 永久黄网站色视频免费直播 | 精品欧美一区二区三区久久久 | 老头边吃奶边弄进去呻吟 | 国产激情综合五月久久 | 国产精品第一国产精品 | 久在线观看福利视频 | 亚洲 a v无 码免 费 成 人 a v | 久久人人爽人人爽人人片ⅴ | 美女黄网站人色视频免费国产 | 成人三级无码视频在线观看 | 久久熟妇人妻午夜寂寞影院 | 天堂а√在线地址中文在线 | 午夜不卡av免费 一本久久a久久精品vr综合 | 欧美人与物videos另类 | 成人女人看片免费视频放人 | 亚洲精品国偷拍自产在线麻豆 | 老熟妇乱子伦牲交视频 | 高清国产亚洲精品自在久久 | 国产麻豆精品一区二区三区v视界 | 亚洲精品久久久久久久久久久 | 欧美日韩色另类综合 | 动漫av一区二区在线观看 | 日本大香伊一区二区三区 | 欧美真人作爱免费视频 | 亚洲精品成人福利网站 | 色综合久久久无码中文字幕 | 国产激情综合五月久久 | 日产精品99久久久久久 | 国产亚洲欧美在线专区 | 欧美人与善在线com | 日本一卡二卡不卡视频查询 | 无码国产色欲xxxxx视频 | 成人亚洲精品久久久久软件 | 久久97精品久久久久久久不卡 | 乱码午夜-极国产极内射 | 精品日本一区二区三区在线观看 | 少妇无码av无码专区在线观看 | 久久久久国色av免费观看性色 | 男人的天堂2018无码 | 久久久久se色偷偷亚洲精品av | 好男人www社区 | 亚洲国产精品无码久久久久高潮 | 无码av免费一区二区三区试看 | 天天躁夜夜躁狠狠是什么心态 | 亚洲国产精品无码久久久久高潮 | 熟妇激情内射com | 亚洲精品国产品国语在线观看 | 国产农村乱对白刺激视频 | 国产成人精品久久亚洲高清不卡 | av无码久久久久不卡免费网站 | av无码不卡在线观看免费 | 国产高清不卡无码视频 | 欧美日韩亚洲国产精品 | 波多野结衣一区二区三区av免费 | 国产又爽又猛又粗的视频a片 | 中文字幕 人妻熟女 | 丰满护士巨好爽好大乳 | 欧美三级a做爰在线观看 | 国产无套内射久久久国产 | 国产超碰人人爽人人做人人添 | 性做久久久久久久免费看 | 午夜精品久久久内射近拍高清 | 亚洲成av人在线观看网址 | 国产偷抇久久精品a片69 | 久久久婷婷五月亚洲97号色 | 97久久精品无码一区二区 | 人人妻人人澡人人爽人人精品 | 高清无码午夜福利视频 | 日韩精品无码一本二本三本色 | 国产av无码专区亚洲a∨毛片 | 亚洲熟悉妇女xxx妇女av | а√资源新版在线天堂 | 无码人妻黑人中文字幕 | 国产精品自产拍在线观看 | aⅴ亚洲 日韩 色 图网站 播放 | 999久久久国产精品消防器材 | 色欲av亚洲一区无码少妇 | 久久久久人妻一区精品色欧美 | 国产av剧情md精品麻豆 | 日韩av无码一区二区三区 | 男女作爱免费网站 | 丰满妇女强制高潮18xxxx | 亚洲熟女一区二区三区 | 色综合视频一区二区三区 | 久久无码专区国产精品s | 国产成人综合在线女婷五月99播放 | 色婷婷av一区二区三区之红樱桃 |