進入第三章的學習~第三章開始每章內容變多了,所以以後每學習一節寫一篇文章~
順便注一句:書上“用來生成描述符的宏”只是節自光盤中的pm.inc文件的,我照書上敲了那短短一段發現編譯的時候報錯- -不過我相信大家的眼睛都比我雪亮
因爲引導扇區空間只有512個字節,解決這個問題有倆辦法:自己寫一個引導扇區or借用別人的引導扇區(從作者的話看起來以後會涉及自己寫引導扇區~期待),咱用第二種,借用一下別人的扇區。又要去Bochs官網下東西了(還是進不去。。),幸虧有好心人~freedos-img下載,把其中的a.img複製到目錄中,改名爲freedos.img。用第二章的方法再生成一個叫做pm.img的軟盤映像(bximage命令,然後fd -> 1.44 -> pm.img),也放到目錄中。然後修改bochsrc文件,把原先的floppy:…與boot: …刪掉,換成下面三行:
floppya: 1_44=freedos.img, status=inserted
floppyb: 1_44=pm.img, status=inserted
boot: a
啓動Bochs,會發現界面顯示出A:\>,這時我們輸入format b:,會提示Format operation complete.(這時不用關Bochs)
在pmtest1.asm中將org後面的07c00h改爲0100h,重新編譯(注意,這裏編譯成.com):
nasm pmtest1.asm -o pmtest1.com
將pmtest1.com複製到虛擬軟盤pm.img上:
sudo mount -o loop pm.img /mnt/floppy(如果沒有此目錄,則要先mkdir /mnt/floppy,不然會報“掛載點/mnt/floppy不存在”)
sudo cp pmtest1.com /mnt/floppy/
sudo umount /mnt/floppy
如果成功的話,在Bochs中輸入dir b:會出現Directory of B:\*.*,下面還有幾行,如果不成功,會出現File not found.這說明pmtest1.com複製失敗(有可能是因爲關了Bochs)
然後在Bochs中執行b:\pmtest1.com,會發現紅色的P出現在了屏幕最右端~
以上爲代碼操作部分,下面是理論部分——
“Intel 8086是16位的CPU,有16位的寄存器、16位數據總線、20位地址總線,1MB尋址能力。”
物理地址 = 段值 * 16 + 偏移 (其中段值和偏移均爲16位)
實模式和保護模式中的段的概念有着根本區別。實模式下,段值可看作是地址的一部分(比如說段值爲XXXXh表示以XXXX0h開始的一段內存)。但是保護模式下,段只是一個索引,指向GDT(即global descriptor table,全局描述符表)的一個表項(描述符)。描述符詳細定義了段的起始地址、界限、屬性等內容。GDT的作用是提供段式存儲機制(此機制通過段寄存器和GDT中的描述符共同提供)
一個講GDT描述符的文章見這裏(其中涉及到“一致碼段”,下面有表列出一致與非一致的比較),還有這篇文章講的很好:保護模式下如何尋址
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
這行代碼看起來是DESC_VIDEO這個描述符相對於GDT基址的偏移,其實它有一個專門名稱:選擇子,而且它也不是一個偏移。選擇子用來選擇描述符表中的一個描述符
在別的地方看到這樣一句話:“選擇子確定描述符,描述符確定段基地址,段基地址與偏移之和就是線性地址。”
“段:偏移”形式的邏輯地址經過段機制轉化成線性地址,而不是物理地址。不過暫時在這裏線性地址就是物理地址。
關於A20地址線:8086->80286尋址範圍擴大,但是8086只能尋到1MB,如果訪問超過1MB的地址,雖然不會發生異常,但是又從0開始尋址,所以爲了保證兼容,使用8042鍵盤控制器來控制第20個地址(從0開始數)。所以爲了訪問所有內存,需要把A20打開,默認是關閉的。
寄存器cr0的第0位是PE位,此位爲0時是實模式,爲1時是保護模式。
jmp dword SelectorCode32:0
這個jmp在16位的段中,目標地址卻是32位。不能去掉dword,去掉的話編譯出來只是16位的代碼,如果目標地址的偏移較大,則前半段會被截斷。其實dword是NASM提供的,在Linux內核代碼中,這個跳轉使用DB指令直接寫二進制代碼的方式來實現的。
特權級 低->高 |
特權級 高->低 |
相同特權 級之間 |
適用於何種代碼 | |
---|---|---|---|---|
一致代碼段 | Yes | No | Yes | 不訪問受保護的資源和某些類型 的異常處理的系統代碼 |
非一致代碼段 | No | No | Yes | 避免低特權級的程序訪問而被 保護起來的系統代碼 |
數據段(總是非一致) | No | Yes | Yes |
幾個指令的含義:
equ——相當於賦值,可以將一個數值或者一個寄存器名賦給一個指定的符號名。
[gs:edi]——段寄存器名:段名,在這裏即代表段:偏移
lgdt——可以把GDT描述符表的大小和起始地址存入gdt寄存器中