《x86汇编语言:从实模式到保护模式》(第5章---编写主引导扇区代码)

在前面的预备知识里,我们已经知道,处理器加电或者复位之后,如果硬盘是首选的启动设备,那么,ROM-BIOS 将试图读取硬盘的 0 面 0 道 1 扇区。传统上,这就是主引导扇区(Main Boot Sector,MBR)。

读取的主引导扇区数据有 512 字节,ROM-BIOS 程序将它加载到逻辑地址 0x0000:0x7c00处,也就是物理地址 0x07c00 处,然后判断它是否有效。一个有效的主引导扇区,其最后两字节应当是 0x55 和 0xAA。ROM-BIOS 程序首先检测这两个标志,如果主引导扇区有效,则以一个段间转移指令 jmp 0x0000:0x7c00 跳到那里继续执行。

一般来说,主引导扇区是由操作系统负责的。正常情况下,一段精心编写的主引导扇区代码将检测用来启动计算机的操作系统,并计算出它所在的硬盘位置。然后,它把操作系统的自举代码加载到内存,也用 jmp 指令跳转到那里继续执行,直到操作系统完全启动。在本章中,我们将试图写一段程序,把它编译之后写入硬盘的主引导扇区,然后让处理器执行(这段代码的作用是完成某个数的各个数位的拆分,并显示在屏幕上)。

显存

如图 5-3 所示,我们知道,8086 可以访问 1MB 内存。其中,0x00000~9FFFF 属于常规内存,由内存条提供;0xF0000~0xFFFFF 由主板上的一个芯片提供,即 ROM-BIOS。中间还有一个 320KB 的空洞,即 0xA0000~0xEFFFF。传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡(0xB8000~0xBFFFF)。如果显卡出了毛病,计算机一定不会通过加电自检过程,这就是传说中的严重错误,计算机是无法启动的,更不要说加载并执行主引导扇区的内容了。
在这里插入图片描述
在这里插入图片描述
传统上,这种专门用于显示字符的工作方式称为文本模式(80×25,屏幕上可以显示 25 行,每行 80 个字符 )。为了给出要显示的字符,处理器需要访问显存,把字符的 ASCII 码写进去。屏幕上的每个字符对应着显存中的两个连续字节,前一个是字符的 ASCII 代码,后面是字符的显示属性,包括字符颜色(前景色)和底色(背景色)(现在最流行的,是用 24 个比特,即 3 个字节,来对应一个像素。因为 2 24 =16777216,所以在这种模式下,同屏可以显示 16777216 种颜色,这称为真彩色。)。

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

编程示例(将载入主引导扇区)

本代码的作用是完成某个数的各个数位的拆分,并显示在屏幕上。

div
  1. 第一种类型是用 16 位的二进制数除以 8 位的二进制数。在这种情况下,被除数必须在寄存器AX 中,必须事先传送到 AX 寄存器里。除数可以由 8 位的通用寄存器或者内存单元提供。指令执行后,商在寄存器 AL 中,余数在寄存器 AH 中。
  2. 第二种类型是用32位的二进制数除以16位的二进制数。在这种情况下,因为 16 位的处理器无法直接提供 32 位的被除数,故要求被除数的高 16 位在DX 中,低 16 位在 AX 中。同时,除数可以由 16 位的通用寄存器或者内存单元提供,指令执行后,商在 AX 中,余数在DX 中。

在编译阶段,每条指令都被计算并赋予了一个汇编地址,就像它们已经被加载到内存中的某个段里一样。实际上,当编译好的程序加载到物理内存后,它在段内的偏移地址和它在编译阶段的汇编地址是相等的。

