自制操作系统3:构建自己的内核--软盘读写

参考:
https://blog.csdn.net/tyler_download/article/details/51815483
https://www.bilibili.com/video/BV1VJ41157wq?p=3&spm_id_from=pageDriver
模拟操作系统早期DOS时代的做法,操作系统内核写在软盘上,上两节有读取量的限制,最多将前512字节读取到内存中。
当操作系统大于512byte就不能这样了。改改思路,第一个扇区不再是内核本身,而是一个内核加载器。负责把操作系统内核从软盘读取到内存
Floppy.java
代码注释有些问题,应该是写完一个盘面,再写另外的盘面。
512×18×80×2=1474560bytes=1440KB=1.5M
OpSystem.java
重复上节的例子,这次是用Floppy类在写磁盘,更精准,比如在512字节末尾两个字节写上0x55aa
boot_helloworld.asm于上节boot.asm相同
nasm -o boot.bat boot_helloworld.asm
发现编译问题,原来从网页上copy下来不行,直接把boot.asm拷贝过来就行,应该是有不可见的错误字符。
运行效果也相同,virtualbox中显示hello world.

改为读盘的汇编:boot_readstring_from_sector.asm
运行发现sytem.img的大小有误:1474091,应该是1474560,差了469字节,应该是第二扇区的内容不足512,没有补充。需要修改一下代码:
public void writeFloppy(MAGNETIC_HEAD head, int cylinder_num, int sector_num, byte[] buf) {
        setMagneticHead(head);
        setCylinder(cylinder_num);
        setSector(sector_num);

        ArrayList<ArrayList<byte[]>> disk = floppy.get(this.magneticHead.ordinal());
        ArrayList<byte[]> cylinder = disk.get(this.current_cylinder);
        //cylinder.set(this.current_sector, buf);
        byte[] buffer = cylinder.get(this.current_sector);
        System.arraycopy(buf,0,buffer,0,buf.length);

}
重新运行system.img就正确了,大小1474560

按文中加载运行是一个黑屏,未读到文字,二进制查看已经写道磁盘上了,估计是写的顺序不对。修正了一下:柱面在外层,盘面在内层。
    public void makeFloppy(String fileName) {
        /**
         * 虚拟软盘是一个纯粹的二进制文件
         * 512×18 盘面0,柱面0
         * 521×18 盘面1,柱面0
         * 512×18 盘面0,柱面1
         * 512×18 盘面1,柱面1
         * 以此类推
         */
        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);
                    }
                }
            }

*/
            for (int cylinder = 0; cylinder < CYLINDER_COUNT; cylinder++) {
                for (int head = 0; head <= MAGNETIC_HEAD.MAGETIC_HEAD_1.ordinal(); head++) {
                    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();
        }
    }

这样就可以运行了:

boot_helloworld.asm

org  0x7c00;

entry:
  mov  ax, 0
  mov  ss, ax
  mov  ds, ax
  mov  es, ax
  
  mov  si, msg
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
  
msg:
  DB 0x0a,0x0a
  DB "Hello,World"
  DB 0x0a
  DB 0

boot_readstring_from_sector.asm

org 0x7c00;

entry:
  mov ax, 0
  mov ss, ax
  mov ds, ax
  mov es, ax
  mov si, msg

readFloppy:
  mov CH, 1
  mov DH, 0
  mov CL, 2
  
  mov BX, msg
  
  mov AH, 0x02
  mov AL, 1
  mov DL, 0
  int 0x13
  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
  jmp putloop
  
msg:
  RESB 64
errmsg:
  db "error"

Floppy.java

package osfloppy;

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 SECTORS_COUNT = 18;
    private int CYLINDER_COUNT = 80;

    private MAGNETIC_HEAD magneticHead = MAGNETIC_HEAD.MAGNETIC_HEAD_0;
    private int current_cylinder = 0;
    private int current_sector = 0;

    // 80*18*512
    //一个磁盘两个面
    private HashMap<Integer,ArrayList<ArrayList<byte[]>> > floppy = new HashMap<Integer,ArrayList<ArrayList<byte[]>> >();

    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<ArrayList<byte[]>> initFloppyDisk() {
        //磁盘的一个面
        ArrayList<ArrayList<byte[]>> floppyDisk = new ArrayList<ArrayList<byte[]>>();
        //一个磁盘面有80个柱面
        for(int i = 0; i < CYLINDER_COUNT; i++) {
            floppyDisk.add(initCylinder());
        }
        return floppyDisk;
    }

    private ArrayList<byte[]> initCylinder() {
        //构造一个柱面,一个柱面有18个扇区
        ArrayList<byte[]> cylinder = new ArrayList<byte[]> ();
        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) {
        this.magneticHead = head;
    }

    public void setCylinder(int cylinder) {
        //80个柱面,磁道0-79
        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 = 17;
        } 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<ArrayList<byte[]>> disk = floppy.get(this.magneticHead.ordinal());
        ArrayList<byte[]> cylinder = 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<ArrayList<byte[]>> disk = floppy.get(this.magneticHead.ordinal());
        ArrayList<byte[]> cylinder = disk.get(this.current_cylinder);
        //cylinder.set(this.current_sector, buf);
        byte[] buffer = cylinder.get(this.current_sector);
        System.arraycopy(buf,0,buffer,0,buf.length);
    }
    public void makeFloppy(String fileName) {
        /**
         * 虚拟软盘是一个纯粹的二进制文件
         * 512×18 盘面0,柱面0
         * 521×18 盘面1,柱面0
         * 512×18 盘面0,柱面1
         * 512×18 盘面1,柱面1
         * 以此类推
         */
        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);
                    }
                }
            }
*/
            for (int cylinder = 0; cylinder < CYLINDER_COUNT; cylinder++) {
                for (int head = 0; head <= MAGNETIC_HEAD.MAGETIC_HEAD_1.ordinal(); head++) {
                    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();
        }
    }
}
OpSystem.java
package osfloppy;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class OpSystem {
    private Floppy floppyDisk = new Floppy();

    public OpSystem(String s) {
        writeFileToFloppy(s);
    }

    private void writeFileToFloppy(String fileName) {
        File file = new File(fileName);
        InputStream in;

        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 (Exception e) {
            e.printStackTrace();
            return;
        }
    }

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

    public static void main(String[] args) {
        OpSystem op = new OpSystem("boot.bat");
        op.makeFllopy();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值