【日拱一卒行而不辍20220916】自制操作系统

 Windows下利用QEMU实现HelloOS

参照《ORANGE’S:一个操作系统的实现》

汇编源码如下:boot.asm

	org	07c00h			; where the code will be running
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	call	DispStr			; let's display a string
	jmp	$			; and loop forever
DispStr:
	mov	ax, BootMessage
	mov	bp, ax			; ES:BP = string address
	mov	cx, 16			; CX = string length
	mov	ax, 01301h		; AH = 13,  AL = 01h
	mov	bx, 000ch		; RED/BLACK
	mov	dl, 0
	int	10h
	ret
BootMessage:		db	"Hello, OS world!"
times 	510-($-$$)	db	0	; fill zeros to make it exactly 512 bytes
dw 	0xaa55				; boot record signature

批处理命令行如下,生成boot.bin

nasm boot.asm -f bin -o boot.bin
pause

boot.bin文件二进制内容如下:

【日拱一卒行而不辍20220916】自制操作系统_第1张图片

在qemu下执行命令行如下: 

c:\qemu>qemu-system-i386.exe boot.bin

执行结果如下,显示了书中一致的Hello,OS world!

【日拱一卒行而不辍20220916】自制操作系统_第2张图片

实模式与保护模式下的段与偏移

参照《ORANGE’S:一个操作系统的实现》

在实模式下,16位的寄存器需要用“段:偏移”这种方法才能达到1MB的寻址能力,如今我们有了32位寄存器,一个寄存器就 可以寻址4GB的空间,是不是从此段值就被抛弃了呢?实际上并没有,新政策下的地址仍然用“段:偏移”这样的形式来表示,只不 过保护模式下“段”的概念发生了根本性的变化。实模式下,段值还是可以看做是地址的一部分的,段值为XXXXh表示以XXXX0h开 始的一段内存。而保护模式下,虽然段值仍然由原来16位的cs、ds等寄存器表示,但此时它仅仅变成了一个索引,这个索引指向一 个数据结构的一个表项,表项中详细定义了段的起始地址、界限、属性等内容。这个数据结构,就是GDT(实际上还可能是LDT,这 个以后再介绍)。GDT中的表项也有一个专门的名字,叫做描述符(Descriptor)。

内核是在实模式还是保护模式下开始执行的?

参照《ORANGE’S:一个操作系统的实现》

现在我们假设已经有了一个内核,Loader肯定要加载它入内存,而且内核开始执行的时候肯定已经在保护模式下了,所 以,Loader要做的事情至少有两件:

在实模式下把内核加载加载进入内存;

跳入保护模式。

然后在保护模式下运行内核。

Loader应该走多远?

参照《ORANGE’S:一个操作系统的实现》

完成从实模式到保护模式跳转这一任务的应该是Loader,那么Loader应该走多远呢?只完成跳转,还是应该把 GDT、IDT、8259A等内容准备完备?实际上,从逻辑上讲,Loader不是操作系统的一部分,所以不应该越俎代庖。而且,你一定也 希望早早结束Loader的工作进入正题,所以,我们还是要让Loader尽量简单,其余的工作留给内核来做。

asm与c之间的跳转

参照《ORANGE’S:一个操作系统的实现》

我猜你一定已经发现了其中的诀窍,不外乎就是关键字global和extern。是的,有了这两个关 键字,就可以方便地在汇编和C代码之间自由来去。

Ubuntu下利用QEMU实现HelloOS

touch boot.S
nano boot.S

输入如下内容

【日拱一卒行而不辍20220916】自制操作系统_第3张图片

 利用nasm进行编译

nasm -o boot boot.S

创建虚拟磁盘映像

bximage -mode=create -hd=60 -q os.raw

填充第一扇区

dd if=boot of=os.raw bs=512 count=1

采用qemu运行

qemu-system-i386 os.raw

如下所示

【日拱一卒行而不辍20220916】自制操作系统_第4张图片

你可能感兴趣的:(Linux,OS,java,数据库,开发语言)