接管裸机的控制权
- 熟悉虚拟机的安装、配置、使用;
- 搭建和应用实验环境,了解各种工具的使用;
- 编写NASM汇编程序;
- 接管裸机的控制权。
虚拟机安装,生成一个基本配置的虚拟机XXXPC和多个1.44MB容量的虚拟软盘,将其中一个虚拟软盘用DOS格式化为DOS引导盘,用WinHex工具将其中一个虚拟软盘的首扇区填满你的个人信息。
设计IBM_PC的一个引导扇区程序,程序功能是:用字符‘A’从屏幕左边某行位置45度角下斜射出,保持一个可观察的适当速度直线运动,碰到屏幕的边后产生反射,改变方向运动,如此类推,不断运动;在此基础上,增加你的个性扩展,如同时控制两个运动的轨迹,或炫酷动态变色,个性画面,如此等等,自由不限。还要在屏幕某个区域特别的方式显示你的学号姓名等个人信息。将这个程序的机器码放进放进第三张虚拟软盘的首扇区,并用此软盘引导你的XXXPC,直到成功。
实验中用到的工具列表
- 操作系统:Windows 10
- 代码编辑器:Visual Studio Code 1.32.1
- 二进制文件编辑器:WinHex 14.2
- 磁盘工具:WinImage 9.00
- 虚拟机软件:VMware Workstation 15 Pro
- 终端:cmder v1.3.11
- Linux 环境:WSL Ubuntu, 4.4.0-17763-Microsoft
- 汇编编译器:NASM 2.11.08 (On Linux)
该任务比较基础,此处仅简述试验方案。详细流程参见“实验过程”栏目。
- 虚拟机的安装,使用 VMware Workstation 15 Pro 软件,并按照流程创建一个最低配置(1个单核处理器,4MB内存,无网络)的裸机环境。
- 使用
WinImage工具创建虚拟软盘文件。 - 使用
WinHex工具修改虚拟软盘的内容。 - 制作 MS-DOS 引导镜像,用 VMware 加载。
字符反射运动的汇编程序已经提供了(stoneM.asm),我只在其的基础上进行功能扩充和代码优化。下面简述我的试验方案:
-
规范化汇编程序
-
经查阅资料得知,系统启动并自检完成后,会将软盘的第一个扇区中的内容读入内存地址
0000:7C00中,接着检查扇区末尾的两个字节是否等于0x55和0xAA,如果是,则说明该扇区为有效的主引导记录。因此,在汇编程序中应规定被装入的内存地址为
0x7C00,且第511、512个字节必须是0x55和0xAA。注意,源程序中为
org 100h,是错误的,必须更正。 -
改写已提供的汇编程序,命名为
jed_stone.asm。开头部分加入如下指令,可以使程序装载到正确的位置:org 7C00h
-
在
jed_stone.asm结尾处添加如下代码:times 510-($-$$) db 0 ; 填充0,一直到第510字节 db 55h, 0AAh ; 扇区末尾两个字节为0x55和0xAA
这两行代码的作用是将程序的剩余部分用0填充,直到第510个字节。之后,填充第511和第512个字节为0x55和0xAA。这样子编译出的程序机器码将正好是512字节。
-
-
添加字符变色功能
-
在研究了字符反射的原理后得知,每次显示一个处于新位置的字符时,程序都会转到标签
show处去执行。因此要使字符变色,只需要在每次显示字符前改变其属性即可。字符属性是保存在一个字节中的(详见“实验总结”栏目),为了使得每次显示字符的属性不同,需要将字符属性保存在内存中的一个位置:
curcolor2 db 09h ; 保存当前字符颜色属性,用于移动的字符
-
在
show中添加内容,使字符属性每次递增以改变颜色。但为了只改变前景色而不改变背景色,需要让字符属性在0x01和0x0F之间变化:show: xor ax,ax ; 计算显存地址 mov ax,word[x] mov bx,80 mul bx add ax,word[y] mov bx,2 mul bx mov bp,ax mov ah,[curcolor2] ; 弹字符的背景色和前景色(默认值为07h,详见文档) inc byte[curcolor2] cmp byte[curcolor2], 0fh jnz skip mov byte[curcolor2], 1 ; 为了不改变背景色 skip: mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) mov word[gs:bp],ax ; 显示字符的ASCII码值
-
-
在屏幕顶端显示个人信息
-
将个人信息字符串以及字符串的长度保存在内存中:
myinfo db ' Zhang Yixin, 17341203 ' infolen dw $-myinfo ; myinfo字符串的长度
-
我们已经学会如何在屏幕指定位置显示1个字符,那么只需使用循环结构就可以显示多个字符(也就是显示字符串)。代码如下,同样加在
show后面:mov si, myinfo ; 显示姓名和学号 mov di, 2 mov cx, word[infolen] loop2: ; 显示myinfo中的每个字符 mov al, byte[ds:si] inc si mov ah, [curcolor] ; 背景色和前景色 add byte[curcolor], 12h ; 变色,该数字可随意调节以达到不错的效果 mov word [gs:di],ax add di,2 loop loop2
-
为个人信息的显示添加炫酷变色效果。与字符变色的原理类似,同样采取保存字符属性、每次显示前递增字符属性的方法。与之不同的是,这里允许背景色、前景色都可以改变。此处略去。
-
-
安装和配置编译环境。我使用
VS Code+cmder+WSL(Windows Subsystem for Linux)+NASM作为开发环境。这些工具的安装不在此处叙述。工具准备就绪后,在
jed_stone.asm目录下打开cmder并进入bash。使用NASM编译并生成机器码。生成的文件应该以.img为后缀,可以直接作为 VMware 的软盘镜像使用。nasm jed_stone.asm -o jed_stone.img
此时若没有错误提示出现,则说明成功!如下图所示:
-
将生成的
jed_stone.img作为 VMware 的软盘镜像。设置方法如图: -
准备工作全部完成,可以正式开始实验了!
-
虚拟机的安装
-
制作1.44MB虚拟软盘,并格式化为 DOS 引导盘
-
下载 MS-DOS 6.22 镜像
DOS622.IMG,并为其创建一个新的虚拟机。创建一个软盘驱动器,将 DOS 镜像加载。 -
打开
WinImage,制作一个空的 1.44 MB软盘镜像文件empty.flp。 -
回到虚拟机,再添加一个软盘驱动器,将这个空的镜像文件加载。
-
开启虚拟机,依据提示安装 DOS 系统。如图,很快便安装好了:
-
此时,
A:为 DOS 安装盘,B:是刚刚添加的空软盘,即empty.flp。使用以下命令格式化该软盘。format b:
按提示操作,如图:
-
对比格式化前后
empty.flp文件内容的变化。以下截图来自WinHex工具:格式化前,内容是由
WinImage默认填充的。格式化后,变为 DOS 的特有格式:
-
-
制作1.44MB虚拟软盘,并在首扇区填满个人信息
-
按照“实验方案”栏目中的步骤创建好
jed_stone.img软盘镜像文件并将其设置在 VMware 中的虚拟软盘镜像后,开启虚拟机,无需其他操作即可看到效果。以下随意截取三张屏幕截图:
-
3.5寸软盘容量的计算如下:
80(磁道)x18(扇区)x512 bytes(扇区)x2(双面) = 1440 x1024 bytes = 1440 KB = 1.44MB
并非
1.44*1024*1024,在创建磁盘文件的时候需要注意这个小问题,从而保持严谨性。 -
主引导记录扇区的末尾两个字节必须是
0x55和0xAA,可以每次生成img文件后再用WinHex手动添加这两个字节,不过这样做太麻烦了。一种不错的方法是,在汇编文件末尾加上这两条伪指令:
times 510-($-$$) db 0 ; 填充0,一直到第510字节 db 55h, 0AAh ; 扇区末尾两个字节为0x55和0xAA
其中
$-$$是汇编中的一个常用技巧,它代表“本扇区到目前为止的字节数”。 -
如何对屏幕字符的背景色和前景色进行控制?每个字符的显示由2个字节表示,低字节是字符的ASCII码,高字节是字符的颜色属性。对于颜色属性的1个字节,从高到低的8个比特位依次用字母表示为:
KRGBIRGB,高四位控制背景色,低四位控制前景色,如下表:
尽管我早有使用虚拟机的经验,不过之前都是运行现成的操作系统。在裸机(虚拟的裸机)上跑程序还是第一次。
开始设计实验方案前,“接管裸机的控制权”这一任务看似十分困难,因为我完全不理解计算机是如何开机的、如何自举的,刚刚上电时计算机的CPU、内存将做什么操作等等。不过后来通过上课、查阅资料、与同学讨论,我逐渐填补了知识上的漏洞,懂得了计算机开机时会去哪个设备的哪个扇区,将多少数据传送到内存中的哪个单元;还学会了以文本方式在显示器上显示字符和字符串,甚至还直到如何改变字符的颜色和背景。
在之前的计算机组成原理课程中,我虽然学过一点 x86 汇编的知识,可是真正上手编程的机会并不是很多。通过本次实验,我学习了 NASM 汇编的格式、伪指令等知识。在程序末尾使用times伪指令来填充数据是我学到新的 NASM 汇编知识的一个例子。
- 都说主引导扇区末尾两个字节必须是 55AA。可是当引导程序不足512个字节时(此时第511和512个字节当然不是55和AA,因为它们根本不存在),虚拟机仍然可以正确引导程序。














