汇编语言程序设计的实验环境及上机步骤 下载本文

汇编语言程序设计的实验环境及上机步骤

一、 实验环境

汇编语言程序设计的实验环境如下: 1. 硬件环境

微型计算机(Intel x86系列CPU)一台 2. 软件环境

? Windows98/2000/XP操作系统

? 任意一种文本编辑器(EDIT、NOTEPAD(记事本)、UltraEDIT等) ? 汇编程序(MASM.EXE或TASM.EXE) ? 连接程序(LINK.EXE或TLINK.EXE) ? 调试程序(DEBUG.EXE或TD.EXE)

文本编辑器建议使用EDIT或NOTEPAD,汇编程序建议使用MASM.EXE,连接程序建议使用LINK.EXE,调试程序建议使用TD.EXE。

二、 上机实验步骤

注:以下步骤适用于除汇编语言程序设计的实验一到实验四外的所有实验(实验一到实验四仅使用TD.EXE)。

1.确定源程序的存放目录

建议源程序存放的目录名为ASM(或MASM),并放在C盘或D盘的根目录下。如果没有创建过此目录,请用如下方法创建:

通过Windows的资源管理器找到C盘的根目录,在C盘的根目录窗口中点击右键,在弹出的菜单中选择“新建”→“文件夹”,并把新建的文件夹命名为ASM。

请把MASM.EXE、LINK.EXE、DENUG.EXE和TD.EXE都拷贝到此目录中。

2.建立ASM源程序

建立ASM源程序可以使用EDIT或NOTEPAD(记事本)文本编辑器。下面的例子说明了用EDIT文本编辑器来建立ASM源程序的步骤(假定要建立的源程序名为HELLO.ASM),用NOTEPAD(记事本)建立ASM源程序的步骤与此类似。

在Windows中点击桌面左下角的“开始”按钮→选择“运行”→在弹出的窗口中输入“EDIT.COM C:\\ASM\\HELLO.ASM”,屏幕上出现EDIT的编辑窗口,如图1所示。

图1 文本编辑器EDIT的编辑窗口

窗口标题行显示了EDIT程序的完整路径名。紧接着标题行下面的是菜单行,窗口最下面一行是提示行。菜单可以用Alt键激活,然后用方向键选择菜单项,也可以直接用Alt-F打开File文件菜单,用Alt-E打开Edit编辑菜单,等等。

如果键入EDIT命令时已带上了源程序文件名(C:\\ASM\\HELLO.ASM),在编辑窗口上部就会显示该文件名。如果在键入EDIT命令时未给出源程序文件名,则编辑窗口上会显示“UNTITLED1”,表示文件还没有名字,在这种情况下保存源程序文件时,EDIT会提示输入要保存的源程序的文件名。

编辑窗口用于输入源程序。EDIT是一个全屏幕编辑程序,故可以使用方向键把光标定位到编辑窗口中的任何一个位置上。EDIT中的编辑键和功能键符合Windows的标准,这里不再赘述。

源程序输入完毕后,用Alt-F打开File菜单,用其中的Save功能将文件存盘。如果在键入EDIT命令时未给出源程序文件名,则这时会弹出一个“Save as”窗口,在这个窗口中输入你想要保存的源程序的路径和文件名(本例中为C:\\ASM\\HELLO.ASM)。

注意,汇编语言源程序文件的扩展名最好起名为.ASM,这样能给后面的汇编和连接操作带来很大的方便。

3.用MASM.EXE汇编源程序产生OBJ目标文件

源文件HELLO.ASM建立后,要使用汇编程序对源程序文件汇编,汇编后产生二进制的目标文件(.OBJ文件)。具体操作如下:

方法一:在Windows中操作

用资源管理器打开源程序目录C:\\ASM,把HELLO.ASM拖到MASM.EXE程序图标上。 方法二:在DOS命令提示符窗口中操作

选择“开始”→“程序”→“附件”→“命令提示符”,打开DOS命令提示符窗口,然后用CD命令转到源程

序目录下,接着输入MASM命令:

I:>C:<回车> C:>CD \\ASM<回车>

C:\\ASM>MASM HELLO.ASM<回车> 操作时的屏幕显示如图2所示。

图2 在DOS命令提示符窗口中进行汇编

不管用以上二个方法中的哪个方法,进入MASM程序后,都会提示让你输入目标文件名(Object filename),并在方括号中显示默认的目标文件名,建议输入目标文件的完整路径名,如:C:\\ASM\\HELLO.OBJ〈回车〉。后面的两个提示为可选项,直接按回车。注意,若打开MASM程序时未给出源程序名,则MASM程序会首先提示让你输入源程序文件名(Source filename),此时输入源程序文件名HELLO.ASM并回车,然后进行的操作与上面完全相同。

图3 有错误的汇编过程例子

如果没有错误,MASM就会在当前目录下建立一个HELLO.OBJ文件(名字与源文件名相同,只是扩展名不同)。如果源文件有错误,MASM会指出错误的行号和错误的原因。图3是在汇编过程中检查出两个错误的例子。在这个例子中,可以看到源程序的错误类型有两类:

警告错误(Warning Errors)。警告错误不影响程序的运行,但可能会得出错误的结果。此例中无警告错误。 严重错误(Severe Errors)。对于严重错误,MASM将无法生成OBJ文件。此例中有两个严重错误。

在错误信息中,园括号里的数字为有错误的行号(在此例中,两个错误分别出现在第6行和第9行),后面给出了错误类型及具体错误原因。如果出现了严重错误,你必须重新进入EDIT编辑器,根据错误的行号和错误原因来改正源程序中的错误,直到汇编没有错为止。

注意,汇编程序只能指出程序的语法错误,而无法指出程序逻辑的错误。

4.用LINK.EXE产生EXE可执行文件