jmp
jmp 0x5000:0xf0c0	;同时修改CS和IP
jmp near infi	;(IP) = (IP) + 16位位移
;16位位移=标号处地址-jmp指令的下一条指令的地址(当前的CS:IP)
代码实现
		;文件名:c05_01_mbr.asm
		;文件说明:硬盘主引导扇区代码
		;参考书:《x86汇编语言:从实模式到保护模式》李忠 著
		;代码功能:拆分代码中的标号number对应偏移地址的十进制各个数位,
		;		   在屏幕上显示Label offset:number对应偏移地址的十进制数。
		
		mov ax,0xb800	;指向文本模式的显示缓冲区
		mov es,ax
		
		;往显存中写入"Label offset:"字符串
		mov byte [es:0x0000],'L'
		mov byte [es:0x0001],0x07	;黑底白字,下同
		mov byte [es:0x0002],'a'	
		mov byte [es:0x0003],0x07
		mov byte [es:0x0004],'b'
		mov byte [es:0x0005],0x07
		mov byte [es:0x0006],'e'
		mov byte [es:0x0007],0x07
		mov byte [es:0x0008],'l'
		mov byte [es:0x0009],0x07
		mov byte [es:0x000a],' '
		mov byte [es:0x000b],0x07
		mov byte [es:0x000c],'o'
		mov byte [es:0x000d],0x07
		mov byte [es:0x000e],'f'
		mov byte [es:0x000f],0x07
		mov byte [es:0x0010],'f'
		mov byte [es:0x0011],0x07
		mov byte [es:0x0012],'s'
		mov byte [es:0x0013],0x07
		mov byte [es:0x0014],'e'
		mov byte [es:0x0015],0x07
		mov byte [es:0x0016],'t'
		mov byte [es:0x0017],0x07
		mov byte [es:0x0018],':'
		mov byte [es:0x0019],0x07
		
		;拆分number对应偏移地址的十进制各个数位
		mov ax,number	;准备被除数
		mov bx,10		;准备除数
		
		mov cx,cs		;设置数据段基地址
		mov ds,cx
		
		;求得个位(用32位/16位的div,下同)
		xor dx,dx		;高位在dx,清零,比mov dx,0的机器码短,且两个寄存器操作速度快
		div bx
		mov [0x7c00+number+0x00],dl		;除以10余数小于2^4,取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
		
		;把各个数位的数转成ASCII字符,送入显存
		mov al,[0x7c00+number+0x04]
		add al,0x30		;'0'对应的ASCII是48,即0x30,数位加上0x30即可转化为该数字字符对应的ASCII
		mov [es:0x001a],al
		mov byte [es:0x001b],0x04	;黑底红字,下同
		
		mov al,[0x7c00+number+0x03]
		add al,0x30
		mov [es:0x001c],al
		mov byte [es:0x001d],0x04
		
		mov al,[0x7c00+number+0x02]
		add al,0x30
		mov [es:0x001e],al
		mov byte [es:0x001f],0x04
		
		mov al,[0x7c00+number+0x01]
		add al,0x30
		mov [es:0x0020],al
		mov byte [es:0x0021],0x04
		
		mov al,[0x7c00+number+0x00]
		add al,0x30
		mov [es:0x0022],al
		mov byte [es:0x0023],0x04
		
		mov byte [es:0x0024],'D'		;添加一个D十进制数标志
		mov byte [es:0x0025],0x07
		
infi:
		jmp near infi	;使得程序在此死循环,避免程序往下走到非代码区
		
number:
		db 0,0,0,0,0	;开5个字节,存放number对应偏移地址的5个数位
		
		times 204 db 0	;填充使得正好凑够512个字节
		db 0x55,0xaa	;主引导扇区有效结束标志(低地址到高地址)
编译后的十六进制机器码

在这里插入图片描述
由此可知,number标号对应的十六进制偏移地址是0x012d,对应十进制301。如果没问题的话,之后虚拟机启动之后显示的十进制数将是00301D。
在这里插入图片描述

把c05_01_mbr.bin写入主引导扇区

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

启动虚拟机Virtual Box观察运行结果

在这里插入图片描述

Bochs程序调试入门

本书中的程序全都只能运行在没有操作系统的祼机下。这意味着,所有流行的调
试工具都不可用。不过,好消息是,一款叫做 Bochs 的软件可以帮助你。

下载安装与配置

下载地址(下载最新版本)
在这里插入图片描述
安装之后如下:
在这里插入图片描述
在 Bochs 的工作文件夹,有两个程序,分别是 bochs.exe 和 bochsdbg.exe。我们说过,Bochs 是虚拟机软件,可以作为类似于 VirtualBox 的虚拟机来使用。在这种情况下,你应当使用 bochs.exe。相反,如果你希望用 Bochs 来调试程序,那么,应当使用 bochsdbg.exe,它的意思是“Bochs 调试”(Bochs Debuger)。
在这里插入图片描述
在“Bochs Start Menu”窗口中,双击“Edit Options”列表框中的“Disk & Boot”,如下设置。柱面数、磁头数和扇区数可以用fixvhdwr.exe程序打开.vhd文件显示查到。
在这里插入图片描述
在这里插入图片描述
点击save,保存到 Bochs 的安装文件夹。
在这里插入图片描述

调试演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Bochs错误及解决方案

笔者第一次进入Bochs,按照教程设置完毕无误,可以正常调试,但是第二次就报错了。。反复重装还是报错。。。
在这里插入图片描述
解决方法:

  1. 在Virtual Box虚拟机目录下自己创建的虚拟机LEARN-ASM下查看,如果有文件LEARN-ASM.vhd.lock,删除掉这个文件。
    在这里插入图片描述
  2. 以管理员身份运行。。。

特别说明

本文参考《x86汇编语言:从实模式到保护模式》李忠 著

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值