我们开发程序的时候,操作系统给我们提供API
我们开发操作系统的时候,BIOS给我们提供API
只有汇编支持我们直接操作计算机的硬件(寄存器),C语言也不行
只有汇编语言和C语言,能够通过指针访问内存函数调用时需要传递参数,那么调用bios提供的函数时,怎么传递参数呢,做法是,把需要传递的参数放入到指定的寄存器中,例如想要在屏幕上输出字符,那么bios提供的编号为0x10的库函数可以实现这个功能,同时按规定,要把寄存器ah设置为0x0e, 把要输出的字符的ascii值放入到寄存器al, 同时要把寄存器设bh的值设置成0,字符的颜色可以通过寄存器bl的值来设定
其实这里和上一篇用Java做一个最小的操作系统内核是一样的,上次是直接把二进制代码写出来了,这次是先自己写汇编,然后用nasm将汇编程序编译成.bin文件,再在java中打开bin文件,将里面的内容写入到生成的img文件中,不够的补0,再添加55aa
org是指示BIOS在将我们这段代码加载进内存的时候,写入到内存0x7c00的位置
entry将寄存器初始化
boot.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 ;调用BIOS jmp putloop fin: HLT jmp fin msg: DB 0x0a, 0x0a db "hello, world" db 0x0a db 0
这是nasm编译后的boot.bin
将boot.bin复制到java工作目录下
用java将boot.bin读入,然后写入到system.img
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 int[] imgContent = new int[]{ // 0xeb,0x4e,0x90,0x48,0x45,0x4c,0x4c,0x4f,0x49,0x50,0x4c,0x00,0x02,0x01,0x01,0x00,0x02,0xe0, // 0x00,0x40,0x0b,0xf0,0x09,0x00,0x12,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x0b,0x00,0x00,0x00,0x00,0x29, // 0xff,0xff,0xff,0xff,0x48,0x45,0x4c,0x4c,0x4f,0x2d,0x4f,0x53,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32, // 0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x00,0x00,0x8e, // 0xd0,0xbc,0x00,0x7c,0x8e,0xd8,0x8e,0xc0,0xbe,0x74,0x7c,0x8a, // 0x04,0x83,0xc6,0x01,0x3c,0x00,0x74,0x09,0xb4,0x0e,0xbb,0x0f,0x00,0xcd,0x10,0xeb,0xee,0xf4,0xeb,0xfd // }; private ArrayList<Integer> imgByteToWrite = new ArrayList<Integer>(); private void readKernelFromFile(String fileName) { File file = new File(fileName); InputStream in = null; try { in = new FileInputStream(file); int tempbyte; while ((tempbyte = in.read()) != -1) { imgByteToWrite.add(tempbyte); } } catch(IOException e) { e.printStackTrace(); return; } imgByteToWrite.add(0x55); imgByteToWrite.add(0xaa); imgByteToWrite.add(0xf0); imgByteToWrite.add(0xff); imgByteToWrite.add(0xff); } public OperatingSystem(String s) { /* for (int i = 0; i < imgContent.length; i++) { imgByteToWrite.add(imgContent[i]); } imgByteToWrite.add(0x0a); imgByteToWrite.add(0x0a); for (int j = 0; j < s.length(); j++) { imgByteToWrite.add((int)s.charAt(j)); } imgByteToWrite.add(0x0a); int len = 0x1fe; int curSize = imgByteToWrite.size(); for (int k = 0; k < len - curSize; k++) { imgByteToWrite.add(0); } //0x1fe-0x1f: 0x55, 0xaa //0x200-0x203: f0 ff ff imgByteToWrite.add(0x55); imgByteToWrite.add(0xaa); imgByteToWrite.add(0xf0); imgByteToWrite.add(0xff); imgByteToWrite.add(0xff); */ readKernelFromFile("boot.bin"); int len = 0x168000; int curSize = imgByteToWrite.size(); for (int l = 0; l < len - curSize; l++) { imgByteToWrite.add(0); } } public void makeFllopy() { try { DataOutputStream out = new DataOutputStream(new FileOutputStream("system.img")); for (int i = 0; i < imgByteToWrite.size(); i++) { out.writeByte(imgByteToWrite.get(i).byteValue()); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { OperatingSystem op = new OperatingSystem("hello, this is my first line of my operating system code"); op.makeFllopy(); } }
用virtualbox运行system.img
参考:
有改动
https://blog.csdn.net/tyler_download/article/details/51761750