文章寫于兩年前的 MacBookAir(2015)
目前筆者為 MacBookPro M1 (抽查了部分 都運行正常)
Github項目地址: https://github.com/wdkang123/MyOperatingSystem
MacOS X86架構(x新版的arm架構的我沒有 所以大家自行測試)
VirtualBox
C/C++環境 (Xcode必裝)
前文中我們將一段代碼通過軟盤加載到了系統內存中 并指示cpu執行加入到內存的代碼
事實上,操作系統內核加載也是這么做的。只不過我們加載的代碼,大只能512 byte, 一個操作系統內核,少說也要幾百兆,由此,系統內核不可能直接從軟盤讀入系統內存
通常的做法是 被加載進 內存的512byte程序 實際上是一個內核加載器 它運行起來之后 通過讀取磁盤 將存儲在磁盤上的內核代碼加載到指定的內存結構中去 然后在把cpu的控制權提交給加載進來的系統內核
硬盤的結構
軟盤的物理結構如上圖 一個盤面被劃分成若干個圓圈
例如圖中的灰色圓圈 我們稱之為磁道 也可以稱作柱面
一個磁道或柱面 又被分割成若干部分 每一部分 我們稱之為一個扇區
一個扇區的大小正好是512k
從而,當我們把數據存儲到軟盤上時,數據會分解成若干個512Byte大小的塊,然后寫入到扇區里
2.模擬我們要模擬的是3.5寸軟盤 這種軟盤的特點是
它有兩個盤面 因此就對應兩個磁頭 每個盤面有80個磁道 也就是柱面 編號分別為0-79 每個柱面都有18個扇區 編號分別為1-18 所以一個盤面可以存儲的數據量大小為:
512 * 18 * 80
一個軟盤有兩個盤面,因此一個軟盤可以存儲的數據為:
2 * 512 * 18 * 80 = 1474560 Byte = 1440 KB = 1.5M
接下來,我們用java來模擬一個3.5寸軟盤,以及它的讀寫邏輯
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
public class Floppy {enum MAGNETIC_HEAD {MAGNETIC_HEAD_0,
MAGETIC_HEAD_1
};
public int SECTOR_SIZE = 512;
private int CYLINDER_COUNT = 80; //80個柱面
private int SECTORS_COUNT = 18;
private MAGNETIC_HEAD magneticHead = MAGNETIC_HEAD.MAGNETIC_HEAD_0;
private int current_cylinder = 0;
private int current_sector = 0;
private HashMap>>floppy = new HashMap>>(); //一個磁盤兩個面
public Floppy() {initFloppy();
}
private void initFloppy() {//一個磁盤有兩個盤面
floppy.put(MAGNETIC_HEAD.MAGNETIC_HEAD_0.ordinal(), initFloppyDisk());
floppy.put(MAGNETIC_HEAD.MAGETIC_HEAD_1.ordinal(), initFloppyDisk());
}
private ArrayList>initFloppyDisk() {ArrayList>floppyDisk = new ArrayList>(); //磁盤的一個面
//一個磁盤面有80個柱面
for(int i = 0; i< CYLINDER_COUNT; i++) {floppyDisk.add(initCylinder());
}
return floppyDisk;
}
private ArrayListinitCylinder() {//構造一個柱面,一個柱面有18個扇區
ArrayListcylinder = new ArrayList();
for (int i = 0; i< SECTORS_COUNT; i++) {byte[] sector = new byte[SECTOR_SIZE];
cylinder.add(sector);
}
return cylinder;
}
public void setMagneticHead(MAGNETIC_HEAD head) {magneticHead = head;
}
public void setCylinder(int cylinder) {if (cylinder< 0) {this.current_cylinder = 0;
}
else if (cylinder >= 80) {this.current_cylinder = 79;
}
else {this.current_cylinder = cylinder;
}
}
public void setSector(int sector) {//sector 編號從1到18
if (sector< 0) {this.current_sector = 0;
}
else if (sector >18) {this.current_sector = 18 - 1;
}
else {this.current_sector = sector - 1;
}
}
public byte[] readFloppy(MAGNETIC_HEAD head, int cylinder_num, int sector_num) {setMagneticHead(head);
setCylinder(cylinder_num);
setSector(sector_num);
ArrayList>disk = floppy.get(this.magneticHead.ordinal());
ArrayListcylinder = disk.get(this.current_cylinder);
byte[] sector = cylinder.get(this.current_sector);
return sector;
}
public void writeFloppy(MAGNETIC_HEAD head, int cylinder_num, int sector_num, byte[] buf) {setMagneticHead(head);
setCylinder(cylinder_num);
setSector(sector_num);
ArrayList>disk = floppy.get(this.magneticHead.ordinal());
ArrayListcylinder = disk.get(this.current_cylinder);
cylinder.set(this.current_sector, buf);
}
public void makeFloppy(String fileName) {try {DataOutputStream out = new DataOutputStream(new FileOutputStream(fileName));
for (int head = 0; head<= MAGNETIC_HEAD.MAGETIC_HEAD_1.ordinal(); head++) {for (int cylinder = 0; cylinder< CYLINDER_COUNT; cylinder++) {for (int sector = 1; sector<= SECTORS_COUNT; sector++) {byte[] buf = readFloppy(MAGNETIC_HEAD.values()[head], cylinder, sector);
out.write(buf);
}
}
}
} catch (Exception e) {// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
讀寫虛擬軟盤需要調用接口readFloppy 或 writeFloppy
使用這些接口時必須指定磁頭 柱面和扇區號
3.主程序在主程序中 我將上節用匯編編譯的操作系統內核寫入到虛擬軟盤中 然后將虛擬軟盤寫成磁盤文件 具體代碼如下:
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
public class OperatingSystem {private Floppy floppyDisk = new Floppy();
private void writeFileToFloppy(String fileName) {File file = new File(fileName);
InputStream in = null;
try {in = new FileInputStream(file);
byte[] buf = new byte[512];
buf[510] = 0x55;
buf[511] = (byte) 0xaa;
if (in.read(buf) != -1) {//將內核讀入到磁盤第0面,第0柱面,第1個扇區
floppyDisk.writeFloppy(Floppy.MAGNETIC_HEAD.MAGNETIC_HEAD_0, 0, 1, buf);
}
} catch(IOException e) {e.printStackTrace();
return;
}
}
public OperatingSystem(String s) {writeFileToFloppy(s);
}
public void makeFllopy() {floppyDisk.makeFloppy("system.img");
}
public static void main(String[] args) {OperatingSystem op = new OperatingSystem("boot.bat");
op.makeFllopy();
}
}
4.匯編軟盤讀寫在前面,我們的內核加載到內存后,會打印出一條語句 而語句與內核代碼都存儲在同一個扇區中
這一次,我們將要打印的語句存儲在第一柱面的第二扇區,內核加載如內存后,通過BIOS調用將要打印的語句從指定位置讀出,然后再顯示到屏幕上,代碼如下:
org 0x7c00;
jmp entry
db 0x90
DB "OSKERNEL"
DW 512
DB 1
DW 1
DB 2
DW 224
DW 2880
DB 0xf0
DW 9
DW 18
DW 2
DD 0
DD 2880
DB 0,0,0x29
DD 0xFFFFFFFF
DB "MYFIRSTOS "
DB "FAT12 "
RESB 18
entry:
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov si, msg
readFloppy:
mov CH, 1 ;CH 用來存儲柱面號
mov DH, 0 ;DH 用來存儲磁頭號
mov CL, 2 ;CL 用來存儲扇區號
mov BX, msg ; ES:BX 數據存儲緩沖區
mov AH, 0x02 ; AH = 02 表示要做的是讀盤操作
mov AL, 1 ; AL 表示要練習讀取幾個扇區
mov DL, 0 ;驅動器編號,一般我們只有一個軟盤驅動器,所以寫死
;為0
INT 0x13 ;調用BIOS中斷實現磁盤讀取功能
jc error
putloop:
mov al, [si]
add si, 1
cmp al, 0
je fin
mov ah, 0x0e
mov bx, 15
int 0x10
jmp putloop
fin:
HLT
jmp fin
error:
mov si, errmsg ;出現錯誤打印error
jmp putloop
msg:
RESB 64
errmsg:
DB "error"
將上面的代碼編譯一下
nasm boot_readstring_from_sector.asm -o boot.bat
在java代碼中進行修改:
我們在生成虛擬軟盤的java代碼中把把要輸出的語句寫入到虛擬軟盤的1柱面,2扇區
這里 將 “This is a text from cylinder 1 and sector 2” 放在了軟盤的1柱面 2扇區
在匯編中 運行時 對這個區域進行讀取 并將內容輸出到屏幕上
public void makeFllopy() {String s = "This is a text from cylinder 1 and sector 2";
floppyDisk.writeFloppy(Floppy.MAGNETIC_HEAD.MAGNETIC_HEAD_0, 1, 2, s.getBytes());
floppyDisk.makeFloppy("system.img");
}
運行代碼 生成system.img
載入后運行:
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
網站題目:MacOS環境-手寫操作系統-02-讀寫軟盤-創新互聯
URL分享:http://m.kartarina.com/article16/ccgogg.html
成都網站建設公司_創新互聯,為您提供網頁設計公司、電子商務、網站改版、定制開發、軟件開發、服務器托管
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