MacOS環境-手寫操作系統-02-讀寫軟盤-創新互聯

讀寫軟盤

文章寫于兩年前的 MacBookAir(2015)
目前筆者為 MacBookPro M1 (抽查了部分 都運行正常)
Github項目地址: https://github.com/wdkang123/MyOperatingSystem
MacOS X86架構(x新版的arm架構的我沒有 所以大家自行測試)
VirtualBox
C/C++環境 (Xcode必裝)

創新互聯公司是一家專業提供棲霞企業網站建設,專注與成都網站制作、網站建設、外貿網站建設HTML5、小程序制作等業務。10年已為棲霞眾多企業、政府機構等服務。創新互聯專業網絡公司優惠進行中。1.簡介

前文中我們將一段代碼通過軟盤加載到了系統內存中 并指示cpu執行加入到內存的代碼

事實上,操作系統內核加載也是這么做的。只不過我們加載的代碼,大只能512 byte, 一個操作系統內核,少說也要幾百兆,由此,系統內核不可能直接從軟盤讀入系統內存

通常的做法是 被加載進 內存的512byte程序 實際上是一個內核加載器 它運行起來之后 通過讀取磁盤 將存儲在磁盤上的內核代碼加載到指定的內存結構中去 然后在把cpu的控制權提交給加載進來的系統內核

硬盤的結構

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lihpgkUm-1671687709613)(null)]
軟盤的物理結構如上圖 一個盤面被劃分成若干個圓圈

例如圖中的灰色圓圈 我們稱之為磁道 也可以稱作柱面

一個磁道或柱面 又被分割成若干部分 每一部分 我們稱之為一個扇區

一個扇區的大小正好是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

載入后運行:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WNvcQYK0-1671687709813)(null)]

你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

網站題目:MacOS環境-手寫操作系統-02-讀寫軟盤-創新互聯
URL分享:http://m.kartarina.com/article16/ccgogg.html

成都網站建設公司_創新互聯,為您提供網頁設計公司電子商務網站改版定制開發軟件開發服務器托管

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都app開發公司
主站蜘蛛池模板: 亚洲另类无码专区首页| heyzo高无码国产精品| 亚洲色偷拍另类无码专区| 成在人线av无码免费高潮水| av无码久久久久久不卡网站| 99久久人妻无码精品系列| 国产V片在线播放免费无码| 亚洲av永久无码精品三区在线4 | 少妇人妻无码精品视频app| 精品无码久久久久久国产 | 亚洲av无码精品网站| 国产精品爆乳奶水无码视频| 久久精品亚洲中文字幕无码麻豆 | 色综合AV综合无码综合网站| 国产成人精品无码一区二区老年人| 久久午夜无码免费| 狠狠噜天天噜日日噜无码| 久久久久久亚洲av无码蜜芽 | 天堂一区人妻无码| 欧洲成人午夜精品无码区久久| 少妇中文无码高清| 无码一区二区三区在线| 亚洲欧洲无码一区二区三区| 亚洲精品无码专区久久久| heyzo专区无码综合| 无码人妻一区二区三区免费视频| 内射精品无码中文字幕| 婷婷四虎东京热无码群交双飞视频| 国产免费无码一区二区| 国产午夜片无码区在线播放 | 国产精品无码AV一区二区三区| 亚洲Av无码乱码在线znlu| 日韩电影无码A不卡| 亚洲人成国产精品无码| julia无码人妻中文字幕在线| 无码AV动漫精品一区二区免费| 国产福利电影一区二区三区久久老子无码午夜伦不| 亚洲国产成人精品无码一区二区| 精品国精品无码自拍自在线| av无码国产在线看免费网站| 亚洲精品无码久久久久YW|