在上一步骤中,汇编程序产生的是二进制目标文件(OBJ文件),并不是可执行文件,要想使我们编制的程序能够运行,还必须用连接程序(LINK.EXE)把OBJ文件转换为可执行的EXE文件。具体操作如下:

方法一:在Windows中操作

用资源管理器打开源程序目录C:\\ASM,把HELLO.OBJ拖到LINK.EXE程序图标上。

方法二:在DOS命令提示符窗口中操作

选择“开始”→“程序”→“附件”→“命令提示符”,打开DOS命令提示符窗口,然后用CD命令转到源程序

目录下,接着输入LINK命令:

I:>C:<回车> C:>CD \\ASM<回车>

C:\\ASM>LINK HELLO.OBJ<回车>

操作时的屏幕显示如图4所示。

图4 把OBJ文件连接成可执行文件

不管用以上二个方法中的哪个方法,进入LINK程序后,都会提示让你输入可执行文件名(Run file),并在方括号中显示默认的可执行文件名,建议输入可执行文件的完整路径名,如:C:\\ASM\\HELLO.EXE〈回车〉。后面的两个提示为可选项,直接按回车。注意,若打开LINK程序时未给出OBJ文件名,则LINK程序会首先提示让你输入OBJ文件名(Object Modules),此时输入OBJ文件名HELLO.OBJ并回车,然后进行的操作与上面完全相同。

如果没有错误,LINK就会建立一个HELLO.EXE文件。如果OBJ文件有错误,LINK会指出错误的原因。对于无堆栈警告(Warning:NO STACK segment)信息,可以不予理睬,它不影响程序的执行。如链接时有其它错误。须检查修改源程序,重新汇编、连接,直到正确。

5.执行程序

建立了HELLO.EXE文件后,就可以直接在DOS下运行此程序,如下所示:

C:>HELLO〈回车〉 C:>

程序运行结束后,返回DOS。如果运行结果正确,那么程序运行结束时结果会直接显示在屏幕上。如果程序不显示结果,我们如何知道程序是否正确呢?例如,这里的HELLO.EXE程序并未显示出结果,所以我们不知道程序执行的结果是否正确。这时,我们就要使用TD.EXE调试工具来查看运行结果。此外,大部分程序必须经过调试阶段才能纠正程序执行中的错误,调试程序时也要使用TD.EXE。

实验一 数据传送

一、 实验目的

1.熟悉8086指令系统的数据传送指令及8086的寻址方式。

2.利用Turbo Debugger调试工具来调试汇编语言程序。 二、 实验预习要求

1.复习8086指令系统中的数据传送类指令和8086的寻址方式。 2.预习Turbo Debugger的使用方法(见附录二):

a) 如何启动Turbo Debugger; b) 如何在各窗口之间切换;

c) 如何查看或修改寄存器、状态标志和存储单元的内容; d) 如何输入程序段;

e) 如何单步运行程序段和用设置断点的方法运行程序段。 3.按照题目要求预先编写好实验中的程序段。 三、 实验任务

1.通过下述程序段的输入和执行来熟悉Turbo Debugger的使用,并通过显示器屏幕观察程序的执行情况。练习程序段如下:

MOV BL,08H MOV CL,BL MOV AX,03FFH MOV BX,AX

MOV DS:[0020H],BX

2.用以下程序段将一组数据压入(PUSH)堆栈区,然后通过不同的出栈顺序出栈,观察出栈后数据的变化情况。压栈程序段如下:

MOV AX,0102H MOV BX,0304H MOV CX,0506H MOV DX,0708H PUSH AX PUSH BX PUSH CX PUSH DX

出栈程序段请自行编写(用不同的出栈顺序)。 3. 指出下列指令的错误并加以改正,上机验证之。 (1) MOV [BX],[SI] (2) MOV AH,BX

(3) MOV AX,[SI][DI]

(4) MOV BYTE PTR[BX],2000H (5) MOV CS,AX (6) MOV DS,2000H

4. 设置各寄存器及存储单元的内容如下: (BX)=0010H,(SI)=0001H

(10010H)=12H,(10011H)=34H,(10012H)=56H,(10013H)=78H (10120H)=0ABH,(10121H)=0CDH,(10122H)=0EFH 说明下列各条指令执行完后AX寄存器中的内容,并上机验证。

(1) MOV AX,1200H (2) MOV AX,BX (3) MOV AX,[0120H] (4) MOV AX,[BX] (5) MOV AX,0110H[BX] (6) MOV AX,[BX][SI] (7) MOV AX,0110H[BX][SI]

5. 将DS:1000H字节存储单元中的内容送到DS:2020H单元中存放。试分别用8086的直接寻址、寄存器间接寻址、变址寻址、寄存器相对寻址传送指令编写程序段,并上机验证结果。

6. 设AX寄存器中的内容为1111H,BX寄存器中的内容为2222H,DS:0010H单元中的内容为3333H。将AX寄存器中的内容与BX寄存器中的内容交换,然后再将BX寄存器中的内容与DS:0010H单元中的内容进行交换。试编写程序段,并上机验证结果。

7. 设(DS)=1000H,(ES)=2000H,有关存储器的内容如图1.5所示。要求将DS段的内容传送到AX寄存器,ES段的内容传送到BX寄存器,试编写程序段。

? ? ? DS:1000H

0FFH 0EEH

ES:2000H

0DDH 0CCH

图1.5 第7题图

实验二 算术逻辑运算及移位操作

一、 实验目的

1.熟悉算术逻辑运算指令和移位指令的功能。

2.了解标志寄存器各标志位的意义和指令执行对它的影响。 二、 实验预习要求

1.复习8086指令系统中的算术逻辑类指令和移位指令。 2.按照题目要求在实验前编写好实验中的程序段。 三、 实验任务 1.

实验程序段及结果表格如表1.2: 表1.2

