实验1 用机器指令和汇编指令编程
一、实验目的
1. 熟练掌握使用debug工具编写和调试x86汇编命令的方法
2. 掌握8086CPU、寄存器、内存的基础知识
3. 理解并掌握内存中多字节数据的存放:小端法
4. 理解并掌握「栈」内存空间的特性和使用
5. 掌握指令mov, add, sub, jmp, push, pop的基础用法
二、实验内容
1. 教材实验1(P35)
2. 教材实验2(P71)
注意,为了便于验证实验结果,对「2. 实验任务」的(1)做如下两点调整:
① 在使用 a 命令输入指令调试之前,先使用 e 命令将内存单元 0022:0~0022:7连续 8 个字节数据
修改为 50H, 51H, 52H, 53H, 54H, 55H, 56H, 57H
② 将 P74 实验任务(1)中第1行的 mov ax, ffff → 改为 mov ax, 0022
三、实验过程以及结论
1. 教材实验1结论
实验任务(1):使用Debug,用 e 命令和 a 命令两种方式将下面的程序段写入内存,逐条执行,观察每条指令执行后CPU中相关寄存器中内容的变化。
机器码 汇编指令
b8 20 4e mov ax, 4E20
05 16 14 add ax, 1416
bb 00 20 mov ax, 2000
01 d8 add ax, bx
① 使用 e 命令写入机器码,并用 t 命令单步执行,效果如下:
② 使用 a 命令写入汇编指令,并用 t 命令单步执行,执行效果如下:
实验任务(2):将下面三条指令写入从2000 : 0 开始的内存单元中,利用这三条指令计算 2 的 8 次方。
mov ax, 1
add ax, ax
jmp 2000 : 2003
使用 a 命令写入汇编指令并且使用 t 命令单步调试实验结果如下图所示:
实验任务(3):PC机主板上的 ROM 中写有一个生产日期,在内存 FFF00H~FFFFFH 的某几个单元中,请找到这个生产日期并试图改变它。
使用 d 命令查看 FFF00H~FFFFFH 单元的数据,检查是否有生产日期,实验截图如下所示:
从上图可以看出ROM 的生产日期为 1992 年 1 月 1 日。
当试图改变地址是 FFF0:00F5 至 FFF0:00FC 的内存单元数据时,程序虽然不会报错,但是会发现数据并未被写入,具体内容如下图所示:
以上图情况来看,我们使用了 e 命令去改写地址 FFF0:00F5 至 FFF0:00FC 内存单元的数据,之后使用 d 命令查看改写的内容。
从中,我们可以得出改写的命令并未执行成功。究其原因,地址为 FFF0:00F5 ~ FFF0:00FC 的内存单元对于 8086 CPU而言其实是
属于 ROM 所映射的部分地址,凡是向只读存储器(ROM)的内存单元中写入数据的操作都是无效的,因为这等于改写只读存储
器的内容,这种操作是不被允许的,即使使用了 debug 命令修改其内存单元也会被视为无效指令。
实验任务(4):向内存从 B8100H 开始的单元中填写数据,如: -e B810:0000 01 01 02 02 03 03 04 04
实验结果如上图所示,可以发现屏幕上出现了几个特殊的字符,而且还带有颜色。其会出现的原因是由于我们向内存空间始址为
B810:0000 的内存单元连续写入了 8 字节的数据,对于 8086CPU 而言,内存地址为 A000:0000 ~ BFFF:000F 会被映射成显存
地址的范围,向地址范围是A000:0000 ~ BFFF:000F 的内存单元写入数据,就是向显存中写入数据,而这些数据会被显示卡输出
到显示器上,这正是在显示屏会显示输出特殊字符的原因所在。
2. 教材实验2结论
实验任务(1) :使用 Debug,将下面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。
mov ax, 0022
mov ds, ax
mov ax, 2200
mov ss, ax
mov sp, 0100
mov ax, [0]
add ax, [2]
mov bx, [4]
add bx, [6]
push ax
push bx
pop ax
pop bx
push [4]
push [6]
① 使用 e 命令修改内存单元0022:0~0022:f 中的数据:50 51 52 53 54 55 56 57,修改完使用 d 命令查看是否正确写入,命令
执行结果如下图所示:
② 使用 a 命令将上述汇编指令写入内存单元中,并且使用反汇编 u 命令来查看指令是否被正确写入,实验过程如下图所示:
③ 使用 t 命令,单步调试每一行汇编指令,实验结果如下图所示:
④ 理论分析结果与实验结果一致,理论分析的过程如下图所示:
实验任务(2):仔细观察 3.19 中的实验过程,然后分析:为什么 2000: 0 ~ 2000: f 的内容会发生改变?
① 使用 a 命令输入图 3.19 所示 7 条汇编指令,使用 e 命令修改 2000:0~2000:f 的值,以及确认是否修改成功,实验过程如下图所示:
② 使用 t 命令单步调试每一条汇编指令,同时使用 d 命令查看每一步指令执行内存空间 2000:0~2000:f 所变化的值,实验过程如下图所示:
以文字方式陈述:
① 前3行汇编指令的功能,特别是,mov sp, 10意味着什么?初始时栈顶和栈底分别是?
mov ax, 2000 ; 将数据 2000H 写入到 ax 寄存器当中 mov ss, ax ; 将 ax 中的数据写入到栈段寄存器(ss)当中,即间接将数据 2000H 写入到 ss 寄存器当中去 mov sp, 10 ; 将数据 10 H 写入到栈顶指针寄存器当中,即定义一个基址为 20000H 而栈长为 8 字的栈
mov sp, 10 ;意味着栈顶地址相对于栈基址的偏移量为 10 H
初始化栈顶的实际物理地址为:20010 H
初始化栈底的实际物理地址为:2000E H
② 基于单步调试观察到的变化,给出你对此的思考及可能原因分析。
下图的内存空间是仅对于出入栈的数据变化所画的图解:
但是在实验验证过程中,当Debug执行完 mov sp, 10 这条汇编指令的时候,此时使用 d 命令发现栈中存有数据,而之前使用 e 命令
写入的数据居然被覆盖了,但是仔细观察后,发现此时栈中存放的数据全部都是 8086CPU 中某些寄存器的值,从图中可以发现栈中存
有CS、IP、BP、AX等寄存器的值了,这说明这是设计者有意为之,考虑到栈中每一次执行指令的时候,Dos 将相关数据存储在栈中的
数据都必会有CS、IP这两个寄存器的值,而凡是被这两个寄存器所指向的内存单元都被认为是指令,同时栈中还存有先前 AX 寄存器的
值。由此可以推断 DOS 系统中只有一个栈,并且系统会用该栈暂存相关数据,以便执行下一条指令,而此实验中正好改变了系统中
SS、SP 的值,由此可见系统Debug单步调试的 t 命令执行汇编指令所需的数据全部都存放在栈当中。