真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MacOS環(huán)境-手寫操作系統(tǒng)-02-讀寫軟盤-創(chuàng)新互聯(lián)

讀寫軟盤

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

創(chuàng)新互聯(lián)公司是一家專業(yè)提供棲霞企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、HTML5、小程序制作等業(yè)務(wù)。10年已為棲霞眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。1.簡介

前文中我們將一段代碼通過軟盤加載到了系統(tǒng)內(nèi)存中 并指示cpu執(zhí)行加入到內(nèi)存的代碼

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

通常的做法是 被加載進(jìn) 內(nèi)存的512byte程序 實(shí)際上是一個內(nèi)核加載器 它運(yùn)行起來之后 通過讀取磁盤 將存儲在磁盤上的內(nèi)核代碼加載到指定的內(nèi)存結(jié)構(gòu)中去 然后在把cpu的控制權(quán)提交給加載進(jìn)來的系統(tǒng)內(nèi)核

硬盤的結(jié)構(gòu)

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

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

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

一個扇區(qū)的大小正好是512k

從而,當(dāng)我們把數(shù)據(jù)存儲到軟盤上時,數(shù)據(jù)會分解成若干個512Byte大小的塊,然后寫入到扇區(qū)里

2.模擬

我們要模擬的是3.5寸軟盤 這種軟盤的特點(diǎn)是

它有兩個盤面 因此就對應(yīng)兩個磁頭 每個盤面有80個磁道 也就是柱面 編號分別為0-79 每個柱面都有18個扇區(qū) 編號分別為1-18 所以一個盤面可以存儲的數(shù)據(jù)量大小為:
512 * 18 * 80
一個軟盤有兩個盤面,因此一個軟盤可以存儲的數(shù)據(jù)為:
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() {//構(gòu)造一個柱面,一個柱面有18個扇區(qū)
        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();
        }
    }
}

讀寫虛擬軟盤需要調(diào)用接口readFloppy 或 writeFloppy

使用這些接口時必須指定磁頭 柱面和扇區(qū)號

3.主程序

在主程序中 我將上節(jié)用匯編編譯的操作系統(tǒng)內(nèi)核寫入到虛擬軟盤中 然后將虛擬軟盤寫成磁盤文件 具體代碼如下:

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) {//將內(nèi)核讀入到磁盤第0面,第0柱面,第1個扇區(qū)
                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.匯編軟盤讀寫

在前面,我們的內(nèi)核加載到內(nèi)存后,會打印出一條語句 而語句與內(nèi)核代碼都存儲在同一個扇區(qū)中

這一次,我們將要打印的語句存儲在第一柱面的第二扇區(qū),內(nèi)核加載如內(nèi)存后,通過BIOS調(diào)用將要打印的語句從指定位置讀出,然后再顯示到屏幕上,代碼如下:

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 用來存儲扇區(qū)號

    mov          BX, msg       ; ES:BX 數(shù)據(jù)存儲緩沖區(qū)

    mov          AH, 0x02      ;  AH = 02 表示要做的是讀盤操作
    mov          AL,  1        ; AL 表示要練習(xí)讀取幾個扇區(qū)
    mov          DL, 0         ;驅(qū)動器編號,一般我們只有一個軟盤驅(qū)動器,所以寫死   
                               ;為0
    INT          0x13          ;調(diào)用BIOS中斷實(shí)現(xiàn)磁盤讀取功能

    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   ;出現(xiàn)錯誤打印error
    jmp   putloop

msg:
    RESB   64
errmsg:
    DB "error"

將上面的代碼編譯一下

nasm boot_readstring_from_sector.asm -o boot.bat

在java代碼中進(jìn)行修改:

我們在生成虛擬軟盤的java代碼中把把要輸出的語句寫入到虛擬軟盤的1柱面,2扇區(qū)

這里 將 “This is a text from cylinder 1 and sector 2” 放在了軟盤的1柱面 2扇區(qū)

在匯編中 運(yùn)行時 對這個區(qū)域進(jìn)行讀取 并將內(nèi)容輸出到屏幕上

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");
    }

運(yùn)行代碼 生成system.img

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

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


本文標(biāo)題:MacOS環(huán)境-手寫操作系統(tǒng)-02-讀寫軟盤-創(chuàng)新互聯(lián)
URL網(wǎng)址:http://weahome.cn/article/ccgogg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部