标志位 程序段1: MOV AX, 1018H MOV SI, 230AH ADD AX, SI ADD AL, 30H MOV DX, 3FFH ADD AX,BX MOV [20H], 1000H ADD [20H], AX PUSH AX POP BX 程序段2: MOV AX, 0A0AH ADD AX, 0FFFFH MOV CX, 0FF00H ADC AX, CX SUB AX, AX INC AX OR CX, 0FFH AND CX, 0F0FH MOV [10H], CX 程序段3: MOV BL, 25H MOV BYTE PTR[10H], 4 MOV AL, [10H] CF 0 0 0 0 0 0 0 0 0 0 ZF 0 0 0 0 0 0 0 0 0 0 SF 0 0 0 0 0 0 0 0 0 0 OF 0 0 0 0 0 0 0 0 0 0 PF 0 0 0 1 0 0 0 0 0 0 AF 0 0 0 1 0 0 0 0 0 0 MUL BL 程序段4: MOV WORD PTR[10H],80H MOV BL, 4 MOV AX, [10H] DIV BL 程序段5: MOV AX, 0 DEC AX ADD AX, 3FFFH ADD AX, AX NOT AX SUB AX, 3 OR AX, 0FBFDH AND AX, 0AFCFH SHL AX,1 RCL AX,1

2. 用BX寄存器作为地址指针,从BX所指的内存单元(0010H)开始连续存入三个无符号数(10H、04H、30H),接着计算内存单元中的这三个数之和,和放在0013H单元中,再求出这三个数之积,积放0014单元中。写出完成此功能的程序段并上机验证结果。

3.写出完成下述功能的程序段。上机验证你写出的程序段,程序运行的最后结果(AX)=? 72 (1) 传送15H到AL寄存器; (2) 再将AL的内容乘以2; (3) 接着传送15H到BL寄存器; (4) 最后把AL的内容乘以BL的内容。

MOV BX, 0010H

MOV BYTE PTR[BX], 10H MOV BYTE PTR[BX+1], 04H MOV BYTE PTR[BX+2], 30H MOV AL, 0H MOV AL, [BX] ADD AL, [BX+1] ADD AL, [BX+2]

MOV BYTE PTR[BX+3], AL

0 0 0 0 0 0 0 0 0 0 0 0 MOV AL, 15H MUL 2 MOV BL, 15H MUL BL

4.写出完成下述功能的程序段。上机验证你写出的程序段,程序运行后的商=? (1) 传送数据2058H到DS:1000H单元中,数据12H到DS:1002H单元中; (2) 把DS:1000H单元中的数据传送到AX寄存器; (3) 把AX寄存器的内容算术右移二位;

(4) 再把AX寄存器的内容除以DS:1002H字节单元中的数; (5) 最后把商存入字节单元DS:1003H中。

5.下面的程序段用来清除数据段中从偏移地址0010H开始的12个字存储单元的内容(即将零送到这些存储单元中去)。

(1) 将第4条比较指令语句填写完整(划线处)。 MOV SI,0010H NEXT: MOV WORD PTR[SI],0 ADD SI,2 CMP SI,

JNE NEXT

HLT

(2) 假定要按高地址到低地址的顺序进行清除操作(高地址从0020H开始),则上述程序段应如何修

改?

上机验证以上两个程序段并检查存储单元的内容是否按要求进行了改变。

6. 输入并运行表1.3中的程序段,把结果填入表右边的空格中,并分析结果,说明本程序段的功能是什么。

表1.3

程序段 MOV [1A00H], 0AA55H MOV [1A02H], 2AD5H SHL WORD PTR[1A02H],1 CMP [1A00H], 8000H CMC RCL WORD PTR[1A02H],1 字单元(1A00H)= 字单元(1A02H)= RCL WORD PTR[1A00H],1

实验三 串操作

一、 实验目的

1.熟悉串操作指令的功能。 2.了解串操作指令的使用方法。 二、 实验预习要求

1.复习8086指令系统中的串操作类指令。 2.按照题目要求在实验前编写好实验中的程序段。 三、 实验任务

1.输入以下程序段并运行之,回答后面的问题。

CLD

MOV DI,1000H MOV AX,55AAH MOV CX,10H REP STOSW 上述程序段执行后:

(1) 从DS:1000H开始的16个字单元的内容是什么?

(2) (DI)= ?(CX)= ?,并解释其原因。

2.在上题的基础上,再输入以下程序段并运行之,回答后面的问题。

MOV SI,1000H MOV DI,2000H MOV CX,20H REP MOVSB 程序段执行后:

(1) 从DS:2000H开始的16个字单元的内容是什么? (2) (SI)= ?(DI)= ?(CX)= ?,并分析之。

3.在以上两题的基础上,再输入以下三个程序段并依次运行之。

程序段1: MOV SI,1000H MOV DI,2000H MOV CX,10H REPZ CMPSW 程序段1执行后:

(1) ZF=? 根据ZF的状态,你认为两个串是否比较完了? (2)(SI)= ?(DI)= ?(CX)= ?,并分析之。 程序段2:

MOV [2008H],4455H MOV SI,1000H MOV DI,2000H MOV CX,10H REPZ CMPSW 程序段2执行后:

(1) ZF=? 根据ZF的状态,你认为两个串是否比较完了? (2)(SI)= ?(DI)= ?(CX)= ?,并分析之。 程序段3: MOV AX,4455H MOV DI,2000H MOV CX,10H REPNZ SCASW 程序段3执行后:

(1) ZF=? 根据ZF的状态,你认为在串中是否找到了数据4455H?

(2)(SI)= ?(DI)= ?(CX)= ?,并分析之。

4.从DS:1000H开始存放有一个字符串”This is a string”,要求把这个字符串从后往前传送到DS:2000H开始的内存区域中(即传送结束后,从DS:2000H开始的内存单元的内容为”gnirts a si sihT”),试编写程序段并上机验证之。

