我的第二个汇编实验报告
实验2 用机器指令和汇编指令编程
1. 预备知识:DEBUG的使用
前面实验中,讲了DEBUG一些主要命令的用法,这里,我们再补充一些关于DEBUG的知识。
(1) 关于D命令
从上次实验中,我们知道,D命令是查看内存单元的命令,可以用:
D 段地址:偏移地址的格式查看指定的内存单元的内容,上次实验中,D命令后面的段地址和偏移地址都是直接给出的。
现在,我们知道段地址是放在段寄存器中的,在D命令后面直接给出段地址,是DEBUG提供的一种直观的操作方式。D命令是由DEBUG执行的,DEBUG在执行“D 1000:0”这样的命令时,也会先将段地址1000送入段寄存器中。
DEBUG是靠什么来执行D命令的?当然是一段程序。
谁来执行这段程序?当然是CPU。
所以,DEBUG在其处理D命令的程序段中,必须有将段地址送入段寄存器中的代码。
段寄存器有4个:CS、DS、SS、ES,将段地址送入哪个段寄存器呢?
首先不能是CS,因为CS:IP必须指向DEBUG处理D命令的代码,也不能是SS,因为SS:SP要指向栈顶。这样只剩下DS和ES可以选择,放在哪里呢?我们知道,访问内存的指令如“MOV AX,[0]”等一般都默认段地址在DS中,所以DEBUG在执行如:“D 段地址:偏移地址”这种D命令时,将段地址送入DS中比较方便。
D命令也提供了一种符合CPU机理的格式:“D 段寄存器:偏移地址”,以段寄存器中的数据为段地址SA,列出从SA:偏移地址开始的内存区间中的数据。以下是4个例子:
①-R DS
:1000
-D DS:0 ;查看从1000:0开始的内存区间中的内容
②-R DS
:1000
-D DS:10 18 ;查看从1000:10~1000:18中的内容
③-D CS:0 ;查看当前代码段中的指令代码
④-D SS:0 ;查看当前栈段中的内容
(2) 在E、A、U命令中使用段寄存器
在E、A、U这些可以带有内存单元地址的命令中,也可以同D命令一样,用段寄存器表示内存单元的段地址。以下是3个例子:
①-R DS
:1000
-E DS:0 11 22 33 44 55 6 ;在从1000:0开始的内存区间中写入数据
②-U CS:0 ;以汇编指令的形式,显示当前代码段中的代码,0代码的偏移地址
③-R DS
:1000
-A DS:0 ;以汇编指令的形式,向从1000:0开始的内存单元中写入指令
(3) 下一条指令执行了吗?
在DEBUG中,用A命令写一段程序:
MOV AX,2000
MOV SS,AX
MOV SP,10 ;安排2000:0~2000:F为栈空间,初始化栈顶。
MOV AX,3123
PUSH AX
MOV AX,3366
PUSH AX ;在栈中压入两个数据
仔细看一下图3.18中单步执行的结果,读者发现了什么问题?
在用T命令单步执行MOV AX,2000后,显示出当前CPU各个寄存器的状态和下一步要执行的指令:MOV SS,AX;
在用T命令单步执行MOV SS,AX后,显示出当前CPU各个寄存器的状态和下一步要执行的指令。。。。。,在这里我们发现了一个问题:MOV SS,AX的下一条指令应该是MOV SP,10,怎么变成了MOV AX,3123H
MOV SP,10到哪里去了?它被执行了吗?
我们再仔细观察,发现:
在程序执行前,AX=0000,SS=0B39,SP=FFEE
在用T命令单步执行MOV AX,2000后,AX=2000;SS=0B39;SP=FFEE
在用T命令单步执行MOV SS,AX后,AX=2000;SS=2000;SP=0010
注意,在用T命令单步执行MOV SS,AX前,SS=0B39,SP=FFEE,而执行后SS=2000,SP=0010,SS变为2000是正常的,这正是MOV SS,AX的执行结果。可是SP变为0010是怎么回事?在这期间,能够将SP设为0010的只有指令MOV SP,10,看来,MOV SP,10一定是得到了执行。
那么,MOV SP,10是在什么时候被执行的呢?当然是在MOV SS,AX之后,因为它就是MOV SS,AX的下一条指令。显然,在用T命令执行MOV SS,AX的时候,它的下一条指令MOV SP,10也紧接着被执行了。
整理一下我们分析的结果:在用T命令执行MOV SS,AX的时候,它的下一条指令MOV SP,10也紧接着执行了。一般情况下,用T命令执行一条指令后,会停止继续执行,显示出当前CPU各个寄存器的状态和下一步要执行的指令,但T命令执行MOV SS,AX的时候,没有做到这一点。
不单是MOV SS,AX,对于如:MOV SS,BX,MOV SS,[0],POP SS等指令都会发生上面的情况,这些指令有哪些共性呢?它们都是修改栈段寄存器SS的指令。
为什么会这样呢?要想彻底说清楚这里面来龙去脉,在这里还为时过早,因为这涉及到我们在以后的课程中要深入研究的内容:中断机制,它是我们后半部分课程中的一个主题。现在我们只要知道这一点就可以了:DEBUG的T命令在执行修改寄存器SS的指令时,一条指令也紧接着被执行。
2 实验任务
(1) 使用DEBUG,将上面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。
MOV AX,FFFF
MOV DS,AX
MOV AX,2200
MOV SS,AX
MOV SP,0100
MOV AX,[0] AX=5BEAH
ADD AX,[2] AX=5CCAH
MOV BX,[4] BX=30FCH
ADD BX,[6] BX=6022H
PUSH AX SP=00FEH,修改的是字单元2200:00FE
PUSH BX SP=00FCH,修改的是字单元2200:00FC
POP AX SP=00FEH,AX=6022H
POP BX SP=0100H,BX=5CCAH
PUSH [4] SP=00FEH,修改的是字单元2200:00FE,内容是30F0H
PUSH [6] SP=00FCH,修改的是字单元2200:00FC,内容是2F32H
(2) 仔细观察图3.19中的实验过程,然后分析:为什么2000:0~2000:F中的内容会发生改变?
可能要再便有些实验才能发现其中的规律。如果读者在这里就正确回答了这个问题,那么要恭喜读者,因为读者有很好的惜玉怜香。大多数的读者对这个问题还是比较迷惑的,不过不要紧,因为随着课程的进行,这个问题的答案将逐渐变得显而易见。
图3.19用DEBUG进行实验的示例
