搭建直接通過CPU執行彙編語言的環境
我們通過編譯寫好的彙編語言程式碼可以生成.bin的機器語言二進位程式碼。但是這個.bin程式我們該如何運行呢?
這裡其實有兩個辦法:
1: 將其作為一個Windows/linux也就是作業系統的可執行程式來運行,這個nasm是可以做到的,很多工具也可以做到,把一個彙編程式編譯鏈接成一個.exe來處理。
2: 直接通過CPU來使用。因為.bin文件是機器碼,肯定是可以直接讓CPU來使用的。作業系統也是一個需要在處理器上運行的軟體,只不過比 起一般的程式而言,體積更為龐大,功能更為複雜而已。如果我們能繞過它,或者代替它,讓電腦一開機的時候直接執行我們自己的程式, 豈不更簡單?而且很酷,不用作業系統,自己直接操作CPU。
採用第一種比較簡單,這裡就不詳述了。
搭建環境原理:
前面我們講述了8086的啟動操作:
在bios調用完之後cs:ip會變成物理地址0x07C00來載入主引導扇區的程式碼,我們可以直接通過硬碟啟動,然後把硬碟的主引導扇區的程式碼變成我們自己的程式碼。這多帥,直接操作CPU,避開作業系統。
但是我們還需要有調試功能才行,因為如果不能調試,那麼CPU就直接順著程式碼走就完了,我們啥也看不到,所以我們需要一個帶有調試功能的虛擬機。正好有一個非常適合我們,叫做 bochs:
預備知識
虛擬硬碟簡介:
我們把我們的程式碼寫到硬碟里,然後虛擬機讀取我們的硬碟就行了。但是由於我們得往硬碟里寫東西,所以需要提前了解一下硬碟。
虛擬硬碟並不是真實的硬碟,而是用文件來模擬生成的一個硬碟。
虛擬硬碟有很多這裡介紹三個:
VMDK | VMWare虛擬機 |
---|---|
VDI | VirtualBox虛擬機 |
VHD | Virtual-PC/Hyper-V虛擬機 |
其中VHD比較簡單,所以這裡我們就採用VHD虛擬硬碟。
VHD也可以分為固定尺寸和動態尺寸,其中固定尺寸更簡單,所以採用VHD的固定尺寸硬碟。
在VHD 規範里,每個扇區是512 位元組。VHD文件一開始的512 位元組,就對應著物理硬碟的0 面0 道1 扇區。然後,VHD 文件的第二個512 位元組,對應著0 面0 道2 扇區,後面的以此類推。再往後,因為硬碟的訪問是按柱面進行的,所以,下一個數據塊對應的是1 面0 道1 扇區,就這樣一 直往後排列,當把第一個柱面全部對應完後,再從第二個柱面開始對應。磁碟轉圈比移動快,所以最後才移動磁軌。
固定尺寸的VHD 虛擬硬碟 是一個具有「.vhd」擴展名的文件,它僅包括兩個部分,前面是數據區,用來模擬實際的硬碟空間,最後面跟著一個512 位元組的結尾
文件尾的內容是以一個字元串「conectix」開始的。這個標誌用來告訴試圖打開它的虛擬機,這的確是一個合法的VHD 文件。該標誌稱為VHD 創建者標識,就是說,該公司(conectix)創建了VHD 文 件格式的最初標準:
從這個標誌字元串開始,後面的數據包含了諸如文件的創建日期、VHD 的 版本、創建該文件的應用程式名稱和版本、創建該文件的應用程式所屬 的作業系統、該虛擬硬碟的參數(磁頭數、每面磁軌數、每磁軌扇區 數)、VHD 類型(固定尺寸還是動態增長)、虛擬硬碟容量等。
磁碟的訪問邏輯:
傳統的訪問模式就是:CHS,通過柱面磁軌磁頭,也就是前面的0 面0 道1 扇區這種類似的格式,但是這個不太方便。
然後就有了LBA(Logical Block Address)就是把所有的扇區進行一個邏輯編號,從0開始到最後一個扇區進行編號,然後單位為塊(block)其實就是扇區,只不過扇區看著確實是一塊一塊的:
LBA和CHS的對應方式:
存儲容量 = 磁頭數 × 磁軌(柱面)數 × 每道扇區數 × 每扇區位元組數
移動方式稍微不一樣點,先移動扇區再磁頭最後再更改柱面。因為更改柱面磁頭需要移動。 也就是以柱面為單位來讀取的意思。
LBA = 磁軌*磁頭 *每個磁軌的扇區數+ 磁頭 * 每個磁軌的扇區數 + 扇區位置-1
比如這裡的: 1面0道2扇區 == 0* 2*17 + 1 *17 +2 -1 ==18
0面1道2扇區 == 1*2 *17 +2 -1 == 35
需要工具:
安裝bochs:(在這裡選擇自己的需要的版本)
安裝 VirtualBox:
下載李忠老師的軟體包:
//www.lizhongc.com/myfiles/download.php?id=201
下載二進位查看軟體:
搭建環境
創建一個固定尺寸的VHD虛擬硬碟,然後將其安裝到Bochs虛擬機上。
第一步創建一個虛擬硬碟:
創建虛擬硬碟:
1:打開Virtual Box,單擊管理—>虛擬介質管理器,就會得到這個介面:
2:點擊創建,選擇VHD虛擬硬碟:
3:選擇固定大小:
4:自己選擇硬碟位置和大小(我這裡拿來學習所以不需要太大)
5:查看結果
配置bochs環境
1:選中配置:
2:關閉軟盤:(軟盤基本上絕跡了)
3:選中ATA channel0:(這個就默認值不改就好)
4:選中ATA channel0的子目錄 First HD/CD on channel0
然後修改,其中Path開頭那個是前面創建的虛擬硬碟。
然後剩下的資訊需要查看虛擬磁碟的資訊才可以,這裡要用到前面李忠老師的資源包里的一個軟體:
叫做fixvhdwr.exe,用它來打開我們前面創建的虛擬硬碟
然後根據裡面的資訊來填充到前面:
Cylinders為柱面,Heads為磁頭,Sectors per track為每個磁軌有多少扇區。
5:修改電腦的啟動順序:
改成第一個用磁碟,第二個用光碟。
編寫程式放到主引導扇區,讓電腦在啟動後執行:
編譯程式:
首先先採用彙編語言來簡單編寫一個程式:
mov ax,0x30
mov dx,0xc0
add ax,dx
然後將其編譯成.bin二進位文件:
不知道這一步怎麼處理的可以查看我的一篇部落格:
然後採用前面下載的二進位查看文件HexView來打開我們的.bin文件:
可以看到我們這個只有8個位元組的內容,但是扇區是以512個位元組為單位的,所以我們必須填充成512個位元組才行。而且主引導扇區的結尾必須是16進位的55和AA不然就是無效的。
所以我們還得修改一下彙編程式碼:
mov ax,0x30
mov dx,0xc0
add ax,dx
times 502 db 0x0
db 0x55
db 0xAA
這裡的times 502 db 0x0 相當於填充了502個位元組的內容且為0。
然後最後結尾為0x55和0xAA。
來查看一下編譯後的結果:
一共是512個位元組(0x200),且結尾為0x55和0xAA。
將程式寫入到虛擬硬碟:
這裡需要用到李忠老師提供的軟體包的一個軟體:fixvhdwr.exe
這個只能寫入固定硬碟的內容:
選中我們剛剛的編譯好的二進位.bin文件。
然後選擇LBA,前面我們了解了LBA的知識所以第一個扇區0面0道1扇區就等於 LBA的0,這裡就選0然後選擇寫入就好了:
然後採用二進位查看工具,查看我們寫入了的VHD磁碟是否成功:
前0x200個位元組完全對應,所以是成功了。