日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

自己动手写操作系统(一)

發布時間:2023/12/10 windows 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自己动手写操作系统(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本系列文章將一步步實現一個簡單的操作系統。實驗環境是在Linux系統下通過Bochs虛擬機運行我們自己寫的操作系統。

一、實驗環境搭建

1. Ubuntu的安裝,Windows用戶可以選擇在虛擬機中安裝Ubuntu,具體安裝教程可自行搜索。

2. Bochs虛擬機的安裝

在學習編寫操作系統的過程中,我們需要一個虛擬機來模擬出一個虛擬的計算機硬件環境,比如cpu、內存、硬盤等,并且能夠運行并且調試我們寫的代碼。Bochs很好的提供了以上所有功能,在它面前我們就像上帝一樣隨時可以讓時間停止,”鉆“到計算機內部,查看這個虛擬電腦的一切信息,這正是開發操作系統所需要的。

Ubuntu下我們可以直接運行以下命令以源碼方式安裝Bochs(注意我們之所以選擇以源碼方式安裝,是因為通過apt install安裝的Bochs是沒有調試功能的)

$ sudo apt update $ sudo apt install build-essential libx11-dev xorg-dev libgtk2.0-dev $ wget https://sourceforge.net/projects/bochs/files/bochs/2.7/bochs-2.7.tar.gz $ tar zxvf bochs-2.7.tar.gz $ cd bochs-2.7/ $ ./configure --enable-debugger --enable-disasm --enable-debugger-gui $ make $ sudo make install

./configure后面的參數便是打開調試功能的開關

到此實驗環境搭建完畢。

二、簡單的引導扇區匯編代碼

先簡單講一下計算機的啟動流程,詳細啟動過程可參考我的另一篇博客 操作系統啟動過程

按下開機鍵后,計算機首先會運行BIOS中的代碼,BIOS在進行硬件檢查和初始化后,會按照設置好的啟動順序(我們在使用U盤安裝系統時,經常要進入BIOS設置這個啟動順序),依次尋找啟動設備(比如硬盤、U盤等)。然后將第一個可用的啟動設備的第一個扇區載入內存0x7c00處,并把執行權限交給它。

啟動設備的第一個扇區我們稱之為引導扇區(MBR),共512個字節,必須以數值0x55及0xaa結尾。包括三部分內容:引導加載程序(Boot Loader)(前446個字節,如GRUB等)、磁盤分區表(DPT,Disk Partition Table)、分區有效性標志(55AA)。其中的引導加載程序負責加載啟動硬盤分區中的操作系統。

在BIOS向引導程序移交執行權之前,BIOS會對處理器進行初始化,這其中就包括處理器的代碼段寄存器CS和指令指針寄存器IP。當BIOS跳轉至引導程序時,CS和IP的值分別為0x0000和0x7c00。此時的處理器處于實模式下,物理地址必須經過CS寄存器和IP寄存器轉換才能得到。轉換公式為:物理地址=CS<<4+IP,也就是物理地址0x7c00處。

BIOS由Bochs虛擬機提供,我們接下來寫的就是這個512字節的引導扇區(MBR)的匯編代碼。目前它并不用加載操作系統,我們只讓它在屏幕上打印出經典的“hello world”即可。

首先看一下匯編代碼:

org 0x07c00mov ax,csmov ds,axmov es,axmov ax,Messagemov bp,axmov cx, 13mov ax,0x1301mov bx,0x0002mov dh,0mov dl,0int 0x10jmp $ Message: db "Hello, world!"times 510-($-$$) db 0dw 0xaa55

代碼和數據是按匯編程序的編寫順序依次連續存放到內存的,即上面的程序在0x7c00處開始存放的是org 0x07c00的機器指令,在512字節最后放的是0xaa55數據。

BIOS程序在把引導程序加載到內存時,同時還創建了中斷系統,在物理內存的前1KB空間初始化中斷向量表,在物理內存最后256KB物理地址空間內保存中斷處理程序。cpu運行完BIOS后,物理內存的布局如下:

本程序就是調用0x10號中斷,在屏幕上打印字符串。在調用0x10號中斷處理程序往顯示器的屏幕上打印字符串時,所有的參數都是通過cpu中的寄存器傳遞的,各參數的含義如下:

  • 寄存器ah:0x13表示向屏幕打印字符串;
  • 寄存器al:指定光標和字符的屬性
    0,表示字符的屬性值保存在寄存器bl中,光標停留在字符串的首字符
    1,表示字符的屬性值保存在寄存器bl中,光標停留在字符串的尾字符
    2,表示字符的屬性值緊跟在字符之后,光標停留在字符串的首字符
    3,表示字符的屬性值緊跟在字符之后,光標停留在字符串的尾字符
  • 寄存器bl:若寄存器al的值為0或者1時,保存字符的屬性值。如圖所示,字符屬性由一個字節大小的數據表示。
  • 寄存器[es:bp]:保存字符串的首字符在數據段中的邏輯地址
  • 寄存器cx:保存字符串的長度
  • 寄存器dh,dl:字符串在屏幕上的起始坐標,其中寄存器dh為行號,寄存器dl為列號。顯示器的屏幕只能顯示25行字符,并且每行只能顯示80個字符,因此dh的取指范圍為0~24,dl的取指范圍為0~79。

代碼解析:

第1行,告訴編譯器程序加載到內存的0x7c00處。

第2~4行,統一數據段寄存器DS和附加段寄存器ES的值和代碼段寄存器CS一致,即不論數據段還是代碼段,段起始地址都是0x7c00。

第5~6行,將字符串"Hello, world!"的首地址傳遞給寄存器bp。注意任何不被方括號[ ]括起來的標簽或變量名都被認為是地址,訪問標簽或變量中的內容必須使用[ ]

第7行,將字符串的長度傳遞給寄存器cx

第8~11行,字符串屬性設置

第12行,調用0x10號中斷處理程序,在屏幕上顯示字符串

第13行,使cpu進入死循環
因為cpu會不停的根據寄存器[cs:ip]中的邏輯地址轉換后的物理地址,從物理內存讀取機器指令,然后對其解析、執行。其中,當運行完一條機器指令后,cpu自動將該機器指令的下一條機器指令的偏移地址賦值給ip。當cpu運行完可執行文件中的最后一個機器指令后,若不采取任何措施,則cpu會將下面的數據看做機器指令,進行取指、解析、執行。因此,需要一條讓cpu進入死循環的機器指令作為可執行文件的最后一條機器指令。

$表示當前行被匯編后的地址,$$表示程序被匯編后的開始地址,也就是0x7c00.

第15、17行,分別以字節和字的形式存放的數據

第16行,表示將0這個字節重復510-($-$$)遍,也就是在剩下的空間不停填充0,直到第510個字節為止。這樣加上結束標志0xaa55占用的兩個字節,恰好是512個字節。

在運行代碼之前我們需要將其轉換成計算機能讀懂的機器指令形式,這就需要編譯器。我們編譯c代碼使用GCC,編譯匯編程序使用nasm編譯器。

把上面的代碼保存成boot.asm,然后使用nasm編譯一下,生成二進制可執行文件boot.bin

$ nasm boot.asm -o boot.bin

三、虛擬硬盤的制作

下面我們將制作一個虛擬硬盤并將已經生成的可執行文件boot.bin放到虛擬硬盤的第一個磁盤塊(引導扇區MBR)中。Bochs虛擬機將使用這塊“硬盤”引導啟動。

首先選擇合適的地方創建一個工程目錄

$ mkdir projectest $ cd projectest

將可執行文件boot.bin拷貝到該工程目錄中

然后在本層目錄中創建一個大小為1MB的硬盤鏡像文件b.img的命令如下:

$ dd if=/dev/zero of=b.img bs=512 count=2048

dd是文件拷貝命令,其中:

  • if=/dev/zero:表示拷貝的源文件的路徑,"/dev/zero"是一個特殊的文件,可以提供n個0(n的值等于bs和count參數的積)
  • of=b.img:表示拷貝的目標文件路徑。若不存在,則創建該文件
  • bs=512:表示塊大小,單位為B
  • count=2048:表示拷貝的文件的塊的數量。

由bs和count參數可知,硬盤鏡像文件的大小為:2048*512B=1MB,硬盤鏡像文件制作好后,將可執行文件boot.bin拷貝到硬盤鏡像文件b.img(硬盤)的引導扇區的命令如下:

$ dd if=boot.bin of=b.img bs=512 seek=0 conv=notrunc

其中:

  • seek=0:表示把可執行文件boot.bin拷貝到硬盤鏡像文件b.img的引導扇區(扇區號為0)。
  • conv=notrunc:表示不改變目標文件的大小,若沒有該選項,則硬盤鏡像文件b.img的大小會由1MB變為可執行文件boot.bin的大小512B。

這樣一個寫入了引導程序的“硬盤”就制作好了。

四、Bochs的使用

1. 啟動Bochs

"硬盤”制作好后,要想啟動bochs還需要一個配置文件——bochsrc.bxrc。為什么需要配置文件呢?因為你需要告訴bochs你希望的虛擬機是什么樣的,比如,內存多大,使用哪個硬盤啟動等等。在下載bochs的源碼包中有一個.bochsrc,就是官方提供的配置文件示例,我們可以根據這個更改。

下面是本實驗用到的bochs配置文件代碼

romimage: file=/usr/local/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest ata0-master: type-disk, path="b.img" megs: 16 cpu: count=1 boot: disk

其中:

  • romimage:指定bochs運行過程中使用的ROM-BIOS的路徑。
  • vgaromimage:指定bochs運行過程中使用的VGA的ROM-BIOS的路徑。
  • ata0-master:指定硬盤鏡像文件b.img的路徑。
  • megs:指定物理內存的大小,單位為MB。
  • cpu:指定cpu的個數,1個。
  • boot:指定啟動方式,從硬盤啟動。

將上面的代碼保存為bochsrc.bxrc,也存到工程目錄下。

現在一切準備就緒,啟動bochs的命令如下:

$ bochs -q -f bochsrc.bxrc

其中:

  • -q: 跳過bochs啟動后的配置界面。
  • -f : bochsrc.bxrc:指定配置文件的路徑。
  • 如果不指定路徑,那么Bochs將按照如下順序在當前目錄中尋找配置文件:
  • .bochsrc

  • bochsrc

  • bochsrc.txt

  • bochsrc.bxrc (windows only)

  • /home/.bochsrc (Unix only)

  • /etc/bochsrc(Unix only)

  • 運行bochs后會在終端出現bochs調試命令行,等待我們輸入調試命令,這里輸入c繼續執行

    可以看到在虛擬機中我們的引導程序已成功運行,在屏幕上打印出了hello world。

    2. Bochs調試

    常用調試命令作用
    b使用物理地址打斷點
    vb使用邏輯地址打斷點
    blist查看所有斷點信息
    n單步執行(遇到函數跳過)
    s單步執行(遇到函數進入函數內部)
    c繼續執行
    r查看所有通用寄存器的值
    (eax、ebx、ecx、edx、esp、ebp、esi、edi、eip、eflags)
    sreg查看所有段寄存器的值
    u /5打印CPU接下來將執行的5條指令
    xp查看物理內存中指定物理地址的內容
    xp /2bx 物理地址:打印兩個字節,以十六進制格式輸出。
    xp /13c 物理地址:打印13個字節,以ASCII碼對應的字符顯示
    watch 變量名運行時,若某一行代碼修改了變量,則中斷,并打印修改前后的值。
    q退出調試繼續執行

    總結

    以上是生活随笔為你收集整理的自己动手写操作系统(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。