代码
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
运行结果:
分析
这个汇编代码主要是在屏幕上输出“hello world”。接着上一节说,当BIOS发现引导扇区时,会将这512字节的内容装载到内存的0000:7c00
处(也就是汇编代码第一行写的那样),然后跳转到7c00处将控制权彻底交给这段代码。到此,计算机不再由BIOS中的程序来控制,而是由操作系统的一部分来控制。
看接下来的代码,给要用的寄存器ax赋值0,让ss、ds、es指向相同的段,以便在以后进行数据操作的时候能定位到正确的位置。si指向的是msg内容的起始地址,该内容就是字符串,putloop就是使用跳转指令实现循环,调用int 0x10打印字符在屏幕上。fin相当于进入死循环。
通过这样就代替了上一节用数组来存储一大堆数据,这里更改java代码,将这段汇编语言文件加载到二进制文件中。
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.bat");
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();
}
}
首先将汇编语言通过nasm软件将刚才的汇编语言文件编译成boot.bat文件,java将此文件读入。