内容简介:之前做的系统内核,放在虚拟软盘的第一扇区,由于一个扇区只有512字节,因此系统内核的大小无法超过512字节。但是,一个拥有完整功能的内核不可能只有512字节,因此要想越过512字节的限制,具体做法就是做一个内核加载器(大小小于512字节),放入第一扇区,加载器加载入内存后,再将内核从软盘加载到系统内存,最后跳转到内核的加载地址假设把编译好的内核代码写入软盘的第一柱面,第2扇区,那么加载器的代码如下(boot.asm)
之前做的系统内核,放在虚拟软盘的第一扇区,由于一个扇区只有512字节,因此系统内核的大小无法超过512字节。但是,一个拥有完整功能的内核不可能只有512字节,因此要想越过512字节的限制,具体做法就是做一个内核加载器(大小小于512字节),放入第一扇区,加载器加载入内存后,再将内核从软盘加载到系统内存,最后跳转到内核的加载地址
假设把编译好的内核代码写入软盘的第一柱面,第2扇区,那么加载器的代码如下(boot.asm)
org 0x7c00; LOAD_ADDR EQU 0X8000 entry: mov ax, 0 mov ss, ax mov ds, ax mov es, ax mov si, ax readFloppy: mov CH, 1 ;CH 用来存储柱面号 mov DH, 0 ;DH 用来存储磁头号 mov CL, 2 ;CL 用来存储扇区号 mov BX, LOAD_ADDR ;ES:BX 数据存储缓冲区 mov AH, 0x02 ;AH = 02 表示要做的是读盘操作 mov AL, 1 ;AL表示要练习读取几个扇区 mov DL, 0 ;驱动器编号,一般我们只有一个软盘驱动器,所以写死为0 INT 0x13 ;调用BIOS中断实现磁盘读取功能 JC fin jmp LOAD_ADDR fin: HLT jmp fin
readFloppy
这段代码的作用是从软盘的1柱面2扇区,将内核读取到系统内存的0x8000处,读取成功后,通过一个 jmp
跳转到内核的加载地址,将机器的控制权转交给内核。内核代码如下(kernel.asm)
org 0x8000 entry: mov ax,0 mov ss,ax mov ds,ax mov es,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 "This is Hello World from kernel"
下载 nasm软件 对汇编语言进行编译。使用命令分别编译加载器和内核:
nasm boot.asm -o boot.bat nasm kernel.asm -o kernel.bat
编译好以后,通过 java 代码将编译好的内核写入虚拟软盘
Floppy.java
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<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) { 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<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); byte[] buffer = cylinder.get(this.current_sector); System.arraycopy(buf, 0, buffer, 0, buf.length); } public void makeFloppy(String fileName) { try { DataOutputStream out = new DataOutputStream(new FileOutputStream(fileName)); 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) { e.printStackTrace(); } } }
OPeratingSystem.java
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class OperatingSystem { private Floppy floppyDisk = new Floppy(); private int MAX_SECTOR_NUM = 18; private void writeFileToFloppy(String fileName, boolean bootable, int cylinder, int beginSec) { File file = new File(fileName); InputStream in = null; try { in = new FileInputStream(file); byte[] buf = new byte[512]; if (bootable) { buf[510] = 0x55; buf[511] = (byte) 0xaa; } while (in.read(buf) > 0) { // 将内核读入到磁盘第0面,第0柱面,第1个扇区 floppyDisk.writeFloppy(Floppy.MAGNETIC_HEAD.MAGNETIC_HEAD_0, cylinder, beginSec, buf); beginSec++; if (beginSec > MAX_SECTOR_NUM) { beginSec = 1; cylinder++; } } } catch (IOException e) { e.printStackTrace(); return; } } public OperatingSystem(String s) { writeFileToFloppy(s, true, 0, 1); } public void makeFllopy() { writeFileToFloppy("kernel.bat", false, 1, 2); floppyDisk.makeFloppy("system.img"); } public static void main(String[] args) { OperatingSystem op = new OperatingSystem("boot.bat"); op.makeFllopy(); } }
运行的是 OperatingSystem.java
代码。将生成的虚拟软盘文件system.img加载到虚拟机中启动,就可以看到如下效果
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C Primer Plus
Stephen Prata、云巅工作室 / 云巅工作室 / 人民邮电出版社 / 2005-2-1 / 60.00元
《C Primer Plus(第5版)(中文版)》共17章。第1、2章学习C语言编程所需的预备知识。第3到15章介绍了C语言的相关知识,包括数据类型、格式化输入输出、运算符、表达式、流程控制语句、函数、数组和指针、字符串操作、内存管理、位操作等等,知识内容都针对C99标准;另外,第10章强化了对指针的讨论,第12章引入了动态内存分配的概念,这些内容更加适合读者的需求。第16章和第17章讨论了C预处......一起来看看 《C Primer Plus》 这本书的介绍吧!