您好,登錄后才能下訂單哦!
? ??操作系統--實模式到保護模式
一.實模式到保護模式(上)
????A.在這里需要從計算機的歷史談起
????1.遠古時期的程序開發:是直接操作物理內存
????2.CPU指令的操作數直接使用實地址(實際的內存地址)
????3.程序員擁有絕對的權力(利用cpu指哪打哪)
????在當時的實模式所擁有的權力帶來了許多的問題-難以定位的問題,主要因為程序每次都需要同樣地址的內存執行;同時還會帶來給多道程序設計帶來障礙的問題,主要是因為不管內存多大,只要有一個字節被其它程序占用都無法執行
????B.為了解決上述的問題就有了這款CPU歷史的里程碑-8086
????1.地址寬度為20位,可訪問1M內存空間
????2.引入[段地址:偏移地址]的內存訪問方式-8086的段寄存器和通用寄存器位16位,單個寄存器尋址最多訪問64K的內存空間,需要兩個寄存器配合,完成所有內存空間的訪問
段地址:偏移地址--這兩個的使用與定義有兩方面的意義
????1.硬件所做的工作--段地址左移4位,構成20位的基地址(起始地址),同時實地址=基地址+偏移地址
????2.對于開發者的意義--可以更有效的劃分內存的功能(數據段,代碼段等),同時當程序地址沖突時,通過修改段地址解決沖突
????
8086的詳細介紹https://baike.baidu.com/item/8086/7716347?fr=aladdin
????Q:由8086會引出一個問題-段地址:偏移地址能訪問的最大地址位0xFFFF:0xFFFF,即10FFEF;超過了1MB的空間,CPU該如何處理?
????我們知道8086的高端地址區
????
????所以8086的處理方式-由于8086只有20位地址線,因此最高位被丟棄
????
所以8086時期應用程序中的問題
????1.1MB內存完全不夠用-內存在任何時期都不夠用
????2.開發者在程序中大量使用內存回卷技術-HMA地址被使用
????3.應用程序之間沒有界限,相互之間隨意干擾-A程序可以隨意訪問B程序中的數據,C程序可以修改系統調度程序的指令
????所以80286出現--8086已經沒有那么多應用程序,所以必須兼容再兼容,加大內存容量,增加地址線數量(24位),[段地址:偏移地址]的方式可以強化一下,可以為每個段提供更多屬性(如:范圍,特權級等),可以為每個段的定義提供固定方式;80286在默認情況下完全兼容8086的運行方式(實模式),它默認可直接訪問1MB的內存空間,但是通過特殊的方式訪問1MB+的空間
C.保護模式
????1.每一段內存都擁有一個屬性定義(描述符)
????2.所有段的屬性定義構成一張表(描述符表)
????3.段寄存器保存的是屬性定義在表中的索引(選擇子)
描述符的內存結構
?描述符表
選擇子的結構
????進入保護模式的方式--1.定義描述符表2.打開A20地址線3.加載描述表4.通知CPU進入保護模式
小結
????1.[段地址:偏移地址]的尋址方式解決了早期程序重定位難得問題
????2.8086實模式下的程序無法保證安全性
????3.80286中提出了保護模式,加強了內存段的安全性
????4.處于兼容的考慮,80286之后的處理器都有2種工作模式
????5.處理器需要特定的設置步驟才能進入保護模式,默認為實模式
二.實模式到保護模式(中)
????????80286的出現引入了保護模式,為現代操作系統和應用程序奠定了基礎,但是在設計方面還是有缺陷的-體現在段寄存器為24位,通用寄存器為16為,理論上段寄存器中的數值可以直接作為段基址,16位通用寄存器最多訪問64K的內存,為了訪問16M的內存,必須不停切換段基址
????A.80386(由于80286的不足,出現了改進版80386)
????1.32位地址總線,可支持4G的內存空間
????2.段寄存器和通用寄存器位32位
????3.任何一個寄存器都能訪問到內存的任意角落--開啟了平坦內存模式的新時代,段基址為0,使用通用寄存器訪問4G內存空間
????新時期的內存使用方式有三種
????1.實模式-兼容8086的內存使用方式
????2.分段模式-通過[段地址:偏移地址]的方式將內存從功能上分段(數據段,代碼段)
????3.平坦模式-所有內存就是一個段[0:32位偏移地址]
段屬性定義
選擇子屬性定義
保護模式中的段定義
匯編小貼士
????section關鍵字用于"邏輯的"定義一段代碼集合
????section定義的代碼段不同于[段地址:偏移地址]的代碼段
????section定義的代碼段僅限于源碼中的代碼段
????[段地址:偏移地址]的代碼段指內存中的代碼段
????bits16-用于指示編譯器將代碼按照16位方式進行編譯
????bits32-用于指示編譯器將代碼按照32位方式進行編譯
在這里我們需要注意的是
????1.段描述表中的第0個描述符不使用
????2.代碼中必須顯示的指明16位代碼段和32位代碼段
????3.必須使用jmp指令從16位代碼段跳轉到32位代碼段
保護模式的編程實驗--實驗的原材料需要inc.asm同時需要將loader.asm進行修改、
loader.asm修改如下
%include?"inc.asm" org?0x9000 jmp?CODE16_SEGMENT [section?.gdt] ;?GDT?definition GDT_ENTRY???????:?????Descriptor????0,????????????0,???????????0 CODE32_DESC?????:?????Descriptor????0,????Code32SegLen??-?1,???DA_C?+?DA_32 ;?GDT?end GdtLen????equ???$?-?GDT_ENTRY GdtPtr: ??????????dw???GdtLen?-?1 ??????????dd???0 ????????????????? ;?GDT?Selector Code32Selector????equ?(0x0001?<<?3)?+?SA_TIG?+?SA_RPL0 ;?end?of?[section?.gdt] [section?.s16] [bits?16] CODE16_SEGMENT: ????mov?ax,?cs ????mov?ds,?ax ????mov?es,?ax ????mov?ss,?ax ????mov?sp,?0x7c00 ???? ????;?initialize?GDT?for?32?bits?code?segment ????mov?eax,?0 ????mov?ax,?cs ????shl?eax,?4 ????add?eax,?CODE32_SEGMENT ????mov?word?[CODE32_DESC?+?2],?ax ????shr?eax,?16 ????mov?byte?[CODE32_DESC?+?4],?al ????mov?byte?[CODE32_DESC?+?7],?ah ???? ????;?initialize?GDT?pointer?struct ????mov?eax,?0 ????mov?ax,?ds ????shl?eax,?4 ????add?eax,?GDT_ENTRY ????mov?dword?[GdtPtr?+?2],?eax ????;?1.?load?GDT ????lgdt?[GdtPtr] ???? ????;?2.?close?interrupt ????cli? ???? ????;?3.?open?A20 ????in?al,?0x92 ????or?al,?00000010b ????out?0x92,?al ???? ????;?4.?enter?protect?mode ????mov?eax,?cr0 ????or?eax,?0x01 ????mov?cr0,?eax ???? ????;?5.?jump?to?32?bits?code ????jmp?dword?Code32Selector?:?0 [section?.s32] [bits?32] CODE32_SEGMENT: ????mov?eax,?0 ????jmp?CODE32_SEGMENT Code32SegLen????equ????$?-?CODE32_SEGMENT
make以及inc.asm
;?Segment?Attribute DA_32????equ????0x4000 DA_DR????equ????0x90 DA_DRW???equ????0x92 DA_DRWA??equ????0x93 DA_C?????equ????0x98 DA_CR????equ????0x9A DA_CCO???equ????0x9C DA_CCOR??equ????0x9E ;?Selector?Attribute SA_RPL0????equ????0 SA_RPL1????equ????1 SA_RPL2????equ????2 SA_RPL3????equ????3 SA_TIG????equ????0 SA_TIL????equ????4 ;?描述符 ;?usage:?Descriptor?Base,?Limit,?Attr ;????????Base:??dd ;????????Limit:?dd?(low?20?bits?available) ;????????Attr:??dw?(lower?4?bits?of?higher?byte?are?always?0) %macro?Descriptor?3 ??????????????????????????;?段基址,?段界限,?段屬性 ????dw????%2?&?0xFFFF?????????????????????????;?段界限1 ????dw????%1?&?0xFFFF?????????????????????????;?段基址1 ????db????(%1?>>?16)?&?0xFF???????????????????;?段基址2 ????dw????((%2?>>?8)?&?0xF00)?|?(%3?&?0xF0FF)?;?屬性1?+?段界限2?+?屬性2 ????db????(%1?>>?24)?&?0xFF???????????????????;?段基址3 %endmacro?????????????????????????????????????;?共?8?字節
make的依賴需要修改
準備工作之后make,bochs之后看結果
????發現在bochs下并沒有打印結果所以需要設置斷點來對該實驗進行繼續驗證,首先對loader.asm進行反編譯得到如圖左邊的結果,發現箭頭對應處為loader.asm也就是右圖箭頭所對應處
可以在左邊對應點地址處設置斷點來對結果進行分析,結果如下
????從右邊的結果可以得出,進行以此跳轉之后再進行賦值,為了實驗,多次進行單步操作,發現得出的結果是一致的,意味著死循環了,這樣我們就從實模式到了保護模式,從16位代碼段進入到32位代碼段進行執行。
????我們在上面的代碼中為什么不直接使用標簽定義描述符中的段基地址?為什么 16 位代碼段到 32 位代碼段必須無條件跳轉呢?那么在匯編中,NASM 將匯編文件當成一個獨立的代碼段進行編譯,匯編代碼中的標簽(Label)代表的是段內偏移地址,實模式下需要配合段寄存器中的值計算標簽的物理地址,這便是我們不直接使用標簽定義描述符中的段基地址的原因了。代碼跳轉則是由于在匯編中存在一個流水線技術的概念。什么是流水線技術呢?處理器為了提高效率將當前指令和后續指令預取到流水線,因此,可能同時預期的指令中既有 16 位代碼又有 32 位代碼。為了避免將 32 位代碼用 16 位代碼的方式運行,需要刷新流水線,此時便需要使用無條件跳轉 jmp 技術才能強制刷新流水線。
小結
????1.80386處理器是計算機發展史上的里程碑
????2.32位的寄存器和地址總線能夠直接訪問4G內存的任意角落
????3.需要在16位實模式中對GDT中的數據進行初始化
????4.代碼中需要位GDT定義一個標識數據結構
????5.需要使用jmp指令從16位代碼跳轉到32位代碼
三.實模式到保護模式(下)
????在上面的實驗中,我們注意到使用了jmp dword Code32Selector :0,為什么需要dword,要知道在這里的jmp的作用(s16-s32)-在16位代碼中,所有的立即數默認為16位,從16位代碼段跳轉到32位代碼時,必須做強制轉換,否則,段內偏移地址可能被截斷
????在這節需要深入保護模式:定義顯存段,為了顯示數據,必須存在兩大硬件:顯卡+顯示器。顯卡是為顯示器提供需要顯示的數據,控制顯示器的模式和狀態。而顯示器是將目標數據以可見的方式呈現在屏幕上。顯存的概念和意義就是顯卡擁有自己內部的而數據存儲器,顯存在本質上和普通內存無差別,用于存儲目標數據,操作顯存中的數據將導致顯示器上內容的改變。
????顯卡的工作模式有兩種-文本模式與圖形模式。在不同的模式下,顯卡對顯存內容的解釋是不同的,可以使用專屬指令或int 0x10中斷改變顯卡工作模式,在文本模式下的顯存的地址范圍映射位[0xB8000,0xBFFFF],一屏幕可以顯示25行,每行80個字符
????顯卡的文本顯示原理與文本模式下顯示字符
????對段基址和段屬性進行設置之后以及打印的結果,發現會在bochs上打印出結果p
????在實現完單個字符的打印之后,可以進一步實現指定內存中的字符串打印,首先需要準備的工作有定義全局堆棧段(.gs),用于保護模式下的函數調用,之后定義全局數據段(.dat),用于定義只讀數據,最后利用對顯存段的操作定義字符串打印函數
????打印函數的設計可以如下圖所示
????
????在這里需要注意的是32位保護模式下的乘法操作是被乘數放到AX寄存器,乘數放到通用寄存器或內存單元(16位),相乘的結果放在EAX寄存器中;同時$表示當前行相對于代碼起始位置處的偏移量,$$表示當前代碼節的起始位置
????實現過程以及實現結果,可以看到實現的結果打印出設置的字符串
????
小結
????1.實模式下可以使用32位寄存器和32位地址
????2.顯存是顯卡內部的存儲單元,本質上與普通內存無差別
????3.顯卡有兩種工作模式-文本模式與圖形模式
????4.文本模式下操作顯存單元中的數據能夠立即反映到顯示器
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。