用java和汇编开发一个Hello World系统内核
文章目录
- 1 汇编实现
- 1.1 汇编实现
- 1.2 使用nasm编译器进行编译
- 2 利用java生成软盘文件
- 2.1 利用java生成软盘文件的代码如下
1 汇编实现
1.1 汇编实现
汇编代码如下:
org 0x7c00;entry:mov ax, 0mov ss, axmov ds, axmov es, axmov si, msgputloop:mov al, [si]add si, 1cmp al, 0je finmov ah, 0x0emov bx, 15int 0x10jmp putloopfin:HLTjmp finmsg:DB 0x0a, 0x0adb "hello, world"db 0x0adb 0
上面的汇编代码主要是设置了一些初始化数据,然后调用bios中断,将某个缓冲区中的字符打印到屏幕上,然后进入一个死循环。代码段的详细解释如下:
/*
org 的意思是origin, 中文意思是“起始,起源,” org 后面的7c00 是物理内存地址,假设物理内存是一个byte类型
的大数组,例如byte[] memory, 如果你有2 G内容,换算成字节就是2097152, 也就相当于memory数组有2097152字
节,于是当虚拟机上电,然后new一块内存 byte[] memory = new byte[2097152]. org 0x7c00 的意思是将本汇编
编译后的二进制数据从memory[0x7c00]处写入memory.
*/
org 0x7c00;/*
jmp entry 中的jmp 其实就是c语言中的语句goto, jmp entry 其实是让cpu跳转到entry 处,执行entry下面的代
码,如果entry是一个函数名字的话,jmp entry 相当于调用entry函数,类比于java就是函数调用:entry();
*/
jmp entry// 下面的代码一直到RESB 18这行代码是可以直接删除的,我这里之所以放在这里是为了记录一下汇编知识点
/*
jmp entry 对应的机器代码,长度是3字节,那么db 0x90 的意思就是 memory[0x7c00+3] = 0x90, 也就是说db
0x90 实际上做的是赋值操作,db 0x90 表示将给定位置处的一个字节赋予数值0x90, 赋值的内存位置就在0x7c00+3处。
*/
db 0x90
/*
DB 和 db 是同一个意思, 那么DB “OSKERNEL” 意思是,strcpy(memory + 0x7c00 + 3 + 1, “OSKERNEL”); 也就
是把”OSKERNEL”这个字符串拷贝到内存0x7c00 + 3 + 1 处, 3是什么意思呢,3就是jmp entry 编译成二进制代码后
的数据长度, 1 就是db 0x90 所所赋值的那个字节的长度。DW 跟DB是一个意思, DB 是将数据赋值给一个字节,由于
一个字节只有8位,那么赋值给这个字节的数据大小不能超过256, 512大于256,所以需要两个字节才能存储512这个数
据,DD 0xFFFFFFFF 就是把0xFFFFFFFF存储到四个字节长的内存中, 语句RESB 18 表示把接下来的18个字节的内存全
部初始化为0,转换为java代码就类似于:
byte[] block = new byte[18];
for (int i = 0; i < 18; i++) {
block[i] = 0;
}
*/
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 18entry:
/*
先做的是初始化一系列寄存器,寄存器其实相当于java程序中,我们定义的变量,ax 是一个2字节长的寄存器, mov
ax, 0是把数值0放入到ax寄存器中,类比于java 就是:
char ax = 0;
char类型的数据在java中是两个字节长,跟寄存器ax的长度一样,类似的,语句: mov ss, ax 相当于java的 char
ss = ax; 后面的语句意思类推。
*/mov ax, 0mov ss, axmov ds, axmov es, ax
/*
我们要注意看语句 mov si, msg. msg 相当于一段内存,
msg:
DB 0x0a, 0x0a
db “hello, world”
db 0x0a
就类似于 C 语言中的char* msg = “\n\nhello,world\n”. 字符’\n’的ascii值就是0xa.mov si, msg 就相当于把msg内存的起始地址放入到寄存器si里。如果用C语言做类比,那么就相当于: char* si = msg;
*/mov si, msgputloop:
/*
mov al, [si]
[si]表示读取si存储的内存地址处的一个字节长度的信息,
mov al, [si] ,把该字节的数据存储到寄存器al 中,ax是两个字节长度的寄存器,这样ax就可以分解成两部分,第一
部分就对应于al, 第二部分就对应于ah,
也就是al, ah合起来就是ax, 对应于C语言就相当于 char ax[2], al 表示的是ax[0], ah 表示的就是 ax[1], mov al, [si], 转换成C语言就是 char al = *si;
*/mov al, [si]
/* add si, 1 表示将寄存器si中的数值加1,也就相当于C语言的 si++; */add si, 1
/* cmp al, 0 表示将al寄存器中的数据跟0比较,看al中的值是否等于0 */cmp al, 0
/*
je fin 中的 je 表示 jump if equal, 也就是如果al 的值确实等于0,那么就跳转到fin所表示的代码处去执行,转
换成C语言就是 :
if (al == 0) {
goto fin
}
*/je fin/*
mov ah, 0xe 就是把0xe赋值给寄存器 ah, mov bx ,15 同理。接下来要调用一个中断,中断其实就是一个函数调用,
我们在写c语言或java程序时,往往需要调用一些系统库函数,例如printf, 或java的System.out.print. 中断就是
bios提供给汇编语言的库函数,这些库函数都放入到一个数组里,int 0x10 意思是在库函数数组中取出第0x10个库函
数,然后执行该库函数的代码。我们知道,函数调用时需要传递参数,那么调用bios提供的函数时,怎么传递参数呢,做法是,把需要传递的参数放入到
指定的寄存器中,例如想要在屏幕上输出字符,那么bios提供的编号为0x10的库函数可以实现这个功能,同时按规定,
要把寄存器ah设置为0x0e, 把要输出的字符的ascii值放入到寄存器al, 同时要把寄存器设bh的值设置成0,字符的颜色
可以通过寄存器bl的值来设定。看起来相当麻烦,这是由于我们做的是非常底层的编程,所以麻烦也就不可避免。
*/mov ah, 0x0emov bx, 15int 0x10jmp putloop
/*
于是代码片段:
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
}printf(“%c”, al);
} while(true);
*//*
hlt 表示 halt, 也就是让cpu进入休眠状态,如果此时我们点击一下键盘,或动一下鼠标,那么cpu就被唤醒,然后执行hlt后面的语句:
jmp fin
也就是跳转到fin开始处去执行,也就是进入了死循环。
*/
fin:HLTjmp finmsg:DB 0x0a, 0x0adb "hello, world"db 0x0adb 0
1.2 使用nasm编译器进行编译
nasm boot.asm -o boot.bat
。
2 利用java生成软盘文件
2.1 利用java生成软盘文件的代码如下
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 ArrayList<Integer> imgByteToWrite = new ArrayList<Integer>();private void readKernelFormatFile(String fileName){File file = new File(fileName);FileInputStream in = null;try{in = new FileInputStream(file);int val = 0;while ((val = in.read()) != -1){imgByteToWrite.add(val);}in.close();}catch (IOException e){e.printStackTrace();return;}// 当前代码之后至510字节全部写0int len = 510;int curlen = imgByteToWrite.size();for (int i=curlen; i<len; i++){imgByteToWrite.add(0);}// 第511、512字节为磁盘主引导扇区的有效标志,必须为0x55、0xaaimgByteToWrite.add(0x55);imgByteToWrite.add(0xaa);//imgByteToWrite.add(0xf0);//imgByteToWrite.add(0xff);//imgByteToWrite.add(0xff);}public OperatingSystem(String fileName) {readKernelFormatFile(fileName);// 1.44MB大小的软盘int len = 0x168000;int curSize = imgByteToWrite.size();for (int i=curSize; i<len; i++) {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 blocke.printStackTrace();}}public static void main(String[] args) {OperatingSystem op = new OperatingSystem("boot.bat");op.makeFllopy();}
}
参考资料:
- Linux操作系统, 构建自己的内核
用java和汇编开发一个Hello World系统内核相关推荐
- ***JAVA*和*Eclipse*开发一个换装小游戏**
JAVA和Eclipse开发一个换装小游戏** 家有一女如有一宝,最近女朋友的少女心有点爆棚,作为一个计算机专业的人,我的情商简直是低到吓人,但是我还是想到了,亲自给女朋友做一个换装的小游戏,来满足女 ...
- JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库
JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库 JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库 本源码技术栈: 项目 ...
- java检查手机号是否被注册_【java】如何开发一个检测手机号注册过哪些网站的应用?...
问题描述 使用python或其它语言开发一个检测手机号注册过哪些网站的应用 问题出现的环境背景及自己尝试过哪些方法 在登陆一个很久没使用的网站时,原注册的手机号已弃用无法找回密码.所以希望有这么一款应 ...
- Java程序:开发一个应用,模拟计算机对移动存储设备的读写,即移动存储设备有U盘、手机卡、移动硬盘、闪卡等设备
开发一个应用,模拟计算机对移动存储设备的读写,即移动存储设备有U盘.手机卡.移动硬盘.闪卡等设备 public interface Mobile {void Read();void Write();} ...
- java安卓怎么开发一个新闻app,一个基于Android系统的新闻客户端(一)
一个基于Android系统的新闻客户端(一) 一.整体概述 在服务器端,通过对凤凰网的抓取存入数据库,客户端通过向服务器发送请求得到新闻. 服务端用WCF,宿主为window服务,客户端为Java写的 ...
- 使用Win32汇编开发一个dll并在C#中调用
使用RadASM,新建一个Dll Project: 下一步,默认: dll包含Def文件: 完成工程构建:都默认: 完成以后项目结构如下: asm代码: .386 .model flat, stdca ...
- 用java开发一个Hello Word系统内核
文章目录 1 最简单的Hello World系统内核实现 2 使用VirtualBox创建虚拟机并加载上述生成的软盘文件 2.1 创建虚拟机 2.2 加载软盘中的内核 1 最简单的Hello Worl ...
- 利用MyEclipse开发一个调用webservice接口的程序
上一篇文章我们已经学习了如何使用Java 工具MyEclipse开发一个webservice接口,那么接口开发好了如何调用?接下来我们就来解决这个问题. 1:首先随便创建一个Java project选 ...
- 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?
2019独角兽企业重金招聘Python工程师标准>>> 今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制 ...
最新文章
- cxf 发布 一个简单的 webservice
- 掌握神经网络模型的快捷方式
- 工作32:get之前打印
- rsync 服务快速部署手册
- JS判断是否是科学计算结果并处理
- 【leetcode】16 3Sum Closest
- pytrhon画图matplolib
- 走自己的路,记得回头看看
- QQ、空间、新浪微博、微信分享
- JDK安装包和Mysql安装包整理
- JAVA日志框架与日志系统
- Gos —— 搭建基础环境
- 我酸了,曝光几个腾讯 阿里P8前同事的副业收入
- matlab绘制那奎斯特曲线和bode图
- Python统计文件夹大小
- Java+MySQL基于SSM的在线论坛交流系统
- 分布式系统理论:Quorum算法
- 【C++】指针深度解析
- mybatis的原理详解
- [转]英文中的偏旁部首及其记忆