预备知识:debug的使用
前面实验中讲了debug一些命令的用法,这里再补充一些关于debug的知识。
(1)关于D命令
从上面实验中我们知道D命令是查看内存单元的命令,可以用:“d段地址:偏移地址”查看指定的内存单元上的内容,上次实验中,d命令后面的段地址和偏移地址都是直接给出的。
现在我们知道段地址是存放在寄存器中的,在D命令后面直接给出段地址,是debug提供的一种直观的操作方式。D命令是由debug执行的,debug在执行d 1000:0这样的命令时会先将段地址1000H送入寄存器中。
debug是靠什么执行D命令的?当然是一段程序。谁来执行这段程序?当然是cpu
cpu在访问内存单元的时候从哪得到内存单元中的段地址?从段寄存器中得到。
所以,debug在处理D命令的程序段中,必须有将段地址送入寄存器的代码。
段寄存器有4个:cs,ds,ss,es,将段地址送入哪个寄存器呢?
首先不能是cs,因为cs:ip寄存器存放的是指令地址,也不能是ss,ss:sp指向的栈顶地址,这样只剩下ds和es,可以选择放在哪里?我们知道访问内存的指令“mov ax,[0]”等一般都默认在ds中,所以debug在执行段地址:偏移地址这种D命令时,将段地址送入ds中比较方便。
D命令也提供了一种符合CPU机理的格式:“d段寄存器:偏移地址”,以段寄存器中的数据为段地址sa,列出从sa:偏移地址开始的内存数据。以下是几个例子。
-r ds
:1000
-d ds:0查看从1000:0开始的内存区间的内容
-r ds
:1000
-d ds:0 18 查看从1000:0 ~ 1000:18内存区间的内容
-d cs:0 查看当前代码段中的指令代码
-d ss:0 查看当前栈段中的内容
(2)在E,A,U命令中使用段寄存器。
在E,A,U这些可以带有内存单元地址的命令中,也可以同D命令一样,用段寄存器表示内存单元中的段地址,以下是几个例子。
-r ds
:1000
-e ds:0 11 22 33 44 55 66从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
mov ax,3123
push ax
mov ax,3366
push ax
从下面运行过程,发现什么
再用T执行mov ax,2000后的下条指令是,mov ax,ss当我们执行完mov ax,ss指令后应当显示的下条执行指令应该是mov sp,10但是却是,mov ax,3123,为什么会这样?
我们发现,在执行mov ss,ax之后不仅仅只有ss发生了改变,而sp也发生了改变,变成了我们应当执行,mov sp,10的结果说明我们在执行mov ss,ax时,sp也紧跟着执行了,但为什么会这样呢?这个内容不是我们当前所要学习的,会在中断机制中进行讲解。
实验任务
使用debug,将下面程序写入内存,逐条执行,根据被执行后的答案进行填空。
ax=ffff
ds=ffff
ax=2200
ss=2200
sp=0100
mov ax,[0] ax=C0EA
add ax,[2] ax=COFC
mov bx,[4] bx=30F0
add bx,[6] bx=6021
push ax sp=000E
push bx sp=000C
pop ax sp=000E,ax=6021
pop bx sp=0010,bx=COFC
push [4] sp=000E 2200:000E,30F0
push [6] sp=000C,2200:000C,6021
(2)仔细观察下图的实验过程,然后分析为什么2000:0~2000:f中的内容会发生变化
一些见解:
执行mov ss,ax 时其后边的指令将立即被执行(这是MOV SS,**指令特点)。这也是为什么强调mov ss,ax 后边必须跟上mov sp,10的原因。这么规定是便于控制栈段大小,防止特别是在有子程序调用时出错。至于这两条指令执行后靠近栈顶的10个字节中值立即有了变化,是对定义栈段时部分运行环境变量进行暂存,靠近栈顶的10个字节中的暂存数据分别是SS、IP、 CS 等的值。