【X86汇编语言 从实模式到保护模式】02 编写主引导扇区代码

1. 主引导扇区

处理器加电或复位之后,如果硬盘是首选的启动设备,那么 RMO-BIOS 将尝试读取硬盘 0 面 0 道 1 扇区。传统上,这就是主引导扇区(Main Boot Sector,MBR)。

主引导扇区数据又512字节,ROM-BIOS 将其加载到逻辑 0x0000:0x7c00 处,即物理地址 0x07c00 处。一个有效的主引导扇区,其最后两个字节是 0x55 和 0xaa。如果主引导扇区有效,ROM-BIOS 就会段间跳转 jmp 0x0000:0x7c00 到该处继续执行。

2. 在屏幕上显示文字

为了显示文字,需要将内容写到显存中(Video RAM,VRAM)。如下图所示,是字符在屏幕上显示的原理图:
字符在屏幕上显示的原理
文本模式和图型模式是显卡的两种基本工作模式。上述专门用于显示字符的工作方式称为文本模式。它需要将字符的 ASCII 码送到显存中。

处理器为了能够直接,有效的访问显存,将显存映射到了处理器可以直接访问的地址空间中。即内存中。如下图是显存到内存的映射:
文本模式下显存到内存的映射
8086 可以访问 1MB 的内存。其中 0x0000 - 0x9FFFF 属于常规内存,由内存条提供;0xF0000 - 0xFFFFF 由主板上的一个芯片提供,即 ROM-BIOS。中间 0xA0000 - 0xEFFFF 320KB 的地址由特定的外围设备提供,其中包括显卡 0xB8000 - 0xBFFFF。

所有在个人计算机上使用的显卡,在加电自检后都会把自己初始化到 80 * 25 的文本模式。每屏 25 行,每行 80 字符,共 2000 字符。

3. 分析代码

书本参考代码如下:

         ;代码清单5-1 
         ;文件名:c05_mbr.asm
         ;文件说明:硬盘主引导扇区代码
         ;创建日期:2011-3-31 21:15 
         
         mov ax,0xb800                 ;指向文本模式的显示缓冲区
         mov es,ax

         ;以下显示字符串"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 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
         mov [es:0x1a],al
         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

为了显示字符串,需要将字符的 ASCII 依次送入 显存中。

  1. 6-7 行代码:由于文本模式下显存的起始物理地址是 0xB8000,所有将 ES 指向 0xB800 作为段地值。所有 2000 字符的偏移地址为 0x0000 - 0x0FA0。
  2. 10-35行代码:显示字符串 “Label offset:”,在文本模式下,需要两个字节显示一个字符,低字节代表字符的 ASCII 码,高字节代表显示属性。字符代码和字符属性示意图如下:
    字符代码和字符属性示意图
    在8086下,80*25 文本模式的颜色表如下:
    80*25 文本模式的颜色表
    由表中可知, 属性0x07代表黑底白字,无闪烁,无加亮。当屏幕一片漆黑时,实际上显示的是,黑底白字的空格字符。
  3. 37行:取得标号 number 的汇编地址 302。程序中还需要显示 number 处的汇编地址显示出来。汇编地址是编译器编译期间会给每一条代码一个汇编地址,这个汇编地址实际上是从0开始。在分段机制中,偏移地址也是从0开始。实际上,这个汇编地址就是与偏移地址是对应的。如下图:
    汇编地址和偏移地址的关系
  4. 38行:将bx寄存器赋值为10 ,作为下面除以10 的时候的除数。
  5. 100行:定义了五字节的数据,用来暂存分解 number 汇编地址的各个数位。
  6. 41-42行:我们将DS寄存器指向代码段,这里代码段和数据段是同一个段。
  7. 70-93行:先将各个数位转化成十进制显示,然后送入到显存,在每一个字符后面写入显示属性0x04,代表黑底红字。
  8. 95-96行:显示字符 D ,黑底白字。
  9. 98行:无限循环,防止处理器再指向接下来的指令。
  10. 102行:由于主引导扇区是512字节的,我们写的程序并没有达到512字节。所以我们应该将主引导扇区未满的地方填满。
  11. 103行:一个有效的主引导扇区,最后两个字节是0x55和0xaa。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值