用java和汇编开发一个Hello World系统内核
生活随笔
收集整理的這篇文章主要介紹了
用java和汇编开发一个Hello World系统内核
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1 匯編實(shí)現(xiàn)
- 1.1 匯編實(shí)現(xiàn)
- 1.2 使用nasm編譯器進(jìn)行編譯
- 2 利用java生成軟盤(pán)文件
- 2.1 利用java生成軟盤(pán)文件的代碼如下
1 匯編實(shí)現(xiàn)
1.1 匯編實(shí)現(xiàn)
匯編代碼如下:
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上面的匯編代碼主要是設(shè)置了一些初始化數(shù)據(jù),然后調(diào)用bios中斷,將某個(gè)緩沖區(qū)中的字符打印到屏幕上,然后進(jìn)入一個(gè)死循環(huán)。代碼段的詳細(xì)解釋如下:
/* org 的意思是origin, 中文意思是“起始,起源,” org 后面的7c00 是物理內(nèi)存地址,假設(shè)物理內(nèi)存是一個(gè)byte類(lèi)型 的大數(shù)組,例如byte[] memory, 如果你有2 G內(nèi)容,換算成字節(jié)就是2097152, 也就相當(dāng)于memory數(shù)組有2097152字 節(jié),于是當(dāng)虛擬機(jī)上電,然后new一塊內(nèi)存 byte[] memory = new byte[2097152]. org 0x7c00 的意思是將本匯編 編譯后的二進(jìn)制數(shù)據(jù)從memory[0x7c00]處寫(xiě)入memory. */ org 0x7c00;/* jmp entry 中的jmp 其實(shí)就是c語(yǔ)言中的語(yǔ)句goto, jmp entry 其實(shí)是讓cpu跳轉(zhuǎn)到entry 處,執(zhí)行entry下面的代 碼,如果entry是一個(gè)函數(shù)名字的話(huà),jmp entry 相當(dāng)于調(diào)用entry函數(shù),類(lèi)比于java就是函數(shù)調(diào)用:entry(); */ jmp entry// 下面的代碼一直到RESB 18這行代碼是可以直接刪除的,我這里之所以放在這里是為了記錄一下匯編知識(shí)點(diǎn) /* jmp entry 對(duì)應(yīng)的機(jī)器代碼,長(zhǎng)度是3字節(jié),那么db 0x90 的意思就是 memory[0x7c00+3] = 0x90, 也就是說(shuō)db 0x90 實(shí)際上做的是賦值操作,db 0x90 表示將給定位置處的一個(gè)字節(jié)賦予數(shù)值0x90, 賦值的內(nèi)存位置就在0x7c00+3處。 */ db 0x90 /* DB 和 db 是同一個(gè)意思, 那么DB “OSKERNEL” 意思是,strcpy(memory + 0x7c00 + 3 + 1, “OSKERNEL”); 也就 是把”O(jiān)SKERNEL”這個(gè)字符串拷貝到內(nèi)存0x7c00 + 3 + 1 處, 3是什么意思呢,3就是jmp entry 編譯成二進(jìn)制代碼后 的數(shù)據(jù)長(zhǎng)度, 1 就是db 0x90 所所賦值的那個(gè)字節(jié)的長(zhǎng)度。DW 跟DB是一個(gè)意思, DB 是將數(shù)據(jù)賦值給一個(gè)字節(jié),由于 一個(gè)字節(jié)只有8位,那么賦值給這個(gè)字節(jié)的數(shù)據(jù)大小不能超過(guò)256, 512大于256,所以需要兩個(gè)字節(jié)才能存儲(chǔ)512這個(gè)數(shù) 據(jù),DD 0xFFFFFFFF 就是把0xFFFFFFFF存儲(chǔ)到四個(gè)字節(jié)長(zhǎng)的內(nèi)存中, 語(yǔ)句RESB 18 表示把接下來(lái)的18個(gè)字節(jié)的內(nèi)存全 部初始化為0,轉(zhuǎn)換為java代碼就類(lèi)似于: 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: /* 先做的是初始化一系列寄存器,寄存器其實(shí)相當(dāng)于java程序中,我們定義的變量,ax 是一個(gè)2字節(jié)長(zhǎng)的寄存器, mov ax, 0是把數(shù)值0放入到ax寄存器中,類(lèi)比于java 就是: char ax = 0; char類(lèi)型的數(shù)據(jù)在java中是兩個(gè)字節(jié)長(zhǎng),跟寄存器ax的長(zhǎng)度一樣,類(lèi)似的,語(yǔ)句: mov ss, ax 相當(dāng)于java的 char ss = ax; 后面的語(yǔ)句意思類(lèi)推。 */mov ax, 0mov ss, axmov ds, axmov es, ax /* 我們要注意看語(yǔ)句 mov si, msg. msg 相當(dāng)于一段內(nèi)存, msg: DB 0x0a, 0x0a db “hello, world” db 0x0a 就類(lèi)似于 C 語(yǔ)言中的char* msg = “\n\nhello,world\n”. 字符’\n’的ascii值就是0xa.mov si, msg 就相當(dāng)于把msg內(nèi)存的起始地址放入到寄存器si里。如果用C語(yǔ)言做類(lèi)比,那么就相當(dāng)于: char* si = msg; */mov si, msgputloop: /* mov al, [si] [si]表示讀取si存儲(chǔ)的內(nèi)存地址處的一個(gè)字節(jié)長(zhǎng)度的信息, mov al, [si] ,把該字節(jié)的數(shù)據(jù)存儲(chǔ)到寄存器al 中,ax是兩個(gè)字節(jié)長(zhǎng)度的寄存器,這樣ax就可以分解成兩部分,第一 部分就對(duì)應(yīng)于al, 第二部分就對(duì)應(yīng)于ah, 也就是al, ah合起來(lái)就是ax, 對(duì)應(yīng)于C語(yǔ)言就相當(dāng)于 char ax[2], al 表示的是ax[0], ah 表示的就是 ax[1], mov al, [si], 轉(zhuǎn)換成C語(yǔ)言就是 char al = *si; */mov al, [si] /* add si, 1 表示將寄存器si中的數(shù)值加1,也就相當(dāng)于C語(yǔ)言的 si++; */add si, 1 /* cmp al, 0 表示將al寄存器中的數(shù)據(jù)跟0比較,看al中的值是否等于0 */cmp al, 0 /* je fin 中的 je 表示 jump if equal, 也就是如果al 的值確實(shí)等于0,那么就跳轉(zhuǎn)到fin所表示的代碼處去執(zhí)行,轉(zhuǎn) 換成C語(yǔ)言就是 : if (al == 0) { goto fin } */je fin/* mov ah, 0xe 就是把0xe賦值給寄存器 ah, mov bx ,15 同理。接下來(lái)要調(diào)用一個(gè)中斷,中斷其實(shí)就是一個(gè)函數(shù)調(diào)用, 我們?cè)趯?xiě)c語(yǔ)言或java程序時(shí),往往需要調(diào)用一些系統(tǒng)庫(kù)函數(shù),例如printf, 或java的System.out.print. 中斷就是 bios提供給匯編語(yǔ)言的庫(kù)函數(shù),這些庫(kù)函數(shù)都放入到一個(gè)數(shù)組里,int 0x10 意思是在庫(kù)函數(shù)數(shù)組中取出第0x10個(gè)庫(kù)函 數(shù),然后執(zhí)行該庫(kù)函數(shù)的代碼。我們知道,函數(shù)調(diào)用時(shí)需要傳遞參數(shù),那么調(diào)用bios提供的函數(shù)時(shí),怎么傳遞參數(shù)呢,做法是,把需要傳遞的參數(shù)放入到 指定的寄存器中,例如想要在屏幕上輸出字符,那么bios提供的編號(hào)為0x10的庫(kù)函數(shù)可以實(shí)現(xiàn)這個(gè)功能,同時(shí)按規(guī)定, 要把寄存器ah設(shè)置為0x0e, 把要輸出的字符的ascii值放入到寄存器al, 同時(shí)要把寄存器設(shè)bh的值設(shè)置成0,字符的顏色 可以通過(guò)寄存器bl的值來(lái)設(shè)定。看起來(lái)相當(dāng)麻煩,這是由于我們做的是非常底層的編程,所以麻煩也就不可避免。 */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就相當(dāng)于C語(yǔ)言: do { char al = *si; si++; if (al == 0) { goto fin }printf(“%c”, al); } while(true); *//* hlt 表示 halt, 也就是讓cpu進(jìn)入休眠狀態(tài),如果此時(shí)我們點(diǎn)擊一下鍵盤(pán),或動(dòng)一下鼠標(biāo),那么cpu就被喚醒,然后執(zhí)行hlt后面的語(yǔ)句: jmp fin 也就是跳轉(zhuǎn)到fin開(kāi)始處去執(zhí)行,也就是進(jìn)入了死循環(huán)。 */ fin:HLTjmp finmsg:DB 0x0a, 0x0adb "hello, world"db 0x0adb 01.2 使用nasm編譯器進(jìn)行編譯
nasm boot.asm -o boot.bat 。
2 利用java生成軟盤(pán)文件
2.1 利用java生成軟盤(pán)文件的代碼如下
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;}// 當(dāng)前代碼之后至510字節(jié)全部寫(xiě)0int len = 510;int curlen = imgByteToWrite.size();for (int i=curlen; i<len; i++){imgByteToWrite.add(0);}// 第511、512字節(jié)為磁盤(pán)主引導(dǎo)扇區(qū)的有效標(biāo)志,必須為0x55、0xaaimgByteToWrite.add(0x55);imgByteToWrite.add(0xaa);//imgByteToWrite.add(0xf0);//imgByteToWrite.add(0xff);//imgByteToWrite.add(0xff);}public OperatingSystem(String fileName) {readKernelFormatFile(fileName);// 1.44MB大小的軟盤(pán)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();} }參考資料:
總結(jié)
以上是生活随笔為你收集整理的用java和汇编开发一个Hello World系统内核的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深州装修公司排名前十口碑推荐有哪些?
- 下一篇: 黑猩猩和人类的智商差距大吗?