汇编网首页登录博客注册
goal00001111的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
  •  --
  • 『姓名』:                    
  • 『性别』:保密  『发送消息
  • 个人说明:当飞鸟失去飞翔的欲望,翅膀也会变成累赘;
    当理想与激情共舞,凡人也能成为英雄.
  • 详细信息『加为好友』
学习动态
好友圈

[2007-10-24 13:47] 学习笔记:调试程序debug常用指令的使用(1)

调试程序debug常用指令的使用
Debug原意是杀虫子。这里是可用于测试和调试 MS-DOS 可执行文件的程序。
DEBUG是为汇编语言设计的一种调试工具,它通过单步执行、设置断点等方式为汇编语言程序员提供了非常有效的程序调试手段。DEBUG可以直接用来检查和修改内存单元、装入、存储及启动运行程序、检查及修改寄存器,也就是说DEBUG可深入到计算机的内部,可使用户更紧密地与计算机中真正进行的工作相联系。不仅如此,对汇编语言初学者来说,DEBUG也是练习使用汇编指令的一种有效工具。初学者可以直接在DEBUG环境下执行汇编指令。然而,在DEBUG下运行汇编语言源程序也受到了一些限制,它不宜汇编较长的程序,不便于分块程序设计,不便于形成以DOS外部命令形式构成的 .EXE文件,不能使用浮动地址,也不能使用ASM和MASM提供的绝大多数伪指令。
启动DEBUG的一般命令如下:
Debug [[drive:][path] filename  [parameters]] 
其中参数 [drive:][path] filename 指定要测试的可执行文件的位置和名称;参数parameters 指定要测试的可执行文件所需要的任何命令行信息。 
         被调试的文件可以是系统中的任何文件,但通常它们的后缀为EXE或COM。
当DEBUG启动成功后,将显示连接符“-”,这时,可输入各种命令。

  Debug 命令列表: 
  ? 显示 Debug 命令列表。 
  a 汇编 8086/8087/8088 记忆码。 
  c 比较内存的两个部分。 
  d 显示部分内存的内容。 
  e 从指定地址开始,将数据输入到内存。 
  f 使用指定值填充一段内存。 
  g 运行在内存中的可执行文件。 
  h 执行十六进制运算。 
  i 显示来自特定端口的 1 字节值。 
  l 将文件或磁盘扇区内容加载到内存。 
  m 复制内存块中的内容 
  /n 为 l 或 w 命令指定文件,或者指定正在测试的文件的参数。 
  o 向输出端口发送 1 个字节的值。 
  p 执行循环、重复的字符串指令、软件中断或子例程。 
  q 停止 Debug 会话。 
  r 显示或改变一个或多个寄存器。 
  s 在部分内存中搜索一个或多个字节值的模式。 
  t 执行一条指令,然后显示所有寄存器的内容、所有标志的状态和 Debug 下一步要执行的指令的解码形式。 
  u 反汇编字节并显示相应的原语句。 
  w 将被测试文件写入磁盘。 
  xa 分配扩展内存。 
  xd 释放扩展内存。 
  xm 映射扩展内存页。 
xs 显示扩展内存的状态。

关于参数的几点说明:
1、进制:在DEBUG中输入或显示的数据都是十六进制形式;
         2、分隔:命令和参数、参数和参数之间要用空格、逗号或制表符等分隔;
3、地址:用“段值:偏移量”的形式来表示地址,也可用段寄存器来代表“段值”;例如:1000:0,ds:10,cs:30等;
4、范围:用来表示地址范围,从哪个地址开始,到哪个地址结束。它有二种表示方式:
地址 地址——前者表示起始地址,要用“段值:偏移量”来表达,后者表示终止地址,只用“偏移量”来表示;
地址 长度——前者表示起始地址,要用“段值:偏移量”来表达,后者表示该区域的大小,用字母’L’开头的数值来表示。
例如:100:50 100——段值为100,偏移量从50到100的内存区域,
100:50 L100——段值为100,偏移量从50开始的100个字节区域。
5、端口地址:二位十六进制数值;
6、字节值:二位十六进制数值;
7、字节值表:由若干个字节值组成,也可以是用引号括起来的字符串;
8、驱动器号:0—驱动器A、1—驱动器B、2—驱动器C、3—驱动器D等。

