自製作業系統 (2)

2021-06-26 03:34:40 字數 2485 閱讀 9084

接上篇,檔案跳轉到了entry.s裡面,這是kernel的入口。首先面臨這麼乙個問題,kernel被載入到了什麼地方?

回想上篇elf檔案的載入機制,以及objdump裡列印出的kernel資訊,可以看到,kernel的**段(text段)被載入到了0x100000的位置,也就是1m的位置,所以記憶體布局如下:

+------------------+  <- 0xffffffff (4gb)

| 32-bit |

| devices |

| |

/\/\/\/\/\/\/\/\/\/\

/\/\/\/\/\/\/\/\/\/\

| |

| unused |

| |

+------------------+ <- depends on amount of ram

| |

| |

| extended memory |

|------------------|

| kernnel |

+------------------+ <- 0x00100000 (1mb)

| bios rom |

+------------------+ <- 0x000f0000 (960kb)

| 16-bit devices, |

| expansion roms |

+------------------+ <- 0x000c0000 (768kb)

| vga display |

+------------------+ <- 0x000a0000 (640kb)

| |

| low memory |

|------------------| <-0x00010000 (elf herader here!)

|------------------|  <-0x00007c00   (boot loader here!)
|  bootmain stack  |

+------------------+ <- 0x00000000

值得注意的是kernel的vma位址為0xf0100000,也就是核心「認為」自己是在乙個高位記憶體裡執行的,因此其中的符號,包括函式名、彙編裡定義的符號,都會指向乙個高位的位址(大於0xf0000000)的位址,所以到目前為止在entry.s裡,只要呼叫任何和「符號」相關的操作,比如jmp指令等,均會出錯,因為高位位址連是否存在都不知道,更不用說裡面是否有內容了(qemu預設是256m記憶體吧?)。

因此,為了使**正常工作,需要對記憶體位址進行一定的對映。

上篇文章也分析了,jos開啟的8086分段機制實際上只是乙個幌子,根本沒有對空間進行任何的對映,所以進行對映的工作一定要由分頁機制來完成。但是為了使開啟分頁之前的**能正常工作,在entry.s裡面定義了巨集reloc。這個巨集就是將乙個位址減去乙個kernelbase,kernelbase定義在memlayout裡面,可以看到是0xf0000000,就目前來說,任何乙個高位位址減去此值,就能得到實際在物理記憶體中的位址了。

在定義了此巨集之後,entry.s首先對entry符號和pgdir符號(也就是頁表目錄)位址做了重定向, 接著通過更改cr3暫存器裡的某些位,開啟分頁記憶體轉換。

我們跟一下pgdir裡的內容,也就是entrypgdir.c裡的內容,發現對於記憶體做了兩塊對映,首先是將虛擬記憶體的0--4m對映到物理記憶體的0--4m,其次是將從0xf000000之後的4m對映到物理記憶體的0--4m。前者的對映是為了保證低於4m的實體地址還能正確的訪問(開啟分頁後所有的記憶體位址均會做變換,即使你不想讓它變換),後面的對映是為了kernel能正常的工作。

關於頁目錄、頁表不再詳細說明,畢竟這是lab2的主要內容。

之後從低位址跳轉到高位址relocate處,然後初始化核心呼叫堆疊(呼叫函式都需要堆疊,所以在進入kernel的c語言**前需要先給它初始化好堆疊,突然覺得在做使用者態程式設計的時候不要考慮這些記憶體分布、棧啥的實在是太幸福了),之後就跳轉到i386_init,轉入c語言**了。

為什麼要從低位址跳轉到relocate處?個人認為只是想驗證之前開啟的分頁機制、載入的頁表是否有錯誤而已,如果不跳轉,直接執行貌似也可,反正call i386_init得時候也就跳轉到高位址了。

另外不要被memlayout.h裡面的那個記憶體分布所迷惑。目前進入作業系統後的呼叫棧位於**的data段(就在entry.s檔案的下面定義),而從objdump取得的資訊來看,這個data段是載入到了物理記憶體的0x0010800,大概在核心**段上面一點,虛擬記憶體的位置為0xf010800,也在核心**段上面的位置,memlayout.h給的貌似是lab2以及以後的虛擬記憶體分布方式。

之後就跳轉到c**執行,一切都變的簡單起來了。

自製作業系統 eposide 2

既然我們知道了如何顯示乙個字元,那麼顯示多個字元似乎也不在話下,請看下面 mov al,h mov ah,0xe mov bx,15 int 0x10 mov al,e mov ah,0xe mov bx,15 int 0x10 mov al,l mov ah,0xe mov bx,15 int 0...

自製作業系統 二

組合語言學習與makefile入門 2.helloos.nas程式核心部分。jmp指令 jump,跳轉。相當於c中的goto。mov指令 move,移動。理解mov指令就理解彙編一大半。指賦值的功能 把乙個東西移走了,他原來占用的位置不會空出 3.cpu的一種儲存電路 暫存器,相當於變數的功能。以下...

自製作業系統(二)

現在呢,大致流程寫在下面 首先,編寫彙編 檔名為myos.asm,所有 大致如下 下面是標準fat12格式軟盤專用 db 0xeb,0x4e,0x90 db myos ipl 啟動區名稱,必須8位元組 dw 512 每個扇區必須為512位元組 db 1 蔟必須為1個扇區 dw 1 fat的起始位置必...