实验四 字符及字符串的输入和输出

一、 实验目的

1.熟悉如何进行字符及字符串的输入输出。 2.掌握简单的DOS系统功能调用。 二、 实验预习要求

1.复习系统功能调用的1、2、9、10号功能。 2.按照题目要求预先编写好实验中的程序段。 三、 实验任务

1.输入以下程序段并用F8键单步运行,执行INT 21H指令时,在键盘上按“5”键。

MOV AH,1 INT 21H

(1) 运行结束后,(AL)=?它是哪一个键的ASCII码?

(2) 重复运行以上程序段,并分别用“A”、“B”、“C”、“D”键代替“5”键,观察运行结果有

何变化?

2.在DS:1000H开始的内存区域设置如下键盘缓冲区:

DS:1000H 5,0,0,0,0,0,0

然后输入以下程序段并用F8键单步运行,执行INT 21H指令时,在键盘上键入“5”、“4”、“3”、“2”、“1”、〈回车〉这六个键。 LEA DX,[1000H] MOV AH,0AH INT 21H

程序段运行完后,检查DS:1000H开始的内存区域: (1) DS:1001H单元的内容是什么?它表示了什么含义?

(2) 从DS:1002H开始的内存区域中的内容是什么?其中是否有字符“1”的ASCII码?为什么? 3.输入以下程序段并运行之。

MOV DL,‘A’ MOV AH,2 INT 21H

(1) 观察屏幕上的输出,是否显示了“A”字符?

(2) 分别用“#”、“X”、“Y”、“$”、“?”代替程序段中的“A”字符,观察屏幕上的输出有何变

化。 (3) 分别用0DH、0AH代替程序段中的“A”字符,观察屏幕上的输出有何变化。

(4) 用07H代替程序段中的“A”字符,观察屏幕上有无输出?计算机内的扬声器是否发出“哔”

的声音?

4.要在屏幕上显示一个字符串“Hello, world”,写出该字符串变量的定义语句和显示这个字符串的程序段。上机验证之。

5.按6行×16列的格式顺序显示ASCII码为20H到7FH之间的所有字符,即每16个字符为一行,共6行。每行中相邻的两个字符之间用空格字符分隔开。试编写程序段并上机运行验证。提示:程序段包括两层循环,内循环次数为16,每次内循环显示一个字符和一个空格字符;外循环次数为6,每个外循环显示一行字符并显示一个回车符(0DH)和一个换行符(0AH)。

实验五 直线程序设计

一、 实验目的

1、学习8086汇编语言程序的基本结构和程序设计的基本方法。

2、熟悉在PC机上建立、汇编、链接、调试和运行8086汇编语言程序的全过程。

二、 实验预习要求 1、

认真阅读预备知识中汇编语言的上机步骤的说明,熟悉汇编程序的建立、汇编、连接、执行、

调试的全过程。

2、 复习BCD码运算的调整指令。

3、根据本实验的编程提示和程序框架预先编写汇编语言源程序。 4、有兴趣的同学请自行编写出后面的实验习题。 三、 直线程序简介

直线程序是控制流仅有一个走向的程序,它主要用于解决一些无需进行判断分支,也无需循环简单的简单问题。

四、 实验内容

设a、b、c、d四个数分别以压缩的BCD码形式存放在内存NUM开始的四个单元,计算(a+b)-(c+d),然后把结果显示在屏幕上。

改变a,b,c,d内容,然后重新汇编、连接并运行程序,检查其结果与手工计算是否相符。下面是几组实验用的数据:

1、a=09,b=16,c=04,d=17 2、a=38,b=41,c=29,d=34 3、a=70,b=23,c=42,d=41 4、a=63,b=73,c=62,d=50 五、 调试提示

源程序编制完后,先静态检查,无误后,对源程序进行汇编连接,生成可执行文件。

先将程序在DOS下运行,如正确,则改变a,b,c,d的值反复验证,如不正确,则将程序调入TD中进行调试。

六、 实验习题

若改变a, b, c, d的值如下: 1、a=90,b=34,c=33,d=44 2、a=12,b=19,c=25,d=33 观察结果,改进程序使结果正确。

实验六 分支及循环程序设计

一、 实验目的

1、学习提示信息的显示及键盘输入字符的方法。 2、掌握分支程序和循环程序的设计方法。 二、 实验预习要求

1、复习比较指令、转移指令、循环指令的用法。 2、根据编程提示,编出汇编语言源程序。 3、有兴趣的同学请编写出实验习题中的程序。 三、 分支程序和循环程序简介 1、

分支程序是根据不同条件执行不同处理过程的程序。分支程序的结构有两种:—种是二分支,

—种是多分支。它们的共同特点是在满足某一条件时,将执行多个分支中的某—分支。

2、

循环程序

四、 实验内容

在屏幕上显示提示信息“Please input 10 numbers:”,提示用户输入10个数(数的范围在0~99之间),然后从键盘上读入这10个数。接着对这10个数从小到大进行排序,并统计0~59、60~79、80~99的数各有多少。最后在屏幕上显示排序后的数(每个数之间用逗号分隔)并显示统计的结果。显示格式如下:

Sorted numbers: xx,xx,xx,xx,xx,xx,xx,xx,xx,xx 0-59: xx 60-79: xx 80-99: xx 五、 实验习题

1. 从键盘输入任意一个字符串,统计其中不同字符出现的次数(不分大小写),并把结果显示在屏幕上。

2. 从键盘分别输入两个字符串,若第二个字符串包含在第一个字符串中则显示‘MATCH’,否则显示‘NO MATCH’。

TD.EXE简要使用说明

TD. EXE(简称TD)是一个具有窗口界面的程序调试器。利用TD,用户能够调试已有的可执行程序(后缀为EXE);用户也可以在TD中直接输入程序指令,编写简单的程序(在这种情况下,用户每输入一条指令,TD就立即将输入的指令

汇编成机器指令代码)。作为入门指导,下面简单介绍一下TD的使用方法,更详细深入的使用说明请参考相关资料。