关于使用命令的几点说明:
         在DEBUG中的提示符“-”下才能输入命令,在按“回车”键后,该命令才开始执行; 
         命令是单个字母,命令和参数的大小写可混合输入; 
         可用F1、F2、F3、Ins、Del和光标移动键等来编辑本行命令; 
         当命令出现语法错误时,将在出错位置显示“^ Error” ;
         可用^C或^Break来终止当前命令的执行,还可用^S来暂停屏幕显示(当连续不断地显示信息时)。

Debug 命令详解:
1.寄存器命令R:
R(Register)命令用于显示和修改处理器的寄存器,它有三种格式。
格式1:R   ;显示所有寄存器的值和标位的状态
例如,当我们刚进入Debug时,就可以执行该命令,显示示例如下: 
C:\>debug
-r;显示所有寄存器的值和标位的状态
AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=0AF2  IP=0100   NV UP EI PL NZ NA PO NC
0AF2:0100 89D8          MOV     AX,BX
-
其中,前两行给出所有寄存器的值,包括各个标志状态。最后一行给出了当前CS : IP处的指令;由于这是一个涉及数据的指令,这一行的最后还给出相应单元的内容。
格式2:R 寄存器名;显示和修改指定寄存器
例如,键入“r ax”,Debug给出当前AX内容,冒号后用于输入新数据,如不修改则按Enter键。
    格式3:RF    ;显示和修改标志位
Debug将显示当前各个标志位的状态。显示的符号及其状态如下所示,用户只要输入这些符号就可以修改对应的标志状态,键入的顺序可以任意。如不修改则按Enter键。
进位标志CF:1(CY), 0(NC);
奇偶标志PF:1(PE), 0(PO);
辅助进位标志AF:1(AC), 0(NA);
零标志ZF:1(ZR), 0(NZ);
符号标志:1(NG), 0(PL);
溢出标志OF:1(OV), 0(NV);
中断允许标志IF:1(EI),0(DI);
方向标志DF:1(DN)时,0(UP);
DEBUG不提供追踪标志TF的符号。
*****************************************************
2.显示命令D:
D(Dump)命令显示主存单元的内容,它的格式如下(注意分号后的部分用于解释命令功能,不是命令本身):
           D [地址]       ;显示当前或指定开始地址的主存内容
         D [范围]       ;显示指定范围的主存内容
