文章目录

  • 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();}
}

参考资料:

  1. Linux操作系统, 构建自己的内核

用java和汇编开发一个Hello World系统内核相关推荐

  1. ***JAVA*和*Eclipse*开发一个换装小游戏**

    JAVA和Eclipse开发一个换装小游戏** 家有一女如有一宝,最近女朋友的少女心有点爆棚,作为一个计算机专业的人,我的情商简直是低到吓人,但是我还是想到了,亲自给女朋友做一个换装的小游戏,来满足女 ...

  2. JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库

    JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库 JAVA毕业设计vue开发一个简单音乐播放器计算机源码+lw文档+系统+调试部署+数据库 本源码技术栈: 项目 ...

  3. java检查手机号是否被注册_【java】如何开发一个检测手机号注册过哪些网站的应用?...

    问题描述 使用python或其它语言开发一个检测手机号注册过哪些网站的应用 问题出现的环境背景及自己尝试过哪些方法 在登陆一个很久没使用的网站时,原注册的手机号已弃用无法找回密码.所以希望有这么一款应 ...

  4. Java程序:开发一个应用,模拟计算机对移动存储设备的读写,即移动存储设备有U盘、手机卡、移动硬盘、闪卡等设备

    开发一个应用,模拟计算机对移动存储设备的读写,即移动存储设备有U盘.手机卡.移动硬盘.闪卡等设备 public interface Mobile {void Read();void Write();} ...

  5. java安卓怎么开发一个新闻app,一个基于Android系统的新闻客户端(一)

    一个基于Android系统的新闻客户端(一) 一.整体概述 在服务器端,通过对凤凰网的抓取存入数据库,客户端通过向服务器发送请求得到新闻. 服务端用WCF,宿主为window服务,客户端为Java写的 ...

  6. 使用Win32汇编开发一个dll并在C#中调用

    使用RadASM,新建一个Dll Project: 下一步,默认: dll包含Def文件: 完成工程构建:都默认: 完成以后项目结构如下: asm代码: .386 .model flat, stdca ...

  7. 用java开发一个Hello Word系统内核

    文章目录 1 最简单的Hello World系统内核实现 2 使用VirtualBox创建虚拟机并加载上述生成的软盘文件 2.1 创建虚拟机 2.2 加载软盘中的内核 1 最简单的Hello Worl ...

  8. 利用MyEclipse开发一个调用webservice接口的程序

    上一篇文章我们已经学习了如何使用Java 工具MyEclipse开发一个webservice接口,那么接口开发好了如何调用?接下来我们就来解决这个问题. 1:首先随便创建一个Java project选 ...

  9. 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?

    2019独角兽企业重金招聘Python工程师标准>>> 今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制 ...

最新文章

  1. cxf 发布 一个简单的 webservice
  2. 掌握神经网络模型的快捷方式
  3. 工作32:get之前打印
  4. rsync 服务快速部署手册
  5. JS判断是否是科学计算结果并处理
  6. 【leetcode】16 3Sum Closest
  7. pytrhon画图matplolib
  8. 走自己的路,记得回头看看
  9. QQ、空间、新浪微博、微信分享
  10. JDK安装包和Mysql安装包整理
  11. JAVA日志框架与日志系统
  12. Gos —— 搭建基础环境
  13. 我酸了,曝光几个腾讯 阿里P8前同事的副业收入
  14. matlab绘制那奎斯特曲线和bode图
  15. Python统计文件夹大小
  16. Java+MySQL基于SSM的在线论坛交流系统
  17. 分布式系统理论:Quorum算法
  18. 【C++】指针深度解析
  19. mybatis的原理详解
  20. [转]英文中的偏旁部首及其记忆

热门文章

  1. 【STM32】FreeRTOS 其他任务 API 函数
  2. 【Matlab 图像】HSV 空间图片分离器
  3. 使用windows自带远程桌面远程办公
  4. memset函数及其用法,C语言memset函数详解
  5. 【转】贴片电阻的工作寿命
  6. 阵元间隔为半波长的均匀分布16元线阵
  7. 基于FPGA的DES加解密系统开发(5000字详细介绍欢迎订阅)
  8. 计算机网络·详解TCP流量控制,拥塞控制,运输连接管理
  9. Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学
  10. 使用Arduino模块实施无线信号的重放攻击