内容简介:上一节,我用Java制作了一个虚拟软盘,当把虚拟软盘插入虚拟机,启动机器后,屏幕就打印出了Java程序中设定的语句,然后卡死。在Java代码中,有一个二进制数组imgContent,它里面存储的实际上是一端二进制代码,当虚拟机设为从软盘启动后,这段代码会被BIOS读到内存中,然后指示CPU去执行imgContent所存储的二进制代码下面我就将imgContent数组中的内容,用汇编语言实现,并且详细阐述其作用,首先看看汇编语言怎么写
上一节,我用 Java 制作了一个虚拟软盘,当把虚拟软盘插入虚拟机,启动机器后,屏幕就打印出了Java程序中设定的语句,然后卡死。
在Java代码中,有一个二进制数组imgContent,它里面存储的实际上是一端二进制代码,当虚拟机设为从软盘启动后,这段代码会被BIOS读到内存中,然后指示CPU去执行imgContent所存储的二进制代码
汇编代码
下面我就将imgContent数组中的内容,用汇编语言实现,并且详细阐述其作用,首先看看汇编语言怎么写
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 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
首先看第一行代码 org 0x7c00
, org
的意思是“起始,起源”, org
后面的 7c00
是物理内存地址,假设物理内存是一个字节数组,例如 byte[] memory
,如果你有2M内容,就需要new2097152字节的内存, byte[] memory = new byte[2097152]
。 org 0x7c00
的意思就是将汇编编译后的二进制数据从 memory[0x7c00]
处写入 memory
。至于为什么是 0x7c00
,这就要问微软
jmp entry
中的 jmp
起始就是 c语言 中的 goto
, jmp entry
其实是让CPU跳转到 entry
处,执行 entry
下面的代码,如果 entry
是一个函数名, jmp entry
相当于调用 entry()
函数
从 db 0x90
到 RESB 18
这段代码做的是一些初始化工作。 jmp entry
对应的机器码长度是3字节,那么 db 0x90
的作用就是 memory[0x7c00+3]=9x90
,也就是说 db 9x90
实际上做的是赋值操作
DB
和 db
是相同的作用,所以 DB "OSKERNEL"
的意思是 strcpy(memory + 0x7c00 + 3 + 1,"OSKERNEL")
,也就是把"OSKERNEL"这个字符串拷贝到内存0x7c00 + 3 + 1处。3就是 jmp entry
所占的3字节长度,1就是 db ox90
所复制的那个字节的长度
DW
和 DB
是相同的意思,只不过 DB
是将数据赋值给一个字节, DW
是将数据赋值给两个字节,从上面代码也能看出来 DW 512
,因为512转换为二进制肯定超过了8位,所以不能用 DB
DD 0xFFFFFFFF
就是将 0xFFFFFFFF
存储到四个字节长的内存中
RESB 18
表示把接下来的18个字节的内容全部初始化为0,类似于下面的Java代码
byte[] block = new byte[18]; for(int i = 0;i < 18;i++) block[i] = 0;
接下来看 entry
代码,它的作用是初始化一系列寄存器,寄存器相当于Java程序中定义的变量, ax
是一个2字节长的寄存器, mov ax,0
就是把数值0放到 ax
寄存器中,类似Java的 char ax = 0
,char类型的数据在Java中也是2字节长。
类似的, mov ss,ax
相当于Java中的 char ss = ax
其中比较重要的语句是 mov si,msg
, msg
相当于一段内存
msg: DB 0x0a, 0x0a db "hello, world" db 0x0a
上面这段代码类似于C语言中的 char* msg = "\n\nhello,world\n"
, \n
的ASCII值就是 0x0a
。那么 mov si,msg
就相当于把 msg
内存的真实地址放到寄存器 si
里,如果用C语言表示就是 char* si = msg
接着看后面的代码 mov al,[si]
, [si]
表示读取 si
存储的内存地址中一个字节长度的信息,这行代码的含义就是把 [si]
内容数据存储到寄存器 al
中, ax
是两字节长的寄存器,这样 ax
就可以分解成两部分,第一部分是 al
,第二部分是 ah
,对应C语言就相当于 char ax[2]
, al
表示的是 ax[0]
, ah
表示的是 ax[1]
, mov ai,[si]
转换成C语言就是 char al = *si
add si,1
表示将寄存器 si
中的数值加1,也就相当于C语言中的 si++
cmp al,0
表示将寄存器 al
寄存器中的数据跟0比较,看 al
中的值是否等于0
je fin
中的 je
表示 jump if equal
,也就是如果 al
的值确实等于0,那么就跳转到 fin
所表示的代码处去执行,转换成C语言就是
if(al == 0) goto fin
mov ah,0xe
就是把 0xe
赋值给 ah
, mov bx,15
同理
接下来调用的是一个中断函数,我们在写C或Java程序时,往往需要调用一些系统库函数,例如 printf
,或 System.out.print
,中断函数就是BIOS提供给汇编语言的库函数,这些库函数都存放在一个数组里, int 0x10
的意思是在库函数数组中取出第 0x10
个库函数执行
有的函数调用时需要传递参数,如果想要调用BIOS提供的函数,在屏幕上输出字符,那么就要将传递的参数放入到指定的寄存器中。BIOS提供的编号为0x10的库函数可以实现这个功能,按照规定,要把寄存器 ah
的值设置为 0x0e
,把要输出字符的ASCII值放到寄存器 al
,同时要把寄存器 bh
的值设为0,字符的颜色可以通过寄存器 bl
的值来设定。
代码段
putloop: mov al, [si] add si, 1 cmp al, 0 je fin mov ah, 0x0e mov bx, 15 int 0x10 jmp putloop
就相当于C语言中的
do { char al = *si; si++; if(al == 0) goto fin print("%c",al); } while(true);
fin
处的代码就两条语句, htl
表示halt,也就是让CPU进入休眠状态,如果此时我们点击一下键盘或动一下鼠标,那么CPU就会被唤醒,然后执行 hlt
后面的语句 jmp fin
,又回到 fin
开始处去执行,进入无限循环
编译汇编代码
把上面的汇编代码存储成一个文件:boot.asm,然后利用汇编编译器nasm来编译, nasm boot.asm
,编译后会得到一个二进制文件,内容如下:
e94e 0090 4f53 4b45 524e 454c 0002 0101 0002 e000 400b f009 0012 0002 0000 0000 0040 0b00 0000 0029 ffff ffff 4d59 4649 5253 544f 5320 2046 4154 3132 2020 2000 0000 0000 0000 0000 0000 0000 0000 0000 00b8 0000 8ed0 8ed8 8ec0 be73 7c8a 0481 c601 003c 0074 09b4 0ebb 0f00 cd10 ebed f4eb fd0a 0a68 656c 6c6f 2c20 776f 726c 640a 00
修改Java代码
把这个二进制文件改名为boot.bat,拷贝到上一个Java程序的工程目录下,然后把Java程序进行修改,将这段二进制数据都入到imgContent数组中,代码如下
import java.util.ArrayList; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; 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) { 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) { 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(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 面试官:说说操作系统微内核和 Dubbo 微内核?
- 操作系统知识之内核与进程学习总结
- 详解操作系统内核对线程的调度算法
- 用Java做一个最小的操作系统内核
- 鸿蒙操作系统用的微内核到底是什么?
- 重磅直播:从Linux内核学习到自主操作系统研发
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ajax开发精要
柯自聪 / 电子工业出版社 / 2006 / 45.00
书籍目录: 概念篇 第1章 Ajax介绍 2 1.1 Ajax的由来 2 1.2 Ajax的定义 3 1.3 Web应用程序的解决方案 5 1.4 Ajax的工作方式 7 1.5 小结 8 第2章 B/S请求响应机制与Web开发模式 9 2.1 HTTP请求响应模型 9 2.2 B/S架构的请求响应机......一起来看看 《Ajax开发精要》 这本书的介绍吧!