输入命令D,执行结果如下所示:
-d;DS:100开始的128个字节
0AF2:0100  3E CD 21 BA BC 98 B4 41-CD 21 C6 06 D1 96 00 E9   >.!....A.!......
0AF2:0110  57 FA E9 AE FE 24 0C 7A-10 50 24 08 34 00 E1 0A   W....$.z.P$.4...
0AF2:0120  24 04 A2 D8 99 08 06 D2-99 A0 D8 99 0A C0 C3 80   $...............
0AF2:0130  3E B7 98 FF 75 0C BF E1-94 BD B7 98 E8 11 01 E8   >...u...........
0AF2:0140  74 E4 32 C0 86 06 16 99-0A C0 75 03 E9 8C 00 8B   t.2.......u.....
0AF2:0150  36 B9 98 BF 76 97 B8 00-29 CD 21 80 3C 00 74 06   6...v...).!.<.t.
0AF2:0160  BA 92 8A E9 53 FF A1 BC-98 80 FC 3A 74 02 B0 40   ....S......:t..@
0AF2:0170  8A 0E D8 99 0C 20 2C 60-A2 76 97 A0 BB 98 8A 26   ..... ,`.v.....&
-
说明:(1)XXXX:YYYY--------主存逻辑地址,前者是内存单元的段地址,后者是内存单元的偏移量。
         (2)中间显示区域是内存单元内容(十六进制的形式),每行显示16个字节的内容;
(3)右边部分是内存单元内容的ASCII字符显示,不可显示字符用点“.”表示。一个D命令仅显示“8行×16个字节”(80列显示模式)内容。
命令D可以带参数,也可省略参数。省略参数时,第一次命令D显示的内容是从DS:100开始的128个字节,再执行不带参数的命令D时,则从上次的显示位置往下接着显示。

方式一:D起始位置
DEBUG从起始位置开始显示128个字节的内容。输入命令D 1AF5:100,执行结果如下所示。
-d1af5:100;从起始位置开始显示128个字节的内容
1AF5:0100  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0110  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0130  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0140  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
1AF5:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-

方式二:D起始位置 结束位置
DEBUG从起始位置开始一直显示到结束位置。输入命令D DS:100 11F,执行结果如下所示。
-d ds:10 58;从起始位置开始一直显示到结束位置
0AF2:0010  56 05 17 03 56 05 1A 04-01 01 01 00 02 FF FF FF   V...V...........
0AF2:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 0B 05 4E 01   ..............N.
0AF2:0030  16 0A 14 00 18 00 F2 0A-FF FF FF FF 00 00 00 00   ................
0AF2:0040  05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF2:0050  CD 21 CB 00 00 00 00 00-00                        .!.......
-

方式三:D起始位置 L长度
DEBUG从起始位置开始显示指定长度的内容。输入命令D DS:100 L10,执行结果如下所示。
-d ds:100 L 10;从起始位置开始显示指定长度为10(16进制)的内容
0AF2:0100  3E CD 21 BA BC 98 B4 41-CD 21 C6 06 D1 96 00 E9   >.!....A.!......
-
再如:
-d 100              ;显示数据段100h开始的主存单元
-d cs:0             ;显示代码段的主存内容
-d2f0 L20           ;显示ds:2f0h开始的20h个主存数据

3.E命令:
它有两种格式:E命令用于修改主存内容,它是用字节值表中的值替换从“起始地址”开始的内存单元内容。
使用方式:E 起始地址 字节值表
也可以是:E 起始地址。
例如:
-e ds:100;从起始地址ds:100开始修改主存内容
0AF2:0100  3E.12   CD.34   21.56-
0AF2:0101  34.78   56.     BA.
-d ds:100;从起始位置ds:100开始显示128个字节的内容
0AF2:0100  12 78 56 BA BC 98 B4 41-CD 21 C6 06 D1 96 00 E9   .xV....A.!......
0AF2:0110  57 FA E9 AE FE 24 0C 7A-10 50 24 08 34 00 E1 0A   W....$.z.P$.4...
0AF2:0120  24 04 A2 D8 99 08 06 D2-99 A0 D8 99 0A C0 C3 80   $...............
0AF2:0130  3E B7 98 FF 75 0C BF E1-94 BD B7 98 E8 11 01 E8   >...u...........
0AF2:0140  74 E4 32 C0 86 06 16 99-0A C0 75 03 E9 8C 00 8B   t.2.......u.....
0AF2:0150  36 B9 98 BF 76 97 B8 00-29 CD 21 80 3C 00 74 06   6...v...).!.<.t.
0AF2:0160  BA 92 8A E9 53 FF A1 BC-98 80 FC 3A 74 02 B0 40   ....S......:t..@
0AF2:0170  8A 0E D8 99 0C 20 2C 60-A2 76 97 A0 BB 98 8A 26   ..... ,`.v.....&
-e 100 12 'abcd'34;从起始地址ds:100开始,一次修改多个单元
-d ds:100;从起始位置ds:100开始显示128个字节的内容
0AF2:0100  12 61 62 63 64 34 B4 41-CD 21 C6 06 D1 96 00 E9   .abcd4.A.!......
0AF2:0110  57 FA E9 AE FE 24 0C 7A-10 50 24 08 34 00 E1 0A   W....$.z.P$.4...
0AF2:0120  24 04 A2 D8 99 08 06 D2-99 A0 D8 99 0A C0 C3 80   $...............
0AF2:0130  3E B7 98 FF 75 0C BF E1-94 BD B7 98 E8 11 01 E8   >...u...........
0AF2:0140  74 E4 32 C0 86 06 16 99-0A C0 75 03 E9 8C 00 8B   t.2.......u.....
0AF2:0150  36 B9 98 BF 76 97 B8 00-29 CD 21 80 3C 00 74 06   6...v...).!.<.t.
0AF2:0160  BA 92 8A E9 53 FF A1 BC-98 80 FC 3A 74 02 B0 40   ....S......:t..@
0AF2:0170  8A 0E D8 99 0C 20 2C 60-A2 76 97 A0 BB 98 8A 26   ..... ,`.v.....&
-
格式1是逐个单元相继修改的方法。例如,键入“e ds:100”,Debug显示原来内容,用户可以直接输入新数据,然后按空格键显示下一个单元的内容,或者按“-”键显示上一个单元的内容;不需要修改可以直接按空格或“-”键;这样,用户可以不断修改相继单元的内容,直到用回车键结束该命令为止。
格式2可以一次修改多个单元,例如:
    -e 100 12 'abcd'34    ;用12 'abcd'34这6个数据替代DS:0100 ~ 0105的原来内容12 78 56 BA BC 98。
我们还可以用E命令向内存中写入机器码,用U命令查看内存中机器码的含义(对应的汇编指令助记符),用T命令执行内存中的机器码。
例如从内存1000:0单元开始写入这样一段机器码:
机器码:                        b80100        b90200        01c8
对应的汇编指令:mov ax,0001                mov cx,0002        add ax,cx
显示如下:
-e 1000:0 b8 01 00 b9 02 00 01 c8;从起始地址1000:0开始输入指令
-d 1000:0 L f;从起始位置1000:0开始显示指定长度为f的内容
1000:0000  B8 01 00 B9 02 00 01 C8-00 00 00 00 00 00 00      .............
-u 1000:0;从1000:0开始显示32个字节机器码对应的汇编指令格式
1000:0000 B80100        MOV     AX,0001
1000:0003 B90200        MOV     CX,0002
1000:0006 01C8          ADD     AX,CX
1000:0008 0000          ADD     [BX+SI],AL
1000:000A 0000          ADD     [BX+SI],AL
1000:000C 0000          ADD     [BX+SI],AL
1000:000E 0000          ADD     [BX+SI],AL
1000:0010 0000          ADD     [BX+SI],AL
1000:0012 0000          ADD     [BX+SI],AL
1000:0014 0000          ADD     [BX+SI],AL
1000:0016 0000          ADD     [BX+SI],AL
1000:0018 0000          ADD     [BX+SI],AL
1000:001A 0000          ADD     [BX+SI],AL
1000:001C 0000          ADD     [BX+SI],AL
1000:001E 0000          ADD     [BX+SI],AL
-
由此我们看到在内存中数据和代码没有任何区别,都是一组二进制数据,关键在于如何解释。
接下来我们使用T命令执行我们刚才输入的机器指令。T命令可以执行CS:IP指向的指令,所以我们先修改CS和IP的值,让CS:IP指向1000:0。
显示如下:
-r;显示所有寄存器的值和标位的状态
AX=0002  BX=00A3  CX=00A1  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=0AF2  IP=100C   NV UP EI NG NZ NA PE NC
0AF2:100C 09C3          OR      BX,AX
-r cs;修改寄存器cs的内容
CS 0AF2
:1000
-r ip;修改寄存器ip的内容
IP 100C
:0000
-r;显示所有寄存器的值和标位的状态
AX=0002  BX=00A3  CX=00A1  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=1000  IP=0000   NV UP EI NG NZ NA PE NC
1000:0000 B80100        MOV     AX,0001
-
修改了CS和IP的值后,我们就可以使用T命令来执行我们写入的指令了。执行T命令后,CPU执行CS:IP指向的指令,使得AX中的内容被改写成为1,IP变成IP+3(因为MOV AX,0001的指令长度为3个字节),CS:IP指向下一条指令。
显示如下:
-t

AX=0001  BX=00A3  CX=00A1  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=1000  IP=0003   NV UP EI NG NZ NA PE NC
1000:0003 B90200        MOV     CX,0002
-t

AX=0001  BX=00A3  CX=0002  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=1000  IP=0006   NV UP EI NG NZ NA PE NC
1000:0006 01C8          ADD     AX,CX
-t

AX=0003  BX=00A3  CX=0002  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=1000  IP=0008   NV UP EI PL NZ NA PE NC
1000:0008 0000          ADD     [BX+SI],AL                         DS:00A3=61
-t

AX=0003  BX=00A3  CX=0002  DX=0000  SP=F954  BP=FCB2  SI=0000  DI=0000
DS=0AF2  ES=0AF2  SS=0AF2  CS=1000  IP=000A   NV UP EI PL NZ NA PO NC
1000:000A 0000          ADD     [BX+SI],AL                         DS:00A3=64
-
评论次数(2)  |  浏览次数(1439)  |  类型(学习笔记) |  收藏此文  | 

[  游客   发表于  2007-10-24 16:04  ]

不错,debug确实是学习汇编不可缺少的工具。
不过写的太多了点,刚开始学习汇编的人不宜背太多影响学习的东西(就像书中前言讲的知识屏蔽,以后用到的知识以后在学),书上讲的常用命令足可以满足学习汇编的需要,不过可以把这篇文章当作使用手册来使用,活学活用~

[  fishboy   发表于  2007-10-24 19:27  ]

收藏了先。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码