1、第2章 机器语言程序的建立与执行,2.1 机器语言程序 2.2 实际地址值的确定 2.3 DEBUG的特殊性质及应用 2.4 机器语言程序的建立与调试,2.1 机器语言程序,本节介绍两个程序范例,第一个程序范例是将指令所定义的“立即型”数据传送入寄存器内,然后进行算术运算,第二个程序范例是使用单独定义的方法将数据定义在数据段中。经过追踪这些指令的执行,你可以深入了解微型计算机的动作状态以及各寄存器所扮演的角色。,2.1.1 启动DOSDEBUG程序是在DOS环境下工作的软件。若计算机同时装有两个操作系统(Windows系统和DOS系统),当系统在Windows环境下工作时,用鼠标左键单击“开始
2、”按钮,在弹出的主菜单中单击“关闭系统”项,弹出“关闭Windows”菜单,选择其中的“重新启动计算机并切换到MS-DOS”项并回答“是”,即可启动DOS。,若计算机仅装有Windows操作系统,开机时,首先将DOS系统磁盘插入A驱动器,若此时电源关闭,则将电源接通;若电源已经启动,可同时按下Ctrl、Alt与Del键,以热启动方式启动计算机,即可用A盘启动DOS。,2.1.2 检查存储器内容的方法第一个练习是,使用DOS DEBUG程序检查存储器被选择地址单元的内容。键入DEBUG然后回车,即可启动DEBUG程序。此时系统会将DEBUG程序从磁盘装入到内存储器,并且执行。之后,屏幕会出现DE
3、BUG的提示符(-)。此提示符表示DEBUG等待接受用户的命令(DEBUG 命令)。此练习只用到D命令,它的功能是显示存储器单元的内容。,1. 存储器的容量机器的存储器容量值存放在物理地址是十六进制00413与00414的存储单元中。在DEBUG环境下,你可以观察此地址处的内容,它是以段的起始地址与偏移地址配合的方法来查看的。例如:(1) 十六进制00400是段起始位置的地址,而你只能键入0040,因为最后一位数字已假设为0。,(2) 13是相对于段起始位置的偏移地址(差距值)。因此,只要键入下列字符串就可看到本机存储器的容量:D 0040:13 并按下Enter键在屏幕上所表示的前两个字节就
4、是存储器的容量,此十六进制数值是以字节反向的顺序出现的,且其单位为K字节即KB。表2-1列举了一些可能出现的反向十六进制数(Reversed Hex)、正确十六进制数,以及其等价的十进制数。,表2-1 反向十六进制、正确十六进制与十进制,2. 序列号微型计算机的序列号是存放于ROM存储器中的,其实际位置的地址为FE000。你只要键入下列字符串就可以看到它的内容:D FE00:0 并按下Enter键此时,屏幕上会显示出一个7位数的数字,其后面跟着版权和日期(Copyright Date)。,3. ROM BIOS日期ROM BIOS日期是存放于位置FFFF5中的,它的表示格式为mm/dd/yy。
5、键入:D FFFF:05 并按下Enter键就可看到ROM BIOS的日期,据此你可以判断出微型计算机的机型及其机龄。注意:上述三个例子均是早期PC机的存储器容量、序列号以及ROM BIOS日期在内存中的映像。它们可能与你所使用的现代机型不符合,但它不会影响你对D命令的使用和对内存单元内容的观察。,到目前为止,你已知道如何使用显示存储器内容的DEBUG命令,并可以正确地设定内存的任何单元的位置(地址),以观察它的内容。你也可以重复地键入D命令,可以不带参数,而逐步地观察存储单元的内容。当你想要退出DEBUG回到DOS的控制下时,只要键入Q然后回车就可以了。接下来,我们利用DEBUG来直接输入程
6、序到内存储器中,并追踪它的执行过程。,2.1.3 机器语言范例1立即型数据运算本范例的目的是说明如何将一个机器语言程序输入到内存储器中,以及对其执行的过程。下列机器语言程序操作是以十六进制格式进行的。机器指令码 注释B82301 ;把0123传送入AX寄存器052500 ;把0025加入AX寄存器,89C3 ;把AX的内容传送入BX 01C3 ;把AX的内容加入BX 89D9 ;把BX的内容传送入CX 29C1 ;把CX的内容减去AX的内容 29C0 ;AX减去AX(AX清0) 90 ;没有运算(不做任何操作) 90 ;但PC+1PC,你也许已注意到每条机器指令的长度是不一样的(有一个、两个或
7、三个字节),而且是以一条指令跟着一条指令的格式存放在内存储器中的。程序从第一条指令开始执行,然后逐步地执行直至完成。目前可以暂时不管机器指令中的操作码所代表的意义。例如,在某种情况下MOV(传送数据)是十六进制B8,而在另一种情况下MOV则为十六进制89。,此程序可以直接输入到存储器中,而且可以一次一条指令逐步地执行。同时在每一条指令执行后,你可以观察到诸寄存器的内容。依照前一节的方法将DEBUG程序装入内存储器中并执行,此时屏幕上会出现一个DEBUG的提示符(-)。若要输出打印这个练习程序,可先打开打印机电源,同时按下Ctrl与P键即可成功连接打印机。,键入下面的命令,就可以直接将机器语言程
8、序存入内存(命令中字节与字节之间有一个空格):E CS:100 B8 23 01 05 25 00 按下Enter键DEBUG的命令E代表输入,CS:100表示指令所要存入的存储单元位置指令段开始后的第100H(256)个字节,这是在DEBUG环境下的机器指令码存放的正常起始位置地址。E命令每次存入两位十六进制数字(一个字节)到存储器的存储单元内。,范例1中,它存放的地址是从CS:100到CS:105,共6个字节。下一个命令为:E CS:106 89 C3 01 C3 89 C9 按下Enter键此命令可从CS:106经107、108、109、10A至10B存入6个字节。最后一个存入命令是:E
9、 CS:10C 29 C1 29 C0 90 90 按下Enter键,此命令可从CS:10C开始经10D、10E、10F、110至111存入个字节。现在你已经存入了第一个机器语言程序。在执行之前先核对输入的资料(机器指令码)是否正确,若发现错误改正过来即可。执行这些指令是很简单的。图2-1显示了所有步骤(包括命令)。屏幕上所显示出的内容将与你所键入的DEBUG命令产生的结果一样。,C:DEBUG -E CS:100 B8 23 01 05 25 00 -E CS:106 89 C3 01 C3 89 D9 -E CS:10C 29 C1 29 C0 90 90 -R AX=0000 BX=00
10、00 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0100 NV UP EI PL NZ NA PO NC 1268:0100 B82301 MOV AX,0123,-T AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0103 NV UP EI PL NZ NA PO NC 1268:0103 052500 ADD AX,0
11、025 -T AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0106 NV UP EI PL NZ NA PE NC 1268:0106 89C3 MOV BX,AX,-T AX=0148 BX=0148 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0108 NV UP EI PL NZ NA PE NC 1268:0108
12、 01C3 ADD BX,AX -T AX=0148 BX=0290 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=010A NV UP EI PL NZ AC PE NC 1268:010A 89D9 MOV CX,BX,-T AX=0148 BX=0290 CX=0290 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=010C NV UP EI PL NZ AC PE
13、NC 1268:010C 29C1 SUB CX,AX -T AX=0148 BX=0290 CX=0148 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=010E NV UP EI PL NZ AC PE NC 1268:010E 29C0 SUB AX,AX,-T AX=0000 BX=0290 CX=0148 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0110 NV UP EI
14、PL ZR NA PE NC 1268:0110 90 NOP -,图2-1 机器语言范例1的追踪,只要键入R命令再按Enter键即可观察诸寄存器与标志寄存器的内容。此时,DEBUG会以十六进制的格式提示所有寄存器的内容,例如:AX=0000,BX=0000,因为DOS版本的不同,所以在屏幕上的段寄存器内容可能与图2-1所显示的结果不相同。指令指针寄存器IP=0100表示指令从指令段起始位置地址后的第100H字节开始执行,这就是为什么要求以E CS:100命令作为存入程序的起始位置地址的原因。,图2-1中的标志寄存器显示了下列标志的设定:NV UP EI PL NZ NA PE NC当前这些标
15、志位的意义分别为:NV没有溢出,UP地址值的变化是增值向上(右)方向,EI中断允许,PL正号,NZ非0,NA没有辅助进位,PE奇校验,NC没有进位。,R命令同时也显示出位于偏移地址0100处的第一条待执行的指令。注意,图2-1中的CS寄存器内容是CS=1268(你的机器也许不一样),且指令如下所示:1268:0100 B82301 MOV AX,0123(1) CS=1268表示指令段的起始位置地址在1268(实际的物理地址值是12680)。1268:0100表示紧接着在CS位置地址12680后的100(十六进制)个字节的位置。(2) B82301是你输入在CS:100位置地址处的机器指令码,
16、B8是操作码,2301是立即数。,(3) MOV AX,0123是机器指令码的汇编语言助记符指令形式。这是“反汇编”操作的结果,“反汇编”是指将机器指令码翻译成汇编语言符号指令形式。利用DEBUG能使你更容易地理解此机器指令程序。在以后的章节中,你将学习到如何使用汇编语言的符号指令独立地编写程序。目前这条汇编语言指令的意思是,把立即数0123移入AX寄存器内。,此时,指令MOV AX,0123尚未执行。为了执行此指令,可键入T(代表Trace)命令并按Enter键。T命令执行之后,DEBUG同时显示各寄存器、标志寄存器的内容,以及下一条待执行的指令。请注意,此刻AX的内容为0123。操作码B8
17、的功能是将紧接着的2301移入AX寄存器。此操作是把23移入AX寄存器的低字节AL,把01移入寄存器的高字节AH,即AX:| 01 | 23 |,IP寄存器的内容是0103,它指示出指令段中下一条待执行指令的位置地址,即1268:0103 052500 ADD AX,0025为了执行这条指令,再键入一个T命令。此条指令把25加到AX的低字节AL,而把00加到AX的高字节AH,整体而言是将0025加入AX中,此刻AX的内容为0148,而IP的内容为0106。,再键入一个T命令,指令会把AX的内容移入BX寄存器内目前BX的内容为0148。因为MOV操作只是将数据从一个位置拷贝到另一个位置,所以AX
18、的内容仍然是0148。逐步地键入T命令,可以执行其余的指令。下一条指令是将AX的内容加至BX中,使得BX的内容变成0290。然后把BX的内容移入CX,再将CX的内容减去AX的内容,并使AX减去AX本身的内容。在AX减AX的运算之后,0标志位会从NZ(非0)改变成ZR(0),以指示运算结果为0。,你可以继续键入T命令,执行最后的两条指令(NOP与NOP),但它们并无任何意义,只是使IP增值,使指令可以连续执行。若你想观看指令段中的机器语言程序,可以键入下面的显示内存命令:D CS:100按下Enter键在80列宽的屏幕中,DEBUG会在每行的左半部提示16个字节的十六进制数字。而其右半部则是AS
19、CII表示法(即为可显示出的码)。就机器指令码而言,ASCII表示法是没有意义的。在以后的章节中,对右边的显示会有更详细的讨论。,图2-2列出了命令D CS:100所操作的部分结果。只要看你自己的机器指令分布,从CS:100至CS:111的机器码即可,而紧接在这些机器指令码之后的存储单元内容则是随机的。, -D CS:100 1268:0100 B8 23 01 05 25 00 89 C3-01 C3 89 D9 29 C1 29 C0 .#%.).). 1268:0110 90 90 CA 74 0B 88 05 47-41 AC 3C 22 34 00 57 12 .t.GA.up8.u
20、&. ,图2-2 机器语言范例1指令段的显示,显示的第一行是从100开始,表示位置地址CS:100至CS:10F共16个字节的内容。第二行表示位置地址CS:110至CS:11F共16个字节的内容。虽然你的程序结束点位于CS:111,但显示命令会自动地显示8行,从CS:100到CS:170。若你想再一次重新执行这些指令,可以使用R命令重新设置IP寄存器的值,再逐步地追踪这些指令的执行。按Q键(代表Quit)可以退出DEBUG,返回到DOS,并显示DOS提示符A或C。,2.1.4 机器语言范例2 数据的定义前一范例中参与运算的数是直接定义在指令中的,即MOV和ADD指令中的立即数0123H和002
21、5H。下面将列举另外一个类似的程序例子,它在数据段内定义了两个字 0123H与0025H。通过此例子的工作过程,你将能更深入地观察到微型计算机是如何借助DS寄存器与偏移地址(差距值)来存取数据的。,本例子所定义的数据区如下所示:数据段地址 十六进制值 占用的单元DS:0000 2301 0,1DS:0002 2500 2,3DS:0004 0000 4,5DS:0006 2A2A2A 6,7,8由于一个十六进制数字占半个字节,所以本例子中的23存于数据段中的第0个单元(第1个字节),01存于第1个单元(第2个字节)。,指令段中的机器指令码,对这些数据有如下的操作功能: 机器指令码 注释 A10
22、000 ;从DS位置地址0000处开始搬移一个字到AX寄存器中 03060200 ;把DS 位置地址0002处开始的字内容加到AX寄存器中 A30400 ;把AX寄存器的内容搬到DS位置地址0004处开始的字中 90 ;空操作 90 ;空操作,你也许已经注意到有两条传送指令(MOV)具有不同的机器指令操作码A1与A3。机器指令的操作码,是依据所用到的寄存器、字节(或字)的数目、数据传送的方向,以及所用到的立即数据或存储单元等而进行编码的。你可以再次利用DEBUG输入此程序并观察其执行过程。当DEBUG发出其提示符(-)时,表示它已准备好接受你输入的DEBUG命令了。,首先利用E命令以键入数据到
23、数据段:E DS:00 23 01 25 00 00 00 并按下Enter键E DS:06 2A 2A 2A 并按下Enter键,第一个E命令存储了6个字节到数据段的起点处(DS:00)。注意你必须以字节反向的方式输入字操作数,使得0123是2301,而0025是2500。当用一条MOV指令存取这些字到寄存器时,它再把这些字反向处理,使得2301变成0123,2500变成0025。第二个E命令输入3个星号,这些存储于数据段中的星号不提供任何作用。只是以后你用显示内存单元内容命令(D)时,提示你可以很方便地观察到它们(参见图2-4)。,此刻,再一次从CS:100处开始把指令存入指令段中:E C
24、S:100 A1 00 00 03 06 02 00 并按下Enter键E CS:107 A3 04 00 90 90 并按下Enter键现在这些指令已存于存储器中位置为CS:100到CS:10B处。你可以用范例1所使用的方法来执行这些指令。,图2-3列出了包含E 命令的所有步骤。只要键入下列命令,你就可以观看存储在数据段中的数据与指令段中的指令码:查看数据段:D DS:00 并按下Enter键查看指令段:D CS:100 并按下Enter键把你所键入的这两段内容与图2-3比较,DS:00 至08与CS:100至10B的内容将与图2-3相同。,C:DEBUG -E DS:00 23 01 25
25、 00 00 00 -E DS:06 2A 2A 2A -E CS:100 A1 00 00 03 06 02 00 -E CS:107 A3 04 00 90 90 -R AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0100 NV UP EI PL NZ NA PO NC 1268:0100 A10000 MOV AX,0000 DS:0000=0123,-T AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE
26、BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0103 NV UP EI PL NZ NA PO NC 1268:0103 03060200 ADD AX,0002 DS:0002=0025 -T AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=0107 NV UP EI PL NZ NA PE NC 1268:0107 A30400 MOV 0004,AX DS:0004=
27、0000,-T AX=0148 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1268 ES=1268 SS=1268 CS=1268 IP=010A NV UP EI PL NZ NA PE NC 1268:010A 90 NOP -,图2-3 机器语言范例2机器指令的追踪,现在,按R键以查看寄存器与标志寄存器的内容,并显示第一条待执行指令。各寄存器的内容与范例1中的相同,所显示的指令为:1268 :0100 A10000 MOV AX,0000CS寄存器的内容为1268,而CS:0100存放着第一条机器指令码(A100
28、00)。DEBUG将此指令解释为MOV(传送),而且它是取数据区中的第一位置0000内的数据。方括号是告诉汇编程序它是一个偏移地址(差距值),而非一个立即数。把立即数移入AX寄存器的汇编语言指令应该为:MOV AX,0000,现在键入DEBUG T命令,执行MOV AX,0000指令会将数据段偏移地址为0的位置处所存放的字内容移入AX寄存器。此字的内容为2301,经过反向操作后,AX 的内容为0123。下一条指令为ADD,执行此指令会把DS:0002中的字内容加入 AX 寄存器中,所以AX的内容变成0148(即0123与0125之和)。,下一条指令是MOV 0004,AX。同样,只要键入T 命
29、令即可执行。此条指令是将AX寄存器的内容移入距DS:0000偏移地址为0004的位置。为了查看数据段被改变的内容,你可以键入D DS:00命令,前9个字节为:数据区段的内容: 23 01 25 00 48 01 2A 2A 2A 偏移地址(差距值): 00 01 02 03 04 05 06 07 08,0148是从AX寄存器中以反向顺序的方式(4801),移入偏移地址为04与05位置的字。请注意,这些十六进制值也以ASCII码的形式显示在右边。例如,十六进制23产生了一个符号(),十六进制25产生一个符号(%),十六进制48产生一个字母(H),而3个十六进制值2A则产生三个星号(*)。屏幕左
30、边显示了在存储器中的实际机器指令码,而屏幕右边只是帮助你更容易地找到文字数据的位置,范例2数据段内容如图2-4所示。, -D DS:0 1268:0000 23 01 25 00 48 01 2A 2A-2A F0 4F 03 F1 0C 8A 03 #.%.H.*.O. 1268:0010 F1 0C 17 03 F1 0C 10 0B-01 01 01 00 02 FF FF FF ,图2-4 范例2数据段内容,同样地,只要键入D CS:00命令就可以查看指令段的内容。最后键入Q命令以结束DEBUG的工作。,2.2 实际地址值的确定,在指令段,微处理器将CS10H,加上IP寄存器的内容(偏
31、移地址),计算出机器指令存放在内存的实际地址(称为物理地址),然后根据此地址去取机器指令码,然后分析并执行。例如,假设CS寄存器的内容为十六进制04AF(实际上是04AF0),且IP寄存器的内容为十六进制0023,其物理地址为:,CS: 04AF0IP:+ 0023指令地址: 04B13 (物理地址) 在数据段,假设以物理地址为十六进制04B13开始,存储的指令如下所示:A1 12 00 MOV AX,0012物理地址: 04B13 04B14 04B15,其中存储器地址为04B13处存放了指令的第一个字节,它是指令的操作码,微处理器从操作码(A1)得知指令长度为3个字节。为了存取位于偏移地址
32、0012的数据项,微处理器将DS10H,加上指令中提供的偏移地址0012,计算出被操作数的地址。若DS寄存器的内容为十六进制值04B1(实际上是04B10),则数据项的物理地址为:,DS: 04B10偏移地址(差距值): + 0012物理地址: 04B22 假设地址04B22与04B23中的内容如下所示:存储器单元的内容: 24 01存储器的物理地址:04B22 04B23,微处理器从地址04B22取出24,并将其存入AL寄存器,而从地址04B23取出01,并将其存入AH寄存器,现在AX的内容为0124。另外,当微处理器取出指令码的每一个字节时,IP寄存器的内容会递增,即自动加1,结果使它含有
33、下一条待执行指令的偏移地址(0026)。,1. 偶数地址如果被存取字的地址是偶数,则8086、80286以及80386微处理器的操作效率会更高。在前面例子的指令段中,微处理器可以直接存取位于04B22地址的字,并将其移入AX寄存器中。但如果所要存取的字的起始地址为奇数时,则微处理器就必须执行两次存取操作。例如,假设指令要存取一个起始地址为04B23的字,并将其移入AX寄存器,则操作如下:,存储器单元的内容:,04B22 04B23 04B24 04B25,存储器的物理地址:,微处理器首先存取位于地址04B22与04B23地址中的字节,将04B23地址中的字节移入AL寄存器。然后存取位于地址04
34、B24与04B25中的字节,再把地址04B24中的字节移入AH寄存器。所以AX的内容为0124。,对于数据的物理地址,你无需在程序中做任何处理,也不必知道它是否为奇数地址。你所应理解的是:存取操作是以反向顺序从存储器中取出一个字到16位寄存器,使得它能重获正确顺序;若有一段重复存取存储器字的程序,为了提高效率,你可以把数据栏的起始地址定义成偶数地址。因为数据栏的起始地址是在偶数地址上,所以第一个数据起始地址为偶数。而且只要往后的数据皆定义成字,则这些数据都会在偶数地址上。就大多数的应用而言,由于微处理器的执行速度很快,因此你无法感觉到其效率的提高。,2.3 DEBUG的特殊性质及应用,在DOS
35、操作系统的环境下,你可以利用DEBUG输入汇编语言符号指令与机器语言指令。2.3.1 A命令DEBUG的A命令是汇编命令,它告诉DEBUG开始接受汇编语言符号指令,并将它们转换成机器指令。使用A命令时要带参数,以设定输入指令的起始地址,方法如下:A 100并按下Enter键,DEBUG会显示指令段和其偏移地址,其格式为xxxx:100。然后键入每一条指令并按下Enter键。当你输入完程序后,再次按下Enter键,可退出A命令。试着输入下列程序:MOV AL,25 并按下Enter键MOV BL,32 并按下Enter键ADD AL,BL 并按下Enter键NOP 并按下Enter键,完成之后,
36、屏幕会提示下列的内容: xxxx: 0100 MOV AL , 25 xxxx: 0102 MOV BL , 32 xxxx: 0104 ADD AL , BL xxxx: 0106 NOP xxxx: 0107,此刻,再按下Enter键即可结束键入符号指令的操作。从屏幕的提示可以看出DEBUG已经决定了每一条指令的起始位置即地址。但在执行此程序之前,应先检查所产生的机器指令,确认刚输入的汇编语言指令没有差错。,2.3.2 U命令用DEBUG的U命令,就可以检查你所输入的符号指令或机器指令是否正确。DEBUG的U命令是反汇编命令,是将机器指令反汇编成为汇编语言的助记符指令。使用U命令时,你必须
37、告诉DEBUG,你想看到的第一条指令与最后一条指令的地址。上例中分别为100与106。键入:U 100,106并按下Enter键,屏幕将会提示下列内容: xxxx: 0100 B025 MOV AL , 25 xxxx: 0102 B332 MOV BL , 32 xxxx: 0104 00D8 ADD AL , BL xxxx: 0106 90 NOP,下面开始执行程序。首先键入R命令以显示所有寄存器的内容与第一条指令,然后键入T命令以追踪这些指令的执行。到目前为止,你已知道如何以机器语言及汇编语言输入一段程序。当你不知道指令机器码时,一般是以汇编语言的形式来输入的,而当执行阶段中需要修改程
38、序内容时,一般是以机器码的形式来输入的(E命令),这样比较快速。,2.3.3 在DEBUG中存储一个程序在下列两种情况下,你可能要使用DEBUG存储一个程序到磁盘中。1. 用DEBUG输入一个小程序且你要将它存入磁盘 (1) 装入DEBUG程序。(2) 使用A命令或E命令建立此程序。(3) 对此程序命名:N 文件名.COM并按下Enter键。此文件的扩展名必须为.COM。例如:-N L23.COM,(4) 修改寄存器CX的内容为程序的长度。(5) 使用U命令你可以知道程序的结束点,所以你要告诉DEBUG此程序的长度,在前面例子中,最后一条指令为:xxxx:0106 90 NOP最后一条指令的长
39、度为一个字节,所以程序的长度为106(程序的结束点)减去100(程序的起始点)再加1,其结果为7。(6) 键入R CX并按下Enter键,准备修改CX的内容。DEBUG回复:CX 0000,(7) 此时,你输入程序的长度7,所以CX的内容变成7。(8) 存储此程序:W并按下Enter键。DEBUG会提示:“Writing 0007 bytes”。(9) 返回DOS,用DIR命令可以观察到你所存储的文件名L23.COM。,2. 读取一个程序、修改它并将它存入磁盘(1) 将此程序读入内存:DEBUG 文件名.COM并按下Enter键。(2) 使用U命令检查程序内容,并以E命令或A命令来输入需修改的
40、内容。(3) 修改寄存器CX的内容为程序的长度。,(4) 将修正过的程序写入磁盘:W并按下Enter键。对以上两种方法,DEBUG都会提示:“Writing nnnn bytes”。若此数值为0,表示你未能存入此程序,再试一次。若你使用的机器是80586以上的微处理器,则必须将BX清为0000,因为它是以BX:CX来记录程序长度的。,2.4 机器语言程序的建立与调试,这一节是对本章内容的练习,通过练习与操作,使你进一步认识CPU各寄存器的作用,深入了解8086/8088存储器的管理方式,帮助你学习使用DEBUG调试程序。,练习中所使用的DEBUG命令如下: E 修改内存单元内容命令 D 显示内
41、存单元内容命令 A 汇编命令 U 反汇编命令 R 检查和修改寄存器内容命令 T 程序追踪命令 Q 退出DEBUG状态命令,2.4.1 练习一:机器语言程序的建立与调试请注意:DEBUG环境下任何数据、信息均默认为十六进制。1. 参考程序 机器指令码 汇编语言指令 注 释B8 23 01 MOV AX, 0123 ;0123AX 05 25 00 ADD AX, 0025 ;AX+0025AX,89 C3 MOV BX, AX ;AXBX 01 C3 ADD BX, AX ;BX+AXBX89 D9 MOV CX, AX ;AXCX29 C1 SUB CX, AX ;CXAXCX29 C0 SU
42、B AX, AX ;AXAXAX90 NOP ;空操作90 NOP ;空操作,2练习步骤第一步:用D命令显示CS:0100处的内容。显示 操作,显示: 1573:0100 B9 04 01 AC 3C 0D 74 23-3C 22 75 05 80 F2 01 EB .t#“u. 1573:0110 F2 0A D2 75 19 E8 FF FA-74 11 3A 06 34 00 62 15 .ut.:.4.b.,上面的显示中,1573为CS寄存器的值,即指令段的开始。0100为指令段的偏移地址,因此,指令段的物理地址为:指令段的起始地址: 15730指令段的偏移地址: + 0100指令段的
43、物理地址: 15830 B9为偏移地址0100(物理地址为15830)单元的内容,04为偏移地址0101(15831)单元的内容。,第一行所显示内容对应的地址范围是0100010F,共16个字节。第二行所显示内容对应的地址范围是0110011F,共16个字节。其余依次类推,D命令共显示8行,共168=128个字节的内容。最右面的显示是该单元内容所对应的ASCII码字符,若该单元内容无对应的ASCII码字符时则显示“”。第二步:用E命令修改CS:0100开始单元的内容,即装入机器语言程序。显示 操作,本次操作输入了第1、2条机器指令码,共6个字节。所占用的地址为CS:0100CS:0105。继续
44、修改:显示 操作,本次操作输入了第35条机器指令码,共6个字节。所占用的地址为CS:0106CS:010B。继续修改:,显示 操作,本次操作输入了第69条机器指令码,共6个字节。所占用的地址为CS:010CCS:0111。第三步:用反汇编命令,将输入的机器指令码用反汇编指令反汇编为汇编语言指令助记符的形式,用以检查输入机器指令码过程中是否有误操作。显示 操作,显示: 1573:0100 B82301 MOV AX,0123 1573:0103 052500 ADD AX,0025 1573:0106 89C3 MOV BX,AX 1573:0108 01C3 ADD BX,AX 1573:01
45、0A 89D9 MOV CX,BX 1573:010C 29C1 SUB CX,AX 1573:010E 29C0 SUB AX,AX 1573:0110 90 NOP 1573:0111 90 NOP,改错:例如,若发现29 C1(SUB CX,AX)误操作成为29 C0(SUB AX,AX),则会显示为:SUB AX,AX SUB AX,AX修改操作如下:显示 操作,重复第三步操作直到程序输入正确为止。第四步:追踪指令执行前用R命令检查IP的值是否等于0100。因为程序指令是从0100位置处开始存放的。显示 操作,显示: AX=0000 BX=0000 CX=0000 DX=0000 SP
46、=FFEE BP=0000 SI=0000 DI=0000 DS=1573 ES=1573 SS=1573 CS=1573 IP=0100 NV UP EI PL NZ NA PO NC 1573:0100 B82301 MOV AX,0123,AX=0000IP=0100显示CPU当前所有寄存器的内容。NV、UP、EI、PL、NZ、NA、PO、NC是CPU标志寄存器的状态。这些标志位的意义分别为:NV没有溢出,UP向上(右)方向,EI中断允许,PL正号,NZ非0,NA没有辅助进位,PO奇数位,NC没有进位。,R命令同时也显示出偏移地址0100处一条待执行的指令。注意,本例显示CS=1573(
47、你的机器可能不同)。显示如下:1573:0100 B8 23 01 MOV AX,0123(1) CS=1573表示指令段的起始位置,物理地址为15830。(2) 0100表示指令段的偏移地址。(3) B8 23 01是输入到CS:01000102的指令机器码。(4) MOV AX, 0123是B8 23 01机器指令码的助记符形式即汇编语言指令。,第五步:单步追踪指令的执行。执行MOV AX, 0123即B8 23 01,也就是当前IP指令指针寄存器所指的指令,使用的是T命令。显示 操作,显示: AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1573 ES=1573 SS=1573 CS=1573 IP=0103 NV UP EI PL NZ NA PO NC 1573:0103 05 25 00 ADD AX,0025,