上一博文实现了把其它扇区的数据加载进内存并显示出来,同理如果其它扇区的是执行代码,在内核加载器加载完其它扇区代码后并指定CS:IP指向加载进来的内存地址,其它扇区的代码将会被指向。
使用汇编实现其他扇区代码功能,内核加载器加载该扇区代码并跳转到指定内存执行写入虚拟磁盘其他扇区的代码。
1.修改内核加载器文件boot.s
;能用于操作内存的寄存器只能是bx、bp、si、di
;0x7c00--0x7dff 这512字节用于启动区
;对内存的访问都必须指定段寄存器,没有显示指定时将使用ds作为段寄存器
org 0x7c00
LOAD_ADDR EQU 0x8000 ;内核加载偏移地址
mov ax,0
mov ss,ax
mov ds,ax
mov es,ax
mov bx,LOAD_ADDR
mov ch,1 ;柱面号
mov dh,0 ;磁头号
mov cl,2 ;扇区号
mov ah,0x02 ;0x02表示读盘操作
mov al,1 ;表示连续读取扇区数
mov dl,0 ;驱动器号,早期有多个软驱,一般只有一个写死0
int 0x13 ;调用BIOS实现磁盘读取
jc error ;读盘操作失败,flag标志寄存器cf 标志位被置1
jmp bx ;跳转到加载的内存地址开始执行代码
fin:
hlt
jmp fin
putloop:
mov al,[si]
inc si
cmp al,0
je fin
mov ah,0x0e ;中断调用参数
mov bx,15 ;字符颜色
int 0x10 ;中断调用号
jmp putloop
error:
mov si,errMsg
jmp putloop
errMsg:
db 'error'
db 0
2.编写内核文件kernel.s
org 0x8000
mov ax,0
mov ss,ax
mov ds,ax
mov es,ax
mov si,msg
putloop:
mov al,[si]
inc si
cmp al,0
je fin
mov ah,0x0e ;中断调用参数
mov bx,15 ;字符颜色
int 0x10 ;中断调用号
jmp putloop
fin:
hlt
jmp fin
msg:
db 'hello world from kernel'
db 0
终端运行nasm 编译汇编文件
nasm boot.s -o boot.bat
nasm kernel.s -o kernel.bat
3.制作虚拟软盘main.c
#include
#include
#include
#include "floppy.h"
int main(int argc,char **argv){
FILE *fp = initFloppy("floppy.img");
if(fp == NULL) {
printf("初始化磁盘失败");
exit(0);
}
FILE *src = fopen("boot.bat", "r");
if(src == NULL) {
printf("文件打开失败");
exit(0);
}
char buf[512];
memset(buf, 0, 512);
fread(buf, 512, 1, src);
buf[510] = 0x55;
buf[511] = 0xaa;
writeFloppy(0, 0, 1, fp, buf);
fclose(src);
memset(buf, 0, 512);
src = fopen("kernel.bat", "r");
if(src == NULL) {
printf("文件打开失败");
exit(0);
}
fread(buf, 512, 1, src);
writeFloppy(1, 0, 2, fp, buf);
fclose(src);
fclose(fp);
return 1;
}
4.验证
编译运行main.c 文件生成虚拟软盘文件,虚拟机加载该软盘文件显示如下:
至此,写入其它扇区的代码被成功加载进内存并执行成功!