這不是苦難, 64K 好像很大, 只不過目前的 p_kernel.elf 來到 45K 左右
-rwxr-xr-x 1 descent descent 45726 2012-07-12 11:12 p_kernel.elf
離 64K 的條件越來越接近了。
這是在 real mode 下使用 bios int 0x13 來載入一個檔案, 由於一個 segment 有 64K 限制, 得要想辦法移動 segment register 才可載入到另外的 64K 記憶體區間。
另外一個問題雖然還有點遠, 就是在 p_kernel.elf 大於 1M 之後就會有載入的問題, 有考慮以 big real mode 來處理, 要不然得等我會寫 sata 或是 usb storage driver 之後才能解決這問題了。
20120719
fixed: git branch more_than64k
比想像中還要難一些, 因為我對組合語言不熟, 我使用了 C + inline assembly 來處理, 需要對 C 轉成的組合語言有概念, 以及了解載入位址和編譯出來的執行檔有何關聯, 否則會有很多奇怪的事情發生, ex: 為何某變數的值不是想像中的那樣 ...
使用 inline assembly 呼叫 bios int 0x13, 改變 es 來突破 64k range, 載入 kernel, ramfs 之後, 切換到保護模式, 從 elf entry point 為起點, 複製 p_kernel.elf 程式碼, 再 jmp 到該 entry point。
其中經歷了 real mode assembly -> real mode c -> protected mode assembly -> protected mode C, 很複雜, 透過 bochs 內建除錯器, 我總算搞懂了。
在這時候的 protected mode c 無法使用 global, static, bss 區域的變數, 這是因為 linker 在計算變數位址和載入時不完全相同, 只能使用 stack 變數。link script 我指定從 0x100 開始計算位址, 但是 kloaderp.bin 是被載入到 0x9000:0x0100, 所以實際位址是 0x90100。
C 語言陷阱很多, 而自己打造的 c runtime 更是麻煩, 很容易就發生意想不到的事情。
另外是 ramfs, kernel , copy elf to entry point 的載入問題, 這部份會互相蓋到, 重新調整這些位址總算是解決了。640K 明明就很大, 還能 overlay 真是奇了。
而因為我最後切到保護模式, 所以也可以將 ramfs 搬到 1M 以後的位址。
雖然有了 uefi 之後這些事情可能都不用做了, 直接就可以用 C, 不過透過這樣的練功方式真的很受用, 搞懂這些東西令我很快樂, 希望我能一直寫著讓我快樂的程式, 過去我寫太多令我不快樂的程式了。
對於 1M 的限制, 嗯 ... 等 kernel 膨脹到 1M 再說了。最近做了其他太多的 branch, 最根本的 bug 還沒解呢!
kloaderp.bin load more than 64K file size issue
git commit: 357613eaea2642b3b72ea24a987b1e8f5760bf32 (fs branch)
diff --git a/p_kernel.s b/p_kernel.s index 1d6be2b..ae6e3c5 100755 --- a/p_kernel.s +++ b/p_kernel.s @@ -698,7 +698,7 @@ setup_paging: mem_size: .int 0x0 TIMER_STR: .asciz "^" VB: .long (0xb8006+160) -.space 4096, 0 +.space 40960, 0 STACK_TOP:
modify p_kernel.s stack size, let p_kernel.elf more than 64K, it will hang in kloaderp.bin loading the p_kernel.elf. like this:
From write_os |
It happen should be 65535, now I don't know why.
目前已經知道原因了, stack 被載入檔案給覆蓋到了。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。