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...