汇编练习:关于VirtualBox中出现“no bootable medium found”的解决办法

问题

最近在看《x86汇编语言 从实模式到保护模式》,书中使用了Virtualbox进行裸机的虚拟以便执行汇编程序。在检测点4的练习中,写的汇编程序

mov ax,0xb800
mov ds,ax
mov byte [0x00],'a'
mov byte [0x02],'s'
mov byte [0x04],'m'
jmp $

在virtualbox上运行时弹出:no bootable medium found 的错误。具体步骤是:

  1. 将汇编代码保存为test.asm
  2. 使用NASM的命令nasm -f bin test.asm -o test.bin编译为汇编程序
  3. 使用VirtualBox建立一个虚拟机,系统选择类型:Other,版本:Other/Unknown;创建新的虚拟硬盘,VHD类型,固定大小
  4. 使用作者提供的小工具fixvhdwr.exe将test.bin写入到刚刚创建的虚拟硬盘中
  5. 运行虚拟机,报错:no bootable medium found

我的操作系统是Windows 7 64位旗舰版,VirtualBox版本5.2.8

搞了好久都没搞好,以为是自己的virtualbox版本问题,或者自己创建的虚拟硬盘有问题。于是我换了作者提供的VHD盘,发现是可以正确引导的,所应该是我的虚拟硬盘有问题

解决

当我看到第5章的“5.2 欢迎来到主引导扇区”一节时,就有讲到:

……主引导扇区数据有512字节……一个有效的主引导扇区,其最后两字节应当是0x550xAA

于是赶忙使用十六进制字节查看器对比了自己的虚拟硬盘和作者提供的虚拟硬盘,果然,作者的虚拟硬盘第510、511字节的值为0x55和0xAA,而自己的不是!!

晕,看来作者自己写的小工具也是有bug的。所以现在的解决办法就是,将虚拟硬盘的第510和511处字节值改为0x55和0xAA即可。

为此,我写了一个python脚本crtvhd.py来完成

import sys
import struct

with open(sys.argv[1], mode='br+') as vhdwriter:
    vhdwriter.seek(510,0)
    vhdwriter.write(struct.pack('B', 0x55))
    vhdwriter.write(struct.pack('B', 0xAA))

使用时,假设我的虚拟硬盘叫做NASM_VM.VHD,则我使用如下命令:

> py -3 crtvhd.py NASM_VM.VHD

现在再运行虚拟机,就得到了正确输出:


正确输出

注释

  1. 书上给的汇编代码是mov [0x00],'a',但是在NASM编译时会出现错误,大致是说没有指定数据大小,因此加一个字节大小说明byte,改为mov byte [0x00],'a'
  2. jmp $为空转指令,$表示当前地址。
  3. python代码中,在写二进制文件时不能直接write一个str或者int数据,应该借助struct模块的pack方法进行转换,方可写入
  4. 由于需求是使用二进制进行写,并且是要在文件中间部分进行覆写数据(覆盖原来的第510、 511字节处的数据),所以文件模式:
    • 不能用bw否则就会把整个文件覆盖掉
    • 也不能用ba或者ba+,追加模式下seek函数没有用,因为此时它会在下一次写的时候把指针又重新定位到了文件尾
    • 在这里我是用了br+,即二进制读模式,+表示可读可写。