在Ubuntu下,从零开始写操作系统(1)-笔记

上一篇讲到如何在屏幕上显示一个Hello,world!

本篇要从软盘中读取文件——Loader.bin

由于起始扇区只有512字节,要在FAT12中读取文件Loader.bin,代码比较紧凑。下面是fat12的文件系统BPB,其中的值基本上都是固定的。

jmp LABEL_START /* 跳转指令 */
	nop /* 这个nop指令是可选的,如果你用的是e9指令(长跳转),这个是不需要的
		但是如果你用的eb指令,说明你只是指明的跳转的步长,nop是必需的 */
BS_OEMName: 		.ascii "MSWIN4.1" /* OEM生成厂商的名字,微软建议使用MSWIN4.1保持兼容行 */
BPB_BytsPerSec:  	.2byte 512	  /*对面现代磁盘来说,这个数可能是4096,但是软盘这个是固定的*/
BPB_SecPerCluse: 	.byte  1	  /*每簇的扇区数,可以取2的n次方*/
BPB_ResvdSecCnt:	.2byte 1	  /*保留扇区数,必须为1*/
BPB_NumFATs:		.byte  2	  /*FAT的数目,一般是2*/
BPB_RootEntCnt:		.2byte 224	  /*根目录可容纳的条目,FAT32此项为0*/
BPB_TotSec16:		.2byte 2880	  /*16bit扇区总数*/
BPB_Media:		.byte  0xf0	  /*媒体介质类型,f0表示可移动磁盘*/
BPB_FATSz16:		.2byte 9	  /*FAT表的大小,9个扇区*/
BPB_SecPerTrk:		.2byte 18	  /*每磁道的扇区数 18 */
BPB_NumHeads:		.2byte 2	  /*磁头数,对于1.44M磁盘来说,这个数固定为2*/
BPB_HiddSec:		.4byte 0	  /*FAT分区之前的隐藏扇区数,没有分区的磁盘来说此项为0*/
BPB_TotSec32:		.4byte 0	  /*总扇区数,和tolsec16含义相同,16位无法表示可用此项*/
BS_DrvNum:		.byte  0	  /*用于0x13中断,0为软盘,0x80为硬盘*/
BS_Reserved1:		.byte  0	  /*保留NT使用*/
BS_BootSig:		.byte  0x29	  /*扩展引导标记,表明此后的3个域可用*/
BS_VolID:		.4byte 0	  /*卷标序列号*/
BS_VolLab:		.ascii "Solrex 0.01" /*卷标*/
BS_FileSysType:		.ascii "FAT12  "	/*文件类型,只是文本字符串,不可用来检测文件系统类型*/
/* Initial registers.初始化寄存器 */
LABEL_START:
	mov %cs,%ax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%ss
	mov $BaseOfStack, %sp
	/*清屏*/
	/*mov $0x0600,%ax /*ah =6 ,al =0*/
	/*mov $0x0700,%bx /* 白屏*/
	/*mov $0,%cx	/*左上角 0,0*/
	/*mov $0x184,%dx	/*右下角 80,50*/
	/*int $0x10	/*10h号中断,ah=6初始化屏幕*/
	/*原有清屏函数有bug新清屏函数*/
	mov $3,%ax
	int $0x10	

	/*显示引导信息*/
	mov $0,%dh
	call Dispstr
	
	/*重置软盘*/	
	xor %ah,%ah
	xor %dl,%dl
	int $0x13

	/*在根目录查找内核文件*/
	movw $SecNoOfRootDir,(wSectorNo) /*第19扇区,固定值*/
	
	/*读取根目录到内存*/
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
	cmpw $0,(wRootDirSizeForLoop) 	/*如果搜寻完整个根目录找不到内核*/
	jz LABEL_NO_LOADERBIN 		/*显示找不到信息*/
	decw (wRootDirSizeForLoop) 	/*变量-1*/
	mov $BaseOfLoader,%ax		/*要载入的基址es*/
	mov %ax,%es
	mov $OffsetOfLoader,%bx		/*偏移地址bx*/
	mov (wSectorNo),%ax		/*起始扇区为第19扇区*/
	mov $1,%cl			/*读取一个扇区*/
	call ReadSector			/*调用读取扇区子函数*/
	mov $LoaderFileName,%si		/*取文件名的基地址放入ds:si*/
	mov $OffsetOfLoader,%di		/*读取后的偏移地址->di,*/
	cld				/*请方向位,传送方向正向*/
	mov $0x10,%dx			/*先查找1个扇区,16*32 = 512byte*/

流程如下,先清屏,之后在根目录中查找LOARER.BIN。 找到后加载到ds:si中。

最后跳转到,jmp $BaseOfLoader,$OffsetOfLoader执行。

Loader.S中仅显示一个“L”

.code16
.text
	mov $0xb800,%ax
	movw %ax,%gs
	mov $0xf,%ah
	mov $'L',%al
	mov %ax,%gs:(0)
	jmp	.

Makefile文件如下:

CC=gcc
LD=ld
LDFILE=foot.ld
LDFILE_LOAD=loader.ld
OBJCOPY=objcopy

all: boot.img LOADER.BIN

#Step 1:gcc 调用as将boot.S编译成目标文件boot.o
boot.o: boot.S
	$(CC) -c boot.S
#Step 2:ld 调用脚本foot.ld将boot.o链接成可执行文件boot.elf
boot.elf: boot.o
	$(LD) boot.o -o boot.elf -T$(LDFILE)
#Step3: objcopy 移除boot.elf 中无用的section(.pdr,.comment,.note),
#	strip 掉所有符号信息,输出为二进制文件 boot.bin
boot.bin: boot.elf
	@$(OBJCOPY) -R .pdr  -R .comment -R .note -S -O binary boot.elf boot.bin
LOADER.BIN: loader.S
	$(CC) -c loader.S
	$(LD) loader.o -o loader.elf -T$(LDFILE_LOAD)
	$(OBJCOPY) -R .pdr  -R .comment -R .note -S -O binary loader.elf $@
#Step 4:生成可启动软盘镜像
boot.img: boot.bin
	@dd if=boot.bin of=boot.img bs=512 count=1	#用boot.bin 生成镜像文件第一个扇区
	#在bin生成镜像文件后补空白,最后成为合适大小的软盘镜像
	@dd if=/dev/zero of=boot.img skip=1 seek=1 bs=512 count=2879
copy: boot.img LOADER.BIN
	mkdir -p /tmp/floppy1;\
	mount -o loop boot.img /tmp/floppy1/ -o fat=12;\
	cp LOADER.BIN /tmp/floppy1/;
	umount /tmp/floppy1/;
	rm -rf /tmp/floppy1/;

clean:
	@rm -rf *.o *.elf *.bin *.img

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值