操作系统真相还原

操作系统真相还原

1、部署工作环境

1.2 Bochs下载安装

下载

下载地址:https://sourceforge.net/projects/bochs/files/bochs/2.7/

解压:
crescentp@crescentp:~/bochs$ tar zxvf bochs-2.7.tar.gz 
编译
./configure --prefix=/os/bochs --enable-debugger --enable-disasm --enable-iodebug --enable-x86-debugger --with-x --with-x11
make
make install
配置bochs

可以在安装目录下查看配置文件的样本文件

cat share/doc/bochs/bochsrc-sample.txt

image-20211014103441538

在 bin目录下编写bochsrc.disk代码

#############################################
# Configuration file for Bochs
# By CP
#############################################
# 第一步,首先设置Bochs在运行中过程中能够使用的内存,本列为32MB
# 关键字为:megs
megs: 32

# 第二步:设置对应真实机器的BIOS和VGA BIOS
# 对应的两个关键字为: romimage 和 vgaromimage
romimage: file=/os/bochs/share/bochs/BIOS-bochs-latest
vgaromimage: file=/os/bochs/share/bochs/VGABIOS-lgpl-latest

# 第三步,设置Bochs所使用的的磁盘,软盘的关键字为floppy
# 若只有一个软盘,则使用的floppya即可,若有多个,则为floppya,floppyb
# floppya: 1_44=a.img, status=inserted

# 第四步,选择启动盘符
#boot: floppy #默认从软盘启动
boot: disk   #改为从硬盘启动,我们的任何代码都将直接写在硬盘上,所以不会再有读写软盘的操作了

# 第五步,设置日志文件的输出
log: bochs.out

# 第六步,开启或关闭某些功能
# 下面是关闭鼠标,并且打开键盘
mouse: enabled=0
# keyboard_mapping: enabled=1,
keyboard:keymap=/os/bochs/share/bochs/keymaps/x11-pc-us.map

# 硬盘设置
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
# ata0-master: type=disk,path="hd60M.img",mode=flat

# 下面的是增加的bochs对gdb的支持,这样gdb便可以远程连接到此机器的1234端口调试了
gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0
运行
bochs

image-20211014113017397

image-20211014113030925

image-20211014113114789
配置启动盘

没有启动盘,那我们就配置启动盘呗

/bin/bximage 是创建启动盘的工具

image-20211014113445746

bin/bximage -hd=60M  -q hd60M.img

image-20211014114553006

image-20211014114800713

image-20211014120007435

2、编写MBR

mbr.S

;主引导程序
;---------------------------------------------------------------------
SECTION MBR vstart=0x7c00	; 表示在本程序编译时,告诉编译器,把我的其实地址编译0x7c00
	mov ax,cs		; 这一块是用cs寄存器的值,去初始化其它的寄存器
	mov ds,ax		; 由于BIOS是通过 jmp 0:0x7c00 跳转到MBR的,故此时cs为0
	mov es,ax
	mov ss,ax
	mov fs,ax
	mov sp,0x7c00		;初始化栈指针,0x7c00以下是安全的区域,可以用来当栈使用

;清屏利用0x6号功能,上卷全部行,即可清屏
;---------------------------------------------------------------------
;INT 0x10 功能号:0x06 功能描述:上卷屏幕
;---------------------------------------------------------------------
;输入;
;AH 功能号 = 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行的属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值
	mov ax,0x600
	mov bx,0x700
	mov cx,0	;左上角:(0,0)
	mov dx,0x184f	;右下角:(80,25)
			;VGA文本模式中,一行只能容纳80个字符,共25行
			;下标从0开始,所以0x18=24,0x4f=79
	int 0x10	;int 0x10

;;;;;;;;	下面这三行代码获取光标位置	;;;;;;;;;;;;;
; .get_cursor 获取当前光标位置,在光标位置处打印字符
	mov ah,3	;输入:3号子功能是获取光标位置,需要存入ah寄存器
	mov bh,0	;bh寄存器存储的是待获取光标的页号
	
	int 0x10	;输出,ch=光标开始行,cl=光标结束行
			;dh=光标所在行号,dl=光标所在列号

;;;;;;;;	获取光标结束位置	;;;;;;;;;;;;

;;;;;;;		打印字符串		;;;;;;;;;;;;
	;还是用10h中断,不过这次调用13号子功能打印字符串
	mov ax,message
	mov bp,ax	;es:bp为串首地址,es此时和cs一致
			;开头已经为sreg初始化

	;光标位置要用到dx寄存器中的内容,cx中光标位置可忽略
	mov cx,5	;cx为串长度,不包括结束符0的字符个数
	mov ax,0x1301	;子功能号13显示字符及属性,要出入ah寄存器
			;al设置写字符方式 ah = 01;显示字符串,光标跟随移动
	mov bx,0x2	;bh存储的是要显示的页号,此处是第0页
			;bl是字符属性,属性为黑底绿字(bl = 02h)
	int 0x10	;执行BIOS 0x10中断
;;;;;;;;	打印字符串结束		;;;;;;;;;;;;;;

	jmp $				;是程序悬停在此处

	message db "1 MBR"
	times 510-($-$$) db 0	; $$ 是本section的地址,$是本行的地址,$-$$是本行到本section的偏移量,最后两个字节是确定的,这就把本扇区的剩余量补0
	db 0x55,0xaa

