co很高興取得了
這本書的作者Kip Irvine同意, 翻譯Getting started with MASM(本篇原文已不見,取而代之的是新版的Getting Started with MASM and Visual Studio 2010)
中譯版文章請參考這裡
有什麼問題也可以讓我知道,謝謝!
co很高興取得了
這本書的作者Kip Irvine同意, 翻譯Getting started with MASM(本篇原文已不見,取而代之的是新版的Getting Started with MASM and Visual Studio 2010)
中譯版文章請參考這裡
有什麼問題也可以讓我知道,謝謝!
這一篇文章來自舊的alt.os.development新聞主題,每一行有">"的部份是由Ian Nottingham所寫,其餘的部份是由Alistair J. R. Young所寫,ㄚ琪茲將其翻成中文分享給華人的朋友。
> Hey…我已經試著開始設計核心一段時間了,但是所有我看的範例都已經遠超過最早開始的
>階段,我沒辦法瞭解從哪裡開始並且什麼時候該做什麼…有人有開發初期的範例嗎?或是可能有一篇指南
>還是有需要做什麼的清單?
我要說的第一件事就是你需要考慮的是”沒有”完整的子系統可以開始,關於核心我發現最有趣的一件事就是每件事跟其餘的事都有有五六個的相依關係- 所以同時你會留下五六個子系統的小片段程式要開發。
如果你是從頭開始,或許你需要做的第一件事就是開發一大堆的小巨集跟函式來把一個漂亮的臉放在X86架構比較雜亂的位元上,如果你真的雄心勃勃,你可以嘗試,並使其成為一個可攜式或至少是一個半攜式的臉。:)
(我真的相信假如你對撰寫大量低階PC-硬體-雜湊值的組合語言程式不感興趣的話,那將會是有很多無聊細節的時間要消磨,我建議你可以取得Utah Oskit {文中所列為v. 0.96,但ㄚ琪查閱之後已經有0.97版,不過這些版本真的都很舊了,約在2002年出來的}這裡所有的資料都可以拿來用)。
你也需要一堆核心的函式庫(不是strcmp()、不是strcpy()、不是malloc()等等,當然,所以…?)- 加上assert()及panic()逐行的偵錯函式。
同時,你*真的*需要現在做你主要設計的決策,否則你會落到跟我現在一樣的狀況 – 必須摧毀這個東西然後重做一遍那可是*很大的*痛苦。
第一件大事就是記憶體模式,分段且/或分頁?如今看起來,大部分的人要分頁而不要分段 – 因為平面記憶體模式是較好的,且因為分頁通常是可相容的而分段卻不能。
再者你要放核心在哪?你允許每個程序有個別的位置空間嗎,或是混合在一起?虛擬記憶體?
然後就是多工/緒,假如你決定有這個功能,或許最關鍵的就是一開始,它是否可能將你的程式碼將永遠在對稱多處理機(SMP)上執行?假如是,你需要從一開始就放進所有的自旋鎖跟其他同步的東西 – 回想到這件是是一個*很難想像的*惡夢。
你的行程模式為何?只是基本的兩階的行程-擁有-執行緒,或是一些更複雜的?(我自己現在使用三階的互動式交談/工作/設施擁有行程擁有執行緒的模式),當你處理工作交換時,你將要寫你自己的程式碼來做這件事,或是用Intel提供的工作狀態分段(task-state segment,TSS)來做,假如是後者,你將要走整套得方法並讓每個執行緒有一個TSS,或是有兩個及交換相應的資訊進出無作用的資訊在每次的工作交換前及之後?
系統呼叫,你如何處理?有幾個可能 – Linux,以及其它的,似乎使用軟體中斷,所以那是相當的流行,其他的選項 – 呼叫閘到來讓使用模式的程序直接呼叫相應的核心函式,或只是有一個呼叫送出訊息到IPC連接埠。
而提到IPC – 訊息連接埠?具名管道?佇列?本地通訊端?上述所有部份?現在最好想一下,因為它會大大影響你其餘的設計 – 你可能想要有一個基本的然後實作其它所有的條款(在
Laura,舉個例來說,一切幾乎是基本的訊息連接埠的衍生 – 而它會影響TCP/IP堆疊的設計(網路 – 這是另外要想到的)。
Ich,設備驅動程式 – 要如何討論這些?以及檔案系統,這真的都是複用式的主題,簡言之,總有Unix的模式是你把所有的事情都當成檔案來處理並且透過檔案系統來存取,或許有更奇特的選項在那裡等待 – 再次使用我自己的核心做例子,Laura模式有一個’命名空間管理員’會列出系統的每個物件 – 設備、檔案系統及他們自己的檔案等等,要存取每個設備、檔案不管什麼東西,你詢問命名空間管理員而它針對這個物件給你一個(回憶之前的)IPC連接埠 – 且每個註冊的事情可以完全支援一系列訂製的動作,不只是標準的open()、close()、 read()、write()、ioctl()…
安全!假如你想要有,現在就想想,它幾乎比SMP改裝還要遜,至少假如你想要避免每個地方有安全漏洞的話,而且有這麼多不同的方法來做到這一點 – 我自己使用物件存取控制表驗證可能的三個不同的權杖(token)而這是基於相關的執行緒、工作及交談來處理的。
嗯,這是所有的設計東西,但這在我的書中是最重要的,我的意思是先把它做完,否則,最後你會花很多時間來摧毀跟重寫。
一旦你真的開始放程式碼到鍵盤…嗯,(除非你使用一樣東西),你需要的第一件事就是粗略的控制台驅動程式,這個程式幾乎確定不會是你使用驅動控制抬得最後一個版本,但是試著不用printf()來偵錯絕對是一個混蛋…
那麼 – 讓我看看,它很多取決於你的OS是如何的佈局(再一次談到設計:) )以及那些相關的事務,很明顯地,首先你需要的是啟動核心的程式碼(假如你使用多重開機啟動程式,或是某些類似的,這比較不會那麼痛苦,使用像它這樣的東西來開始甚至是稍後你計畫寫你自己的啟動程式可能是一個不錯主意)以及做最基本的設定(讓分段設定正確、配置核心堆積及堆疊來工作等等…等等)。
然後,我的第一步是寫東西,用來顯示啟動和停止的旗幟(這樣我就可以真正看到東西發生什麼事 – 這總是一個好處!)然後,在這上面建構 – 讓我們來看看,我的第一個步驟是重寫那個要顯示旗幟,然後進入系統閒置狀態(也就是最後變成限制執行緒的迴圈),那就*真的*比只用’for (;;) ;’ 還複雜了 – 我認為在這期間停止處理器避免使用過多電力是一個好主意,但是…
我認為下一件事可以拿來做的就是陷阱處理(trap handling)或許是個好主意- 即使,在這個階段,你所能做的就是顯示一個訊息、列印狀態以及核心的錯誤(依我所見,這應該是你預設的處理器),這訊息會在稍後偵錯的時後派上用場(比只是崩潰還有用),這在你已經有了一個架構時可以更快地實作真正的處理器。
同樣的事就是中斷的處理,我覺得這可能是名單上需要處理的下一件事,但我不會對一個無法預期的中斷感到恐慌。
在此之後 – 嗯,做好後它會依賴你現在正在做的核心,我的下一個步驟就是獲得一個處理器來跑時間的中斷 – 幾乎所有的事情都會使用系統的定時器來做*某些事*,所以這是非常必要的,而且,我也需要排程器來工作,所以…
Utah OSKit 可以在http://www.cs.utah.edu/flux/oskit/找到。
ㄚ琪發現翻譯這篇硬體的英文,對我來說難度頗高的,因為很多專業名詞是沒有接觸過的,有機會繼續涉獵囉。
看來大多數人真的想要寫一個作業系統,卻不知道從哪裡開始,他們不知道他們需要知道什麼程式語言。
嗯,ㄚ琪也是不知道從哪裡開始,所以剛好看到一些資料,所以我翻譯這篇OS開發入門。
用Q&A的方式來寫可能比較容易懂。
Q:所以我需要知道什麼程式語言來開發自己的作業系統?
A:你至少應該知道組合語言(asm)因為你會需要它來寫開機磁區(bootsector)(下面的問題會解釋)以及相當多其他的東西,我建議你也要學C/C++,因為它是比ASM還要容易瞭解的語言,接著你就可以使用C/C++跟ASM在你的作業系統中,你可能會考慮用Pascal跟 ASM來寫自己的作業系統,而不是用C/C++跟ASM,但是我還是建議使用C/C++跟ASM,(注意用C++跟作業系統的開發有一些特別的問題)。
Q: 什麼是開機磁區(bootsector)?
A: 開機磁區是一個儲存在磁碟片及/或硬碟最前面的很小程式,它負責找到你的核心(你OS的最主要部份做最多事的),載入到記憶體,然後執行。
Q: 我是否必須有一個OS來做一個OS?
A: 是的,大部分的人使用Windows 且/或 Linux來開發OS。
Q: 我應該用什麼編譯器?
A: 對於組合語言來說,我建議NASM因為它是免費的,有好的文件,可以輸出到很多的檔案格式,以及在很多的OS上可用,它也有釋出原始碼,有最多的組合語言範例在需要原始碼的OS dev站上可以找到,對於C/C++ 我建議在Linux下使用gcc,在Windows下使用DJGPP(這兩個彼此相容)。.
Q: 我如何做我的OS可開機磁區?
A: 你會需要輸出到只有機器碼的執行檔,在NASM 使用-f bin,假如你使用C/C++ 你會需要使用連結器來做(見這一個問題)。
Q: 什麼是連結器,如何使用來開發OS?
A: 連結器會將編譯器產生的輸出檔連結到一個檔案中,對於OS的開發來說,你一般會想到連結你的檔案到機器碼用的執行檔中,對於LD(DJGPP跟gcc最常用到的連結器)使用選項--oformat binary,假如你使用LD,你應該使用連結器指令碼可以比較好控制連結。
Q: 什麼是真實模式?
A: 真實模式 是x86(386、486、Pentium等等)在你第一次啟動你的PC時的狀態,真實模式有幾個缺點:
Q: 什麼是保護模式?
A: 保護模式(Protected Mode)(也叫做PMode)是真實模式的加強,保護模式有幾個比真實模式還好的優點:
如果不是很明顯,你的OS應該是以保護模式在執行除非你特別的理由要使用真實模式。
Q: 什麼是A20匯流排(A20-Gate)?
A: 8086微處理器(這個處理器是在286、386、486、Pentium等等之前的)只能存取1MB的位址空間,對於這個位址範圍,20個位址位元(A0 – A19)是足夠的,然後,Intel發明了80286(通常只叫做"286"),80286可以存取到16MB的位址空間,但是80286必須跟8086相容(做在8086上的程式必須可以在80286上執行),解決的辦法是什麼?為了這個位址範圍要給80286更多的位址匯流,但是有些程式受到這個事實影響,位址只能圍繞在1MB:
讓我們用8086看它的方式來看它:你在兩個系統裡有位址11111111111111111111然後增加1到這個位址,結果是0因為你沒有第21個位元(A20!),但是80286真的有更多的位元,要解決這個問題,Intel讓80286關閉了A20-匯流排,然後限制位址範圍到20位元,所以存取1MB以上的記憶體時,我們需要啟用A20-匯流排。
Q: 什麼是選擇器?
A: 選擇器(有時也叫做描述器)是一個區段的定義,它包含一個基本的區段屬性描述,像是分段基底值(它是開始的位址)以及分段界限值(它的長度),每一個選擇器的長度是64位元,更多的資料在GDT跟LDT的描述裡面。
Q: 什麼是GDT?
A: 全域描述表(gdt)是一個含有選擇器的表格,基本上它提供一個開始位址來定址所有的選擇器。
Q: 什麼是中斷?
A: 中斷是一個中斷目前CPU正在做的工作的一個信號,它告訴CPU一個重要的事件來臨,例如硬體中斷,而CPU需要停止目前的工作並執行適當的中斷處理器,中斷處理器是一個特殊的函式設計來處理一個特定的中斷(像是鍵盤的按鍵),由於中斷有特殊的性能,例如他們可以用來切換ring 3到ring 0,他們可以被用在作業系統中作為系統呼叫使用,Linux系統呼叫透過中斷來處理。
Q: 什麼是PIC?
A: PIC,可程式中斷控制器(Programmable Interrupt Controller),是一個裝置用來收集中斷已經發生的CPU上的硬體中斷的請求和信號,當發生時,PIC跟CPU會溝通那個請求發生,cpu會停止目前的工作以及執行請求的中斷處理器。
Q: 什麼是PIT?
A: PIT,可程式中斷計時器(Programmable Interrupt Timer),是一個可程式(你可以改變速度)的硬體計時器,它激發一個停止的中斷(IRQ 0),它主要用於工作的排程。
Q: 我應該用什麼順序來做我自己的OS?
A: 嗯,你可以從任何地方開始,但是你可能會有無數的錯誤,我建議從製作開機磁區開始,然後做基本的核心,接著增加到你的核心。
Q: 什麼是開機時設定PMode的基本步驟?
A:
更詳細的內容在Protected Mode by Chris Giese。
Q: 我的問題在這裡沒有答案,我該怎麼辦?
A: 你可以email給Bona Fide,他會設法幫你解答,然後增加到這篇來(這篇教學還有很多沒有完成)。
在看過30天打造OS!作業系統自作入門(附光碟)的04-05 指標的應用(二)這節後,ㄚ琪要進展到04-06 設定顏色編號,http://community.osdev.info/?VGA這裡的視訊DA轉換器是本節會用到的資訊:
貼上日文的自行參考,中文就自己買書來看吧!
接著04-07 矩形的繪製處理,透過用#define顏色的代碼,讓我們不用記那麼多的顏色代碼,其餘看程式怎麼做就行了!
04-08 最終的成果長這樣:
看到這個徒有沒覺得跟WX的畫面很像啊!原來自己DIY OS是這樣的喔!
在看過30天打造OS!作業系統自作入門(附光碟)的03-08 邁向32位元模式前的準備工作這節後,ㄚ琪要進展到03-09 終於開始導入C語言,這一節主的一些指令一定要記起來,不然下週書還了,又不知要如何進行了。
首先使用cc1.exe由bootpack.c製作bootpack.gas。
然後使用gas2nask.exe由bootpack.gas製作bootpack.nas。
接著使用nask.exe由bootpack.nas製作bootpack.obj。
並且使用obj2bim.exe由bootpack.obj製作bootpack.bim。
最後使用bim2hrb.exe由bootpack.bim製作bootpack.hrb。
然後使用copy命令,將asmhead.bin與bootpack.hrb連結起來,就成了haribote.sys。
先試著紀錄這幾個部份,再繼續往下一章看!
在04-03向指標挑戰這裡,使用C語言的指標跟組合語言的關係,在宣告的部份:
char *p; /* BYTE用位址的情況 */
short *p;/* WORD用位址的情況 */
int *p;/* DWORD 用位址的情況 */
程式:
void HariMain(void)
{
int i; /* 変数宣言。iという変数は、32ビットの整数型 */
char *p; /* pという変数は、BYTE [...]用の番地 */
for (i = 0xa0000; i <= 0xaffff; i++) {
p = i; /* 番地を代入 */
*p = i & 0x0f;
/* これで write_mem8(i, i & 0x0f); の代わりになる */
}
for (;;) {
io_hlt();
}
}
用這個去make run的話,會發生
bootpack.c:10: warning: assignment makes pointer from integer without a cast
第10行p = i; /* 代入位址 */這是轉型的問題,只要做p = (char *) i;的修正就可以解決問題!
所以專欄二中,有個進階的寫法:
p =(char *) i; /* 番地を代入 */
*p = i & 0x0f;
可以寫成:
*((char *) i) = i & 0x0f;
而這又跟組合語言的BYTE [i] = i & 0x0f;很像。
專欄3指標跟位址的說明很清楚,我就不重述紀錄了!
在看過30天打造OS!作業系統自作入門(附光碟)的02-04 針對今後的需要而導入Makefile這節後,ㄚ琪要進展到03-01 製作真正的IPL,這一節主要針對這段程式碼做講解:
; ディスクを読む
MOV AX,0×0820
MOV ES,AX
MOV CH,0 ; シリンダ0
MOV DH,0 ; ヘッド0
MOV CL,2 ; セクタ2
MOV AH,0×02 ; AH=0×02 : ディスク読み込み
MOV AL,1 ; 1セクタ
MOV BX,0
MOV DL,0×00 ; Aドライブ
INT 0×13 ; ディスクBIOS呼び出し
JC error
也提到使用http://community.osdev.info/?%28AT%29BIOS提到的BIOS的指令。
算是很詳細,只要照著做就可以開機了!
最新的回應