乙個作業系統的實現 2 保護模式1

2021-08-10 16:11:55 字數 3538 閱讀 6486

1:實模式下記憶體定址

段首位址*16+偏移量=實體地址(段暫存器左移四位+offset)

2:保護模式下定址

1)段暫存器中存放段選擇子selector

2)gdtr(全域性描述符表暫存器)中存放段描述符首位址

3)通過選擇子與gdtr中首位址,找到對應的段描述符

4)段描述符中有段的物理首位址,就得到段在記憶體中的首位址

5)加上偏移量,就得到這個段中存放的資料的真正實體地址

3:程式說明

;巨集定義descriptor可看做是表示描述符的結構體,由3個引數構成,這些descriptor組成全域性描述符表gdt

%macro descriptor 3        

dw %2 & 0ffffh

dw %1 & 0ffffh

db (%1>>16) & 0ffh

dw ((%2>>8) & 0f00h) | (%3 & 0f0ffh)

db (%1>>24) & 0ffh

%endmacro

da_32 equ 4000h

da_c equ 98h

da_drw equ 92h

;org 07c00h  ;直接載入.bin檔案時用07c00h位址(小於512bytes時)

org 0100h    ;大於512bytes時製作成.com檔案,通過freedos來載入.com檔案,得到執行的效果

jmp label_begin

[section .gdt]

label_gdt: descriptor 0, 0, 0  ;描述符的三個引數分別表示段物理首位址,段界限,段屬性,下面定義的三個描述符label_gdt,code32和video構成描述符表

label_desc_code32: descriptor 0,segcode32len - 1, da_c + da_32

label_desc_video: descriptor 0b8000h, 0ffffh, da_drw

gdtlen  equ $ - label_gdt  ;描述符表長度

gdtptr dw gdtlen - 1        ;gdtptr結構共48位,低16位為段界限,高32位為0,以後會重置,高32位的訪問通過gdtptr+2進行,高32位存放gdt的實體地址        

dd 0

selectorcode32 equ label_desc_code32 - label_gdt ;定義段選擇子,即當前描述符相對全域性描述符表的偏移量

selectorvideo equ label_desc_video - label_gdt

[section .s16]

[bits 16]            ;告訴編譯器這是乙個16位**段,此段**初始化所以段描述符表中的段物理首位址

label_begin:        ;程式的入口處

mov ax,cs            ;ds,es,ss與cs**段基位址都一樣

mov ds,ax

mov es,ax

mov ss,ax

mov sp,0100h

xor eax,eax            ;自己與自己異或,將eax清零

mov ax,cs            ;eax是32位暫存器,ax是eax的低16位

shl eax,4            ;左移四位,相當於乘以16,實模式下計算實體地址

add eax,label_seg_code32    ;加上段相對**段的偏移位址,eax中得到32位的code32段的實體地址

mov word [label_desc_code32 + 2],ax    ;用實際實體地址填充label_desc_code32段描述符的段物理首位址字段,其中低16位分別放在2,3位元組,高16位中的低8位放在第4位元組,高16位中的高8位放在第7位元組.

shr eax,16

mov byte [label_desc_code32 + 4],al

mov byte [label_desc_code32 + 7],ah

;得到段描述符表的實體地址,存放到gdtr暫存器中

xor eax,eax        

mov ax,ds        ;gdt的段位址為資料暫存器ds

shl eax,4        

add eax,label_gdt    ;計算出實際實體地址

mov dword [gdtptr + 2],eax    ;將實際實體地址直接放到gdtptr+2中(和實際gdtr暫存器結構相同)

lgdt  [gdtptr]            ;通過lgdt指令將gdtptr中內容載入到gdtr暫存器

cli                ;關中斷(實模式和保護模式下中斷處理不同,故關中斷防止出錯)

in al,92h        ;開啟a20位址線

or al,00000010b

out 92h,al

mov eax,cr0        ;將cr0暫存器的第0位(pe位,決定cpu執行於實模式還是保護模式)置為1

or eax,1

mov cr0,eax

jmp dword selectorcode32:0    ;跳入code32執行,加dword告訴編譯器這句**要編譯成32位**

[section .s32]

[bits 32]

label_seg_code32:

mov gs,ax

xor edi,edi

mov edi,(80*11 + 79)*2        ;螢幕的第11行,79列

mov ah,0ch                    ;0000黑底,1100紅字

mov al,'p'

mov [gs:edi],ax

jmp $

segcode32len equ $ - label_seg_code32

修改.bochsrc配置檔案,floppya:.......freedos.img

floppyb:......pm.img

boot=a

執行bochs,freedos執行成功後格式化b盤;format b:

將0100h的編譯版本用nasm編譯生成pmtest1.com檔案

在/mnt/下新建乙個目錄floppy,

mount -o loop pm.img /mnt/floppy

cp ./pmtest1.com /mnt/floppy

umount /mnt/floppy

在freedos中執行dir b:檢視b盤內容,再執行b:\pmtest1.com即可完成此次實驗

若採用第乙個實驗中的載入方式而不採用freedos方式,只需要將0100位址改為07c00,並且編譯成.bin檔案直接執行即可

1)準備gdt(包括設定各個段描述符內容)

2)用lgdt載入gdtr

3)關中斷,開啟a20位址線

4)置cr0的pe位

5)跳轉,進入保護模式

《乙個作業系統的實現》閱讀筆記 之 保護模式

一 認識保護模式 1 保護模式,protected mode,或有時簡寫為 pmode 是一種 80286 系列和之後的 x86 相容 cpu 操作模式。保護模式有一些新的特色,設計用來增強 多工 和系統穩定度,像是 記憶體保護,分頁 系統,以及硬體支援的 虛擬記憶體。2 執行環境 3 進入保護模式...

作業系統保護模式Protected Mode

保護模式,是一種80286系列和之後的x86相容 cpu操作模式。保護模式有一些新的特色,設計用來增強 多工和系統穩定度,像是 記憶體保護,分頁系統,以及硬體支援的 虛擬記憶體。大部分的現今 x86 作業系統 都在保護模式下執行,包含 linux freebsd 以及 微軟windows 2.0 和...

乙個作業系統的實現 2

接上文 xiongjian 2010.12.22 msn cug live.cn 10 下面開始程序,首先引入幾個基本原則 1 程序表a用來儲存程序a的資訊和程序a切換時,儲存當前a執行時暫存器資訊。定義為 processproc table 1024 表示系統最多可以有1024個程序,proces...