一、如何启动TD 二、TD中的数制 三、TD的用户界面 四、代码区的操作

五、寄存器区和标志区的操作 六、数据区的操作 七、堆栈区的操作

一、如何启动TD

1. 在DOS窗口中启动TD

?

回车键,下同):

仅启动TD而不载入要调试的程序

转到TD.EXE所在目录(假定为C:\\ASM),在DOS提示符下键入以下命令(用户只需输入带下划线的部分,↙表示

C:\\ASM>TD↙

用这种方法启动TD,TD会显示一个版权对话框,这时按回车键即可关掉该对话框。

? 启动TD并同时载入要调试的程序

转到TD.EXE所在目录,在DOS提示符下键入以下命令(假定要调试的程序名为HELLO.EXE):

C:\\ASM>TD HELLO.EXE↙

若建立可执行文件时未生成符号名表,TD启动后会显示“Program has no symbol table”的提示窗口,这时按回车键即可关掉该窗口。

2. 在Windows中启动TD

? 仅启动TD而不载入要调试的程序

双击TD.EXE文件名,Windows就会打开一个DOS窗口并启动TD。启动TD后会显示一个版权对话框,这时按回车键即可关掉该对话框。

? 启动TD并同时载入要调试的程序

把要调试的可执行文件拖到TD.EXE文件名上,Windows就会打开一个DOS窗口并启动TD,然后TD会把该可执行文件自动载入内存供用户调试。

若建立可执行文件时未生成符号名表,TD启动后会显示“Program has no symbol table”的提示窗口,这时按回车键即可关掉该窗口。

二、TD中的数制

TD支持各种进位记数制,但通常情况下屏幕上显示的机器指令码、内存地址及内容、寄存器的内容等均按十六进制显示(数值后省略“H”)。在TD

的很多操作中,需要用户输入一些数据、地址等,在输入时应遵循计算机中数的记数制标识规范。例如: 二进制数后面加“B”或“b”,如10010001b等; 十六进制数后面加“H”或“h”,如38h、0a5h、0ffh等。

如果在输入的数后面没有用记数制标识字母来标识其记数制,TD默认该数为十六进制数。但应注意,如果十六进制数的第一个数字为“a”~“f”,则

前面应加0,以区别于符号和名字。

TD允许在常数前面加上正负号。例如,十进制数的-12可以输入为-12d,十六进制数的-5a可以输入为-5ah,TD自动会把输入的带正负号的数转换为十六

进制补码数。只有一个例外,当数据区的显示格式为字节,若要修改存储单元的内容则不允许用带有正负号的数,而只能按手工转换成补码后再输入。

本实验指导书中所有的实验在输入程序或数据时,若没有特别说明,都可按十六进制数进行输入,若程序中需要输入负数,可按上述规则进行输入。

三、TD的用户界面

1.CPU窗口

TD启动后呈现的是一个具有窗口形式的用户界面,见图B.1,它称为CPU窗口。CPU窗口显示了CPU和内存的整个状态。利用CPU窗口可以:

? 在代码区内使用嵌入汇编,输入指令或对程序进行临时性修改。 存取数据区中任何数据结构下的字节,并以多种格式显示或改变它们。 检查和改变寄存器(包括标志寄存器)的内容。

? ?

全局菜单

代码区

数据区

功能键提示条

寄存器区 堆栈区 标志区

图B.1 TD的CPU窗口界面

CPU窗口分为五个区域:代码区、寄存器区、标志区、数据区和堆栈区。

在五个区域中,光标所在区域称为当前区域,用户可以使用Tab键或Shift-Tab键切换当前区域,也可以在相应区中单击鼠标左键选中某区

为当前区。光标在各个区域中显示形式稍有不同,在代码区、寄存器区、标志区和堆栈区呈现为一个反白条,在存储器区为下划线形状。

在图B.1中,CPU窗口上边框的左边显示的是处理器的类型(8086、80286、80386、80486等,对于80486以上的CPU均显示为80486)。上边

框的中间靠右处显示了当前指令所访问的内存单元的地址及内容。再往右的“1”表示此CPU窗口是第一个CPU窗口,TD允许同时打开多个CPU窗口。

CPU窗口中的代码区用于显示指令地址、指令的机器代码以及相应的汇编指令;寄存器区用于显示CPU寄存器当前的内容;标志区用于显示CPU

的8个标志位当前的状态;数据区用于显示用户指定的一块内存区的数据(十六进制);堆栈区用于显示堆栈当前的内容。 在代码区和堆栈区分别显示有一个特殊标志(?),称为箭标。代码区中的箭标指示出当前程序指令的位置(CS:IP),堆栈区中的箭标指示出

当前堆栈指针位置(SS:SP)。

2.全局菜单介绍

CPU窗口的上面为TD的全局菜单条,可用“ALT键+菜单项首字符”打开菜单项对应的下拉子菜单。在子菜单中用“↑”、“↓”键选择所需的

功能,按回车键即可执行选择的功能。为简化操作,某些常用的子菜单项后标出了对应的快捷键。下面简单介绍一下常用的菜单命令,详细的说明

情查阅相关资料。

(1) File菜单:文件操作

Open 载入可执行程序文件准备调试 Change dir 改变当前目录 Get info 显示被调试程序的信息

DOS shell 执行DOS命令解释器(用EXIT命令退回到TD) Quit 退出TD(Alt-X)

(2)

Copy 复制当前光标所在内存单元的内容到粘贴板(Shift-F3) Paste 把粘贴板的内容粘贴到当前光标所在内存单元(Shift-F4)

(3)

Breakpoints 断点信息 Stack 堆栈段内容 Watches 被监视对象信息 Variables 变量信息 Module 模块信息 File 文件内容

CPU 打开一个新的CPU窗口

Dump 数据段内容 Registers 寄存器内容

(4)

Run 从CS:IP开始运行程序直到程序结束(F9) Go to cursor 从CS:IP开始运行程序到光标处(F4)

Trace into 单步跟踪执行(对CALL指令将跟踪进入子程序)(F7) Step over 单步跟踪执行(对CALL指令将执行完子程序才停下)(F8) Execute to 执行到指定位置(Alt-F9) Until return 执行当前子程序直到退出(Alt-F8)

(5)

Toggle 在当前光标处设置/清除断点(F2) At 在指定地址处设置断点(Alt-F2) Delete all 清除所有断点

(6)

Inspector 打开观察器以查看指定的变量或表达式 Evaluate/Modify 计算和显示表达式的值

Add watch 增加一个新的表达式到观察器窗口

(7)

Display options 设置屏幕显示的外观 Path for source 指定源文件查找目录 Save options 保存当前选项

(8)

Zoom 放大/还原当前窗口(F5) Next 转到下一窗口(F6)

Next Pane 转到当前窗口的下一区域(Tab) Size/Move 改变窗口大小/移动窗口(Ctrl-F5) Close 关闭当前窗口(Alt-F3)

User screen 查看用户程序的显示(Alt-F5)

3.功能键提示条

菜单中的很多命令都可以使用功能键来简化操作。功能键分为三组:F1~F10功能键,Alt-F1~Alt-F10功能键以及Ctrl功能键(Ctrl功能键实际

上就是代码区的局部菜单)。CPU窗口下面的提示条中显示了这三组功能键对应的功能。通常情况下提示条中显示的是F1~F10功能键的功能。按

住Alt不放,提示条中将显示Alt-F1~Alt-F10功能键的功能。按住Ctrl不放,提示条中将显示各Ctrl功能键的功能。表B.1列出了各功能键对应的功能。

表B.1

键 功能 键 功能 键 功能 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 帮助 设/清断点 查看模块 运行到光标 放大窗口 下一窗口 跟踪进入 单步跟踪 执行程序 激活菜单 Alt-F1 Alt-F2 Alt-F3 Alt-F4 Alt-F5 Alt-F6 Alt-F7 Alt-F8 Alt-F9 Alt-F10 帮助 设置断点 关闭窗口 Undo跟踪 用户屏幕 Undo关窗 指令跟踪 跟踪到返回 执行到某处 局部菜单 Ctrl-G Ctrl-O Ctrl-F Ctrl-C Ctrl-P Ctrl-S Ctrl-V Ctrl-M Ctrl-N 定位到指定地址 定位到CS:IP 定位到指令目的地址 定位到调用者 定位到前一个地址 查找指定的指令 查看源代码 选择代码显示方式 更新CS:IP 局部菜单

TD的CPU窗口中,每个区域都有一个局部菜单,局部菜单提供了对本区域进行操作的各个命令。在当前区域中按Alt-F10键即可激活本区域的

局部菜单。代码区、数据区、堆栈区和寄存器区的局部菜单见图B.2~图B.5所示。标志区的局部菜单非常简单,故没有再给出其图示。对局部菜

单中各个命令的解释将在下面几节中分别进行说明。

图B.2 代码区的局部菜单

图B.3 数据区的局部菜单

图B.4 堆栈区的局部菜单

图B.5 寄存器区的局部菜单

四、代码区的操作

代码区用来显示代码(程序)的地址、代码的机器指令和代码的反汇编指令。本区中显示的反汇编指令依赖于所指定的程序起始地址。TD自动

反汇编代码区的机器代码并显示对应的汇编指令。

每条反汇编指令的最左端是其地址,如果段地址与CS段寄存器的内容相同,则只显示字母“CS”和偏移量(CS:YYYY),

否则显示完整的十六进

制的段地址和偏移地址(XXXX:YYYY)。地址与反汇编指令之间显示的是指令的机器码。如果代码区当前光标所在指令引用了一个内存单元地址,

则该内存单元地址和内存单元的当前内容显示在CPU窗口顶部边框的右部,这样不仅可以看到指令操作码,还可看到指令要访问的内存单元的内容。

1.输入并汇编一条指令

有时我们需要在代码区临时输入一些指令。TD提供了即时汇编功能,允许用户在TD中直接输入指令(但直接输入的指令都是临时性的,不能保存

到磁盘上)。直接输入指令的步骤如下:

(1) 使用方向键把光标移到期望的地址处。

(2) 打开指令编辑窗口。有两种方法:一是直接输入汇编指令,在输入汇编指令的同时屏幕上就会自动弹出指令的

临时编辑窗口。二是激活代码

(3) 区局部菜单(见下一小节),选择其中的汇编命令,屏幕上也会自动弹出指令的临时编辑窗口。

(4) 在临时编辑窗口中输入/编辑指令,每输入完一条指令,按回车,输入的指令即可出现在光标处,同时光标自动

下移一行,以便输入下一条指

(5) 令。注意,临时编辑窗口中曾经输入过的指令均可重复使用,只要在临时编辑窗口中用方向键把光标定位到所

需的指令处,按回车即可。如果临时编辑

(6) 窗口中没有完全相同的指令,但只要有相似的指令,就可对其进行编辑后重复使用。

2. 代码区局部菜单

当代码区为当前区域时(若代码区不是当前区域,可连续按Tab或Shift-Tab键使代码区成为当前区域),按Alt-F10组合键即可激活代码区局部菜单,

代码区局部菜单的外观见图B.2。下面介绍一下各菜单项的功能。 ?

Goto(转到指定位置)

此命令可在代码区显示任意指定地址开始的指令序列。用户可以键入当前被调试程序以外的地址以检查ROM、BIOS、DOS及其它驻留程序。此命令

要求用户提供要显示的代码起始地址。使用Previous命令可以恢复到本命令使用前的代码区位置。 ?

Origin(回到起始位置)

从CS:IP指向的程序位置开始显示。在移动光标使屏幕滚动后想返回起始位置时可使用此命令。使用Previous命令可恢复到本命令使用前的代码区位置。

?

Follow(追踪指令转移位置)

从当前指令所要转向的目的地址处开始显示。使用本命令后,整个代码区从新地址处开始显示。对于条件转移指令(JE、JNZ、LOOP、JCXZ等),无

论条件满足与否,都能追踪到其目的地址。也可以对CALL、JMP及INT指令进行追踪。使用Previous命令可恢复到本命令使用前的代码区位置。

?

Caller(转到调用者)

从调用当前子程序的CALL指令处开始显示。本命令用于找出当前显示的子程序在何处被调用。使用Previous命令可恢复到本命令使用前的代码区位置。

?

Previous(返回到前一次显示位置)

如果上一条命令改变了显示地址,本命令能恢复上一条命令被使用前的显示地址。注意光标键、PgUp、PgDn不会改变显示地址。若重复使用本命令,

则在当前显示地址和前一次显示地址之间切换。 ?

Search(搜索)

本命令用于搜索指令或字节列表。注意,本命令只能搜索那些不改变内存内容的指令,如: PUSH DX

POP [DI+4] ADD AX,100

若搜索以下指令可能会产生意想不到的结果: JE 123

CALL MYFUNC LOOP 100

View Source(查看源代码)

?

本命令打开源模块窗口,显示与当前反汇编指令相应的源代码。如果代码区的指令序列没有源程序代码,则本命令不起作用。

?

Mixed(混合)

本命令用于选择指令与代码的显示方式,有三个选择: No 只显示反汇编指令,不显示源代码行。

Yes 如当前模块为高级语言源模块,应使用此选择。源代码行被显示在第一条反汇编指令之前。 Both 如当前模块为汇编语言源模块,应使用此选择。在有源代码行的地方就显示该源代码行,否则显示汇

编指令。

?

New CS:IP(设置CS:IP为当前指令行的地址)

本命令把CS:IP设置为当前指令所在的地址,以便使程序从当前指令处开始执行。用这种方法可以执行任意一段

指令序列,或者跳过那些

不希望执行的程序段。注意,不要使用本命令把CS:IP设置为当前子程序以外的地址,否则有可能引起整个程序崩溃。

?

Assemble(即时汇编)

本命令可即时汇编一条指令,以代替当前行的那条指令。注意,若新汇编的指令与当前行的指令长度不同,其后面机

器代码的反汇编显示会发生变化。

也可以直接在当前行处输入一条汇编指令来激活此命令。 ?

I/O(输入/输出)

本命令用于对I/O端口进行读写。选择此命令后,会再弹出下一级子菜单,如图B.6所示。子菜单中的命令解释如下: In byte(输入字节)

用于从I/O端口输入一个字节。用户需提供端口地址。 Out byte(输出字节)

用于往I/O端口输出一个字节。用户需提供端口地址。 Read word(输入字)

用于从I/O端口输入一个字。用户需提供端口地址。 Write word(输出字)

用于往I/O端口输出一个字。用户需提供端口地址。

图B.6 输入/输出子菜单

五、寄存器区和标志区的操作

寄存器区显示了CPU各寄存器的当前内容。标志区显示了八个CPU标志位的当前状态,表B.2列出了各标志位在该

区的缩写字母。 表B.2 标志区字母 标志位名称 进位(Carry) 全零(Zero) 符号(Sign) 溢出(Overflow) 奇偶(Parity) 辅助进位(Auxiliary carry) 中断允许(Interrupt enable) 方向(Direction) c z s o p a i d 1.寄存器区局部菜单

当寄存器区为当前区域时(若寄存器区不是当前区域,可连续按Tab或Shift-Tab键使寄存器区成为当前区域),按Alt-F10组合键即可激活寄存器

区局部菜单,寄存器区局部菜单的外观见图B.5。以下是各菜单项的功能。 ?

Increment(加1)

本命令用于把当前寄存器的内容加1。 ? Decrement(减1)

本命令用于把当前寄存器的内容减1。 ?

Zero(清零)

本命令用于把当前寄存器的内容清零。 ?

Change(修改)

本命令用于修改当前寄存器的内容。选择此命令后,屏幕上会弹出一个输入框,在输入框中键入新的值,然后回车,这个新的值就会取代原来

该寄存器的内容。

修改寄存器的内容还有一个更简单的变通方法,即把光标移到所需的寄存器上,然后直接键入新的值。 ?

Register 32-bit(32位寄存器)

按32位格式显示CPU寄存器的内容(缺省为16位格式)。在286以下的CPU或实方式时只需使用16位显示格式即可。

2.修改标志位的内容

用局部菜单的命令修改标志位的内容比较繁琐。实际上只要把光标定位到要修改的标志位上按回车键或空格键即可使标志位的值在0、1之间变化。

六、数据区的操作

数据区显示了从指定地址开始的内存单元的内容。每行左边按十六进制显示段地址和偏移地址(XXXX:YYYY)。若段地址与当前DS寄存器内容

相同,则显示“DS”和偏移量(DS:YYYY)。地址的右边根据“Display as”局部菜单命令所设置的格式显示一个或多个数据项。对字节(Byte)

格式,每行显示8个字节;对字格式(Word),每行显示4个字;对浮点格式(Comp、Float、Real、Double、Extended),每行显示1个浮点数;

对长字格式(Long),每行显示2个长字。

当以字节方式显示数据时,每行的最右边显示相应的ASCII字符,TD能显示所有字节值所对应的ASCII字符。 1.显示/修改数据区的内容

在默认的情况下,TD在数据区显示从当前指令所访问的内存地址开始的存储区域内容。但用户也可用局部菜单中的“Goto”命令显示任意指定地址

开始的内存区域的内容。TD还提供了让用户修改存储单元内容的功能,用户可以很方便地把任意一个内存单元的内容修改成所期望的值。但要注意,若

修改了系统使用的内存区域,将会产生不可预料的结果,甚至会导致系统崩溃。修改内存单元内容的步骤如下:

(1) 使用局部菜单中的“Goto”命令并结合使用方向键把光标移到期望的地址单元处(注意数据区的光标是一个下

划线)。

(2) 打开数据编辑窗口。有两种方法:

(3) 方法1:直接输入数据,在输入数据的同时屏幕上就会自动弹出数据编辑窗口。

(4) 方法2:激活数据区局部菜单(见下一小节),选择其中的“Change”命令,屏幕上也会弹出数据编辑窗

口。

(5) 在数据编辑窗口中输入所需的数据,输入完后,按回车,输入的数据就会替代光标处的原始数据。注意,数据

编辑窗口中曾经输入过的数据均可

(6) 重复使用,只要在数据编辑窗口中用方向键把光标定位到所需的数据处,按回车即可。

2.数据区局部菜单

当数据区为当前区域时(若数据区不是当前区域,可连续按Tab或Shift-Tab键使数据区成为当前区域),按Alt-F10组合键即可激活数据区局部菜单,

数据区局部菜单的外观见图B.3,下面给出各菜单项的功能描述。 ?

Goto(转到指定位置)

此命令可把任意指定地址开始的存储区域的内容显示在CPU窗口的数据区中。除了可以显示用户程序的数据区外,还可以显示BIOS区、DOS区、驻留

程序区或用户程序外的任一地址区域。此命令要求用户提供要显示的起始地址。 ?

Search(搜索)

此命令允许用户从光标所指的内存地址开始搜索一个特定的字节串。用户必须输入一个要搜索的字节列表。搜索从低地址向高地址进行。

?

Next(下一个)

搜索下一个匹配的字节串(由Search命令指定的)。 ?

Change(修改)

本命令用于修改当前光标处的存储单元的内容。选择此命令后,屏幕上会弹出一个输入框,在输入框中键入新的值,然后回车,这个新的值就会取代原

来该单元的内容。

修改存储单元的内容还有一个更简单的方法,即把光标移到所要求的存储单元位置上,然后直接键入新的值。

?

Follow(遍历)

本命令可以根据存储单元的内容转到相应地址处并显示其内容(即把当前存储单元的内容当作一个内存地址看待)。

此命令有下一级子菜单,如图B.7所 示。子菜单中的命令解释如下:

图B.7 遍历子菜单

Near code(代码区近跳转)

本子菜单命令将数据区中光标所指的一个字作为当前代码段的新的偏移量,使代码区定位到新地址处并显示新内容。 Far code(代码区远跳转)

本子菜单命令将数据区中光标所指的一个双字作为新地址(段值和偏移量),使代码区定位到新地址处并显示新内容. Offset to data(数据区近跳转)

本子菜单命令将光标所指的一个字作为数据区的新的偏移量,使数据区定位到以该字为偏移量的新地址处并显示。 Segment:Offset to data(数据区远跳转)

本子菜单命令将光标所指的一个双字作为数据区的新的起始地址,使数据区定位到以该双字为起始地址的位置并显示。

Base segment:0 to data(数据区新段)

本子菜单命令将光标所指的一个字作为数据段的新段值,使数据区定位到以该字为段址,以0为偏移量的位置并显示。

?

Previous(返回到前一次显示位置)

即把数据区恢复到上一条命令使用前的地址处显示。上一条命令如果确实修改了显示地址(如Goto命令),本命令才有效。注意,而光标键、

PgUp、PgDn键并不能修改显示起始地址。

TD在堆栈中保存了最近用过的五个显示起始地址,所以多次使用了Follow命令或Goto命令后,本命令仍能让用户返回到最初的显示起始位置。

?

Display as(显示方式)

本命令用于选择数据区的数据显示格式。共有8种格式,描述如下: Byte 按字节(十六进制)进行显示。

Word 按字(十六进制)进行显示。 Long 按长整型数(十六进制)进行显示。 Comp 按8字节整数(十进制)进行显示。 Float 按短浮点数(科学计数法)进行显示。 Real 按6字节浮点数(科学计数法)进行显示。 Double 按8字节浮点数(科学计数法)进行显示。 Extended 按10字节浮点数(科学计数法)进行显示。 ?

Block(块操作)

本命令用于进行内存块的操作,包括移动、清除和设置内存块初值、从磁盘中读内容到内存块或写内存块内容到磁盘中。本命令有下一级子菜单,

如图B.8所示。子菜单中的命令解释如下:

图B.8 内存块操作子菜单

Clear(块清零)

把整个内存块的内容其全部清零,要求输入块的起始地址和块的字节数。 Move(块移动)

把一个内存块的内容复制到另一个内存块。要求输入源块起始地址、目标块起始地址和源块的字节数。 Set(块初始化)

把整个内存块内容设置为指定的同一个值。要求输入起始地址、块的字节数和所要设置的值。 读取(Read)

读文件内容到内存块中。要求输入文件名、内存块起始地址和要读的字节数。 写入(Write)

写内存块内容到文件中。要求输入文件名、内存块起始地址和要写的字节数。

七、堆栈区的操作

当堆栈区为当前区域时(若堆栈区不是当前区域,可连续按Tab或Shift-Tab键使堆栈区成为当前区域),按Alt-F10组合键即可激活堆栈区局部菜单,

堆栈区局部菜单的外观见图B.4。堆栈区局部菜单中各菜单项的功能与数据区局部菜单的同名功能完全一样,只是其操作对象为堆栈区,故此不再赘述。