本文是以下幾篇文章對應的主引導扇區代碼匯編代碼:
- 【OS學習筆記】三十四 保護模式十:中斷和異常區別
- 【OS學習筆記】三十五 保護模式十:中斷描述符表、中斷門和陷阱門
- 【OS學習筆記】三十六 保護模式十:通過中斷發起任務切換----中斷任務
;代碼清單
17-1;文件名:c17_mbr
.asm;文件說明:硬盤主引導扇區代碼
;創建日期:
2012-07-13 11:20 ;設置堆棧段和棧指針 core_base_address equ
0x00040000 ;常數,內核加載的起始內存地址 core_start_sector equ
0x00000001 ;常數,內核的起始邏輯扇區號
;===============================================================================
SECTION mbr vstart
=0x00007c00 mov ax
,cs mov ss
,axmov sp
,0x7c00;計算GDT所在的邏輯段地址mov eax
,[cs
:pgdt
+0x02] ;GDT的
32位物理地址 xor edx
,edxmov ebx
,16div ebx
;分解成
16位邏輯地址 mov ds
,eax
;令DS指向該段以進行操作mov ebx
,edx
;段內起始偏移地址
;跳過
0#號描述符的槽位
;創建
1#描述符,保護模式下的代碼段描述符mov dword
[ebx
+0x08],0x0000ffff ;基地址為
0,界限
0xFFFFF,DPL
=00 mov dword
[ebx
+0x0c],0x00cf9800 ;4KB粒度,代碼段描述符,向上擴展
;創建
2#描述符,保護模式下的數據段和堆棧段描述符 mov dword
[ebx
+0x10],0x0000ffff ;基地址為
0,界限
0xFFFFF,DPL
=00mov dword
[ebx
+0x14],0x00cf9200 ;4KB粒度,數據段描述符,向上擴展
;初始化描述符表寄存器GDTRmov word
[cs
: pgdt
],23 ;描述符表的界限 lgdt
[cs
: pgdt
]in al
,0x92 ;南橋芯片內的端口 or al
,0000_0010Bout
0x92,al
;打開A20cli
;中斷機制尚未工作mov eax
,cr0 or eax
,1mov cr0
,eax
;設置PE位
;以下進入保護模式
... ...jmp dword
0x0008:flush
;16位的描述符選擇子:
32位偏移
;清流水線并串行化處理器
[bits
32] flush
: mov eax
,0x00010 ;加載數據段
(4GB
)選擇子mov ds
,eaxmov es
,eaxmov fs
,eaxmov gs
,eaxmov ss
,eax
;加載堆棧段
(4GB
)選擇子mov esp
,0x7000 ;堆棧指針
;以下加載系統核心程序mov edi
,core_base_addressmov eax
,core_start_sectormov ebx
,edi
;起始地址call read_hard_disk_0
;以下讀取程序的起始部分(一個扇區)
;以下判斷整個程序有多大mov eax
,[edi
] ;核心程序尺寸xor edx
,edxmov ecx
,512 ;512字節每扇區div ecxor edx
,edxjnz @
1 ;未除盡,因此結果比實際扇區數少
1dec eax
;已經讀了一個扇區,扇區總數減
1@
1:or eax
,eax
;考慮實際長度≤
512個字節的情況jz pge
;EAX
=0 ?;讀取剩余的扇區mov ecx
,eax
;32位模式下的LOOP使用ECXmov eax
,core_start_sectorinc eax
;從下一個邏輯扇區接著讀@
2:call read_hard_disk_0inc eaxloop @
2 ;循環讀,直到讀完整個內核pge
:;準備打開分頁機制。從此,再也不用在段之間轉來轉去,實在暈乎
~ ;創建系統內核的頁目錄表PDTmov ebx
,0x00020000 ;頁目錄表PDT的物理地址
;在頁目錄內創建指向頁目錄表自己的目錄項mov dword
[ebx
+4092],0x00020003 mov edx
,0x00021003 ;MBR空間有限,后面盡量不使用立即數
;在頁目錄內創建與線性地址
0x00000000對應的目錄項mov
[ebx
+0x000],edx
;寫入目錄項(頁表的物理地址和屬性)
;此目錄項僅用于過渡。
;在頁目錄內創建與線性地址
0x80000000對應的目錄項mov
[ebx
+0x800],edx
;寫入目錄項(頁表的物理地址和屬性)
;創建與上面那個目錄項相對應的頁表,初始化頁表項 mov ebx
,0x00021000 ;頁表的物理地址xor eax
,eax
;起始頁的物理地址 xor esi
,esi
.b1
: mov edx
,eaxor edx
,0x00000003 mov
[ebx
+esi
*4],edx
;登記頁的物理地址add eax
,0x1000 ;下一個相鄰頁的物理地址 inc esicmp esi
,256 ;僅低端
1MB內存對應的頁才是有效的 jl
.b1
;令CR3寄存器指向頁目錄,并正式開啟頁功能 mov eax
,0x00020000 ;PCD
=PWT
=0mov cr3
,eax
;將GDT的線性地址映射到從
0x80000000開始的相同位置 sgdt
[pgdt
]mov ebx
,[pgdt
+2]add dword
[pgdt
+2],0x80000000 ;GDTR也用的是線性地址lgdt
[pgdt
]mov eax
,cr0or eax
,0x80000000mov cr0
,eax
;開啟分頁機制
;將堆棧映射到高端,這是非常容易被忽略的一件事。應當把內核的所有東西
;都移到高端,否則,一定會和正在加載的用戶任務局部空間里的內容沖突,
;而且很難想到問題會出在這里。 add esp
,0x80000000 jmp
[0x80040004] ;-------------------------------------------------------------------------------
read_hard_disk_0
: ;從硬盤讀取一個邏輯扇區
;EAX
=邏輯扇區號
;DS
:EBX
=目標緩沖區地址
;返回:EBX
=EBX
+512 push eax push ecxpush edxpush eaxmov dx
,0x1f2mov al
,1out dx
,al
;讀取的扇區數inc dx
;0x1f3pop eaxout dx
,al
;LBA地址
7~0inc dx
;0x1f4mov cl
,8shr eax
,clout dx
,al
;LBA地址
15~8inc dx
;0x1f5shr eax
,clout dx
,al
;LBA地址
23~16inc dx
;0x1f6shr eax
,clor al
,0xe0 ;第一硬盤 LBA地址
27~24out dx
,alinc dx
;0x1f7mov al
,0x20 ;讀命令out dx
,al
.waits
:in al
,dxand al
,0x88cmp al
,0x08jnz
.waits
;不忙,且硬盤已準備好數據傳輸 mov ecx
,256 ;總共要讀取的字數mov dx
,0x1f0.readw
:in ax
,dxmov
[ebx
],axadd ebx
,2loop
.readwpop edxpop ecxpop eaxret
;-------------------------------------------------------------------------------pgdt dw
0dd
0x00008000 ;GDT的物理
/線性地址
;------------------------------------------------------------------------------- times
510-($
-$$
) db
0db
0x55,0xaa
總結
以上是生活随笔為你收集整理的【OS学习笔记】三十七 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码----主引导扇区代码的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。