配置bochs,進入bochs simulator後一直是黑屏,原來預設是除錯模式,需要輸入c(continue)來讓除錯繼續。
主講mbr及進入mbr前的步驟
1.實模式只能訪問1mb的記憶體空間。
2.bios在rom中。
3.開機上電後cs:ip指向記憶體0xfff0,這裡有個跳轉語句,轉到fe05b才是真正的bios程式,之後檢測記憶體,顯示卡燈,建立資料結構,中斷向量表和填寫中斷例程。
主講實模式
段的大小統一64kb,段基址代表記憶體的起始,偏移位址代表段內偏移量。
section:節,只是為了讓程式設計師在邏輯上將程式劃分為幾個部分,偽指令
vstart:告訴編譯器以新的數字作為後面資料的位址的起始值
進入保護模式
段描述符:專門用來描述乙個記憶體段,大小為8位元組
全域性描述符(gdt):
1.相當於描述符的陣列,可以用選擇子中提供的下標在全域性描述符表中索引描述符。
2.位於記憶體中,需要gdtr暫存器指向他cpu才知道在哪。通過lgdt載入gdtr,指令格式是:lgdt48位記憶體資料,48位前16位是以位元組為單位的界限值,後32位是gdt的起始位址。2^16=65536,65536/8=8192,所以最多儲存8192個段或門。
3.在保護模式下由於段基址已經存入段描述符,段暫存器沒必要再存段基址了,所以段暫存器存入選擇子,通過選擇子在gdt中找到段描述符從而得到記憶體段起始位址和段界限值。選擇子低2位儲存了rpl(可以表示0、1、2、3四種特權級),第2位是ti位用來選擇是gdt還是ldt索引描述符。而選擇子的索引部分有13位,所以最多索引8192個段,和gdt儲存的數量相同
注意:gdt中第0個段描述符是不可用的,原因是如果選擇子忘記初始化則值為0,為避免誤操作如果訪問第0個描述符處理器將發出異常。
區域性描述符(ldt)
現代作業系統中很少使用ldt
cpu廠商建議每個任務的私有記憶體段都應該放到自己的段描述符表中,該錶就是ldt,即每個任務都有自己的ldt,隨著任務切換,也要切換相應任務的ldt。下面是linux0.11核心中描述符的關係
從相應的核心**中,我們看到在task_struct的宣告中,有如下內容:
struct task_struct ;
這說明ldt是和每個task有關。每當需要建立新的process時,就需要在記憶體中把一塊相應的區域劃分給這個process的ldt。
(部分參考自
先回憶下上章內容並解釋一些不清楚的地方。
乙個程序的位址空間,從使用者的角度看,是由若干的段(segment)組成的,這些段可以分為兩種:私有段(private)、共享段(shared)。cpu也是按照使用者的邏輯進行記憶體管理的(分段),intel pentium規定了每種段最多有8k個,每個segment最大4g。乙個cpu對應有乙個gdt(global descriptor table),該錶詳細描述了shared segment,這個表為所有程序共享的;乙個process對應有乙個ldt(local),該錶詳細描述了該process的private segment,這個表是程序私有的。
我們的程式是處在乙個個的segment中的,無論是指令還是資料。我們在程式中列印出乙個變數的位址其實是段內的偏移位址(32位),程式的16bit段號由作業系統分配管理,我們是看不見的,但是的確存在。
注意注意注意:以上的解釋中,為簡單,沒有說明分頁!
總之,segmentselector(16bit) + 段內offset(32bit) = 乙個32bit的位址值
其實這個就是虛擬位址。將這個位址轉換為實體地址就需要用他到頁目錄表中找到頁表的位址,再到頁表中找到真實實體地址。
(部分參考自
如果儲存器採用基本分頁機制,那麼作業系統會為每個程序或任務建立乙個頁表(這個頁表可能是一級的也可能是多級的)。整個作業系統中有多個程序在執行,那麼系統就會有多個頁表。頁表在記憶體中的儲存位置由暫存器cr3給出。這本書裡採用的是第一種方案,乙個程序乙個頁表,這個頁表是二級的。將頁目錄表和頁表緊挨在一起,如下圖所示如果儲存器採用基本分段機制,那麼作業系統會為每個程序或任務建立乙個段表(一般不用多級),用於記錄資料段、**段等各類段在記憶體中的具體位置。
如果採用段頁式結合的機制,那麼一般乙個程序或任務,作業系統會給其建立乙個段表,而段表中的每個段又會對應乙個頁表,也就是說,段頁式機制的每個程序有乙個段表,有多個頁表。
對於典型的linux系統而言,作業系統會維護乙個全域性描述符表(相當於系統的段表),全域性描述符表中用於記錄系統任務和使用者任務的描述符,其中使用者任務的描述符又指向使用者任務的區域性描述符表(相當於使用者任務的段表)。因此要說linux中的分段機制用的是一張大表,我個人認為也是有道理的。
這裡將兩個表都存在核心空間的低端記憶體處,這樣通過cr3的實體地址可以馬上找到頁表(因為核心空間是真實線性的,即虛擬位址和實體地址一樣)。每乙個程序的頁表都放在一起,其實還有其他的放置方法可見此貼
快表
虛擬位址到實體地址轉換有乙個快取器,快表,儲存少量的轉換關係,能加快轉換速度。轉換時一般先查快表查不到再查頁表項。
啟動分頁流程
在64位的linux下,gcc 編譯 32 位程式需要新增引數 -m32 ,ld需要新增引數是 -m elf_i386。
本章講了一些函式呼叫 ,彙編和c語言混合程式設計等知識
1.cdecl呼叫,由呼叫者清理棧空間,即將棧頂往上加。
2.linux系統呼叫入口只有乙個 0x80 中斷描述符表中的一項 具體呼叫子功能由eax指定。
3.呼叫函式,當輸入的引數小於等於 5 個時, linux 用暫存器傳遞引數。當引數個數大於 5 個時,把引數按照順序放入連續的記憶體區域,並將該區域的首位址放到 ebx 暫存器。
tips
fatal error: sys/cdefs.h: no such file or directory|
try these:
sudo apt-get purge libc6-dev
sudo apt-get install libc6-dev
in case of -m32:
sudo apt-get install libc6-dev-i386
原始碼中loader_strat_selector一直在boot.inc裡定義位0x2 所以loader.bin應放到硬碟第二個扇區
《作業系統真象還原》 閱讀筆記(中)
作業系統是由中斷驅動的。中斷分為外部中斷和內部中斷。外部中斷分為可遮蔽中斷和不可遮蔽中斷,內部中斷分為軟中斷和異常。外部中斷 來自cpu外部的中斷。可遮蔽中斷 通過intr引腳進入cpu,外部裝置如硬碟 網絡卡 印表機等發出的中斷 cpu可以不理會,因為不會宕機。linux把中斷分為上半部和下半部分...
《作業系統真象還原》閱讀筆記 第1章
安裝一系列的包。首先,linux 系統需要安裝了x window系統才能使用bochs。因bochs是由c 寫的,需先安裝gnu gcc g 編譯器。安裝命令如下 sudo apt get install build essential sudo apt get install xorg dev s...
《作業系統 真象還原》書評
首先我對這本書的評價是正面的,這是一本還算不錯的書。請以這個基調閱讀本文。我也從來沒寫過書評,只不過這本書實在是讓人忍不住要寫一下,因為各種各樣的原因。這本書大致就是在bochs虛擬機器上面,實現乙個簡單的作業系統,實現的內容包括 mbr,loader,記憶體管理,中斷管理,檔案管理,系統呼叫,多程...