编译

nasm -o mbr.bin mbr.S 

image-20211014143307822

将mbr.bin转载进入磁盘的第一个扇区

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img  bs=512 count=1 conv=notrunc

运行

bin/bochs -f bin/bochsrc.disk

image-20211014144313543

3、完善MBR

我们不适用int10中断来显示MBR,而是通过操控显存的方式

;主引导程序
;
;LOADER_BASE_ADDR equ 0xA00
;LOADER_START_SECTOR equ 0x2
;---------------------------------------------------------------------
SECTION MBR vstart=0x7c00	; 表示在本程序编译时,告诉编译器,把我的其实地址编译0x7c00
	mov ax,cs		; 这一块是用cs寄存器的值,去初始化其它的寄存器
	mov ds,ax		; 由于BIOS是通过 jmp 0:0x7c00 跳转到MBR的,故此时cs为0
	mov es,ax
	mov ss,ax
	mov fs,ax
	mov sp,0x7c00		;初始化栈指针,0x7c00以下是安全的区域,可以用来当栈使用
	mov ax,0xb800		;显存文本模式中,其内存地址是0xb8000
	mov gs,ax	

;清屏
;利用0x6号功能,上卷全部行,即可清屏
;---------------------------------------------------------------------
;INT 0x10 功能号:0x06 功能描述:上卷屏幕
;---------------------------------------------------------------------
;输入;
;AH 功能号 = 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行的属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值
	mov ax,0x600
	mov bx,0x700
	mov cx,0	;左上角:(0,0)
	mov dx,0x184f	;右下角:(80,25)
			;VGA文本模式中,一行只能容纳80个字符,共25行
			;下标从0开始,所以0x18=24,0x4f=79
	int 0x10	;int 0x10

	;输出背景色绿色,前景色红色,并且跳动的字符串“1 MBR”
	mov byte [gs:0x00],'1'
	mov byte [gs:0x01],0xA4	;A表示绿色背景闪烁,4表示前景位红色

	mov byte [gs:0x02],' '
	mov byte [gs:0x03],0xA4

	mov byte [gs:0x04],'M'
	mov byte [gs:0x05],0xA4

	mov byte [gs:0x06],'B'
	mov byte [gs:0x07],0xA4

	mov byte [gs:0x08],'R'
	mov byte [gs:0x09],0xA4

	jmp $				;是程序悬停在此处

	message db "1 MBR"
	times 510-($-$$) db 0	; $$ 是本section的地址,$是本行的地址,$-$$是本行到本section的偏移量,最后两个字节是确定的,这就把本扇区的剩余量补0
	db 0x55,0xaa

编译

nasm -o mbr.bin mbr.S 

将mbr.bin装载进入磁盘的第一个扇区

dd if=/os/bochs/mbr.bin of=/os/bochs/hd60M.img  bs=512 count=1 conv=notrunc

运行

bin/bochs -f bin/bochsrc.disk

image-20211015093448087

image-20211015093457589

可见这是跳动的

接下来我们通过从硬盘中读取加载信息,将内核加载器读入到内存,

mbr.S

;主引导程序
;------------------------------------------------------------------------------
%include "boot.inc"		;让编译器在编译之前,把boot.inc文件包含进来
SECTION MBR vstart=0x7c00
	mov ax,cs
	mov ds,ax
	mov es,ax
	mov ss,ax
	mov fs,ax
	mov sp,0x7c00
	mov ax,0xb800
	mov gs,ax

;清屏
;利用0x06功能,上卷所有行,则可清屏
;-------------------------------------------------------------------------------
;INT 0x10 功能号:0x06 功能描述:上卷窗口
;-------------------------------------------------------------------------------
;输入;
;AH 功能号:0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值
	mov ax,0600h
	mov bx,0700h
	mov cx,0	;左上角:(0,0)
	mov dx,184fh	;右下角:(80,25)
;因为VGA文本模式中,一行只能容纳80个字符,共25行
	; 下标从0开始,所有0x18=24,0x4f=79
	int 10h		;int 10h

	;输出字符串MBR
	mov byte [gs:0x00],'1'
	mov byte [gs:0x01],0xA4

	mov byte [gs:0x02],' '
	mov byte [gs:0x03],0xA4

	mov byte [gs:0x04],'M'
	mov byte [gs:0x05],0xA4		;A表示绿色背景闪烁,4表示前景颜色为红色

	mov byte [gs:0x06],'B'
	mov byte [gs:0x07],0xA4

	mov byte [gs:0x08],'R'
	mov byte [gs:0x09],0xA4

	mov eax,LOADER_START_SECTOR	;起始扇区lba地址,0x2
	mov bx,LOADER_BASE_ADDR		;写入的地址,0x900
	mov cx,1			;待写入的扇区数
	call rd_disk_m_16		;以下读取程序的起始部分(一个扇区)

	jmp LOADER_BASE_ADDR

;-------------------------------------------------------------------------------------
;功能:读取硬盘n个扇区
rd_disk_m_16:
;-------------------------------------------------------------------------------------
					;eax=LBA扇区号
					;bx=将数据写入的内存地址
					;cx=读入的扇区数
	mov esi,eax			;备份eax,因为al在out命令中会使用,会影响到eax的低8位
	mov di,cx			;备份cx,cx在读
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值