《X86汇编语言从实模式到保护模式》第05章:编写主引导扇区代码

从第5章开始写起,第一部分主要是介绍写基础知识,看书即可,从第5章开始涉及代码编写。

这些文章的主要结构如下:

  1. 总结书中涉及的知识点。
  2. 调试和验证书中的代码部分。

1:知识点

1.1 主引导扇区

在电脑已启动就会去读0面0道1扇区,这个扇区就是主引导扇区(main boot sector)。

程序从0X7C00开始,一个扇区是512字节(0X200),所以主引导扇区是从0X7C00--0X7E00。主引导扇区的最后两个字节是0X55,0XAA。BIOS检查该标志,如果有效,则跳转到0X7C00继续执行。后续的操作系统的自举代码由MBR加载到内存之后,跳转到操作系统的入口地址继续执行。

 

1.2 8086的地址空间

8086总共20根地址线,访问2^20(1M地址),其中:

0x00000----0x9FFFF为常规内存

0XF0000--0xFFFFF(64K)为BIOS所用

0XA000-0XEFFFF(320K)由外围设备提供。

地址0XB8000---0XBFFFF就是留给显示用的,就是我们操作该地址就可以操作显卡,把显卡这段地址表示成段地址:偏移地址的形式,则表示为段地址0XB800,偏移地址是从0x0000----0xFFFF。

用段寄存器ES来定义段的开始,intel规定不允许将一个立即数送到段寄存器,比如:

mov es,0xb800

只允许通用寄存器和内存单元送到段寄存器

mov 段寄存器,通用寄存器
mov 段寄存器,内存单元

 

1.3 显存的访问

要把一个字符显示在屏幕上,不仅仅是显示字符的内容,还要显示字符的格式(背景色,前景色),字符的内容是ASCII(American standard code for information美国信息交换标准代码)规定的。

用7位(b0~b6),表示2^7(128)个信息,

将信息送到内存的方式为:先送一个ASCII字符,然后给出这个字符要显示的格式(前景色和背景色)

前景色和背景色属于颜色,用RGB红黄蓝来表示,RGB各占1位,所以最多只能表示2^8共8钟颜色。

1.4 如何把一个数字分成单独的位

如果有一个十进制的数字1234,(一千二百三十四)。

  • 用该数字除以10,除数为123,商为4
  • 继续将除数123除以10,除数为12,商为3
  • 继续将除数12除以10,除数为1,商为2
  • 继续将除数1除以10,除数为0,商为1。

这其中的规律就是,十进制的数,不断的除以进制(10),得到的商即为分离出来的数。

 

2:调试和验证

基本的知识点就是上面的,剩下的只是点就是汇编语言自身的了,在代码中注释吧,汇编代码的注释以分号(;)开头。

废话不多说,直接上实验结果看看,在再调试,如果要调试,得首先知道偏移和运行的方法吧。

我用QEMU环境

代码如下:

;代码清单5-1 
;文件名:c05_mbr.asm
;文件说明:硬盘主引导扇区代码
;创建日期:2011-3-31 21:15 

;以上两句,相当于设置段的起始地址为0xb8000,存放在寄存器es中,因为处理器在处理段地址时,会将段地址左移4位。intel不允许直接将立即数放到

	mov ax,0xb800                 ;指向文本模式的显示缓冲区
	mov es,ax

;在段内偏移从0X00--0x19放置字符串,放置显存是,先放置ASCII字符,然后放置显示格式,显示格式又分为前景色和背景色,用1个字节表示
;以下显示字符串"Label offset:"
	mov byte [es:0x00],'L'
	mov byte [es:0x01],0x07       ;显示字符的背景色和前景色
	mov byte [es:0x02],'a'
	mov byte [es:0x03],0x07
	mov byte [es:0x04],'b'
	mov byte [es:0x05],0x07
	mov byte [es:0x06],'e'
	mov byte [es:0x07],0x07
	mov byte [es:0x08],'l'
	mov byte [es:0x09],0x07
	mov byte [es:0x0a],' '
	mov byte [es:0x0b],0x07
	mov byte [es:0x0c],"o"
	mov byte [es:0x0d],0x07
	mov byte [es:0x0e],'f'
	mov byte [es:0x0f],0x07
	mov byte [es:0x10],'f'
	mov byte [es:0x11],0x07
	mov byte [es:0x12],'s'
	mov byte [es:0x13],0x07
	mov byte [es:0x14],'e'
	mov byte [es:0x15],0x07
	mov byte [es:0x16],'t'
	mov byte [es:0x17],0x07
	mov byte [es:0x18],':'
	mov byte [es:0x19],0x07

	;mov ax,number                 ;取得标号number的偏移地址
	mov ax,0x99                 ;取得标号number的偏移地址
	mov bx,10

	;设置数据段的基地址
	mov cx,cs
	mov ds,cx

	;求个位上的数字
	mov dx,0
	div bx
	mov [0x7c00+number+0x00],dl   ;保存个位上的数字

	;求十位上的数字
	xor dx,dx
	div bx
	mov [0x7c00+number+0x01],dl   ;保存十位上的数字

	;求百位上的数字
	xor dx,dx
	div bx
	mov [0x7c00+number+0x02],dl   ;保存百位上的数字

	;求千位上的数字
	xor dx,dx
	div bx
	mov [0x7c00+number+0x03],dl   ;保存千位上的数字

	;求万位上的数字 
	xor dx,dx
	div bx
	mov [0x7c00+number+0x04],dl   ;保存万位上的数字

	;以下用十进制显示标号的偏移地址
	mov al,[0x7c00+number+0x04]
	add al,0x30      ;0x30是'0'的ascii字符,将该字符加上0的ascii字符
	mov [es:0x1a],al ;将该字符送到es:0x1a的位置显示
	mov byte [es:0x1b],0x04;设置显示的属性

	mov al,[0x7c00+number+0x03]
	add al,0x30
	mov [es:0x1c],al
	mov byte [es:0x1d],0x04

	mov al,[0x7c00+number+0x02]
	add al,0x30
	mov [es:0x1e],al
	mov byte [es:0x1f],0x04

	mov al,[0x7c00+number+0x01]
	add al,0x30
	mov [es:0x20],al
	mov byte [es:0x21],0x04

	mov al,[0x7c00+number+0x00]
	add al,0x30
	mov [es:0x22],al
	mov byte [es:0x23],0x04

	mov byte [es:0x24],'D'
	mov byte [es:0x25],0x07

infi: jmp near infi                 ;无限循环

	number db 0,0,0,0,0

times 203 db 0
	db 0x55,0xaa

 

先编译运行:

nasm boot.asm -o boot.bin

用该bin文件制作启动扇区,为了方便将该文件写到不同的扇区。

dd if=boot.bin of=boot.img bs=512 count=1

运行启动扇区

qemu-system-i386 boot_image

为了以后将bin文件写到不同扇区,才使用dd命令制作一个磁盘,如果只是一个扇区,则不用制作磁盘,也可启动

qemu-system-i386 boot.bin

 

启动的结果如下,其中的153,即为程序中设置的mov ax,0x99 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值