Debug概览
Debug是什么?
- debug是Windows 16位或者32位机器上的一款调试工具。也就是说,在WindowsXP及以前的机器上都有debug,直接Win+X debug就可以调出;在之后的32位机也有;但是在之后的64位机器上不存在,即使有,也无法运行。
不必尝试到底能不能运行,绝对不能
- 相似的,微软的masm也无法在64位版本的系统上运行。
可以通过安装dosbox来虚拟一个DOS环境或者使用WindowsXP(虚拟机即可)的方式来使用debug和masm。
debug的作用是什么?如何打开debug?
- 顾名思义 - 用来调试的工具。debug有极为丰富的命令支持,灵活、高效。debug的调试不同于IDE的调试 - 虽然都支持下断点的方式,但是debug能够直接查看CPU寄存器的内容,甚至能够在程序运行过程中修改自身代码 - 这是IDE望尘莫及的。
- 打开debug的方式:Win + X呼出运行窗口,输入cmd,然后输入debug回车就行了。进入debug后,命令提示符会变成“-”,如下图。
但是一般来说不使用系统的debug进行实验以防止无意中损坏系统,一般来说使用单独分离出来的debug进行实验,以获得更高的安全性和更完整的功能体验。Debug下载链接在文末,与masm同打包
调用时在cmd中cd到存放debug.exe的文件夹,输入debug并回车就可以了。或者在当前文件夹编写一个bat,内容为字母cmd,撒谎及运行可以达到同样的效果。
使用DEbug时你必须知道的几点
0.所有数据都是
10进制,除非有别的进制的符号修饰(如50h)
1.range 表示范围,不同指令默认段有所不同。均可以适用类似 CS:0100L2的形式表示范围
2.不能使用符号常量和符号地址.(就是说不能用变量和指针)
3.不能使用绝大部分伪指令,但两个最常用的伪指令 DB 和 DW 能被使用,用于直接把字节和字数据置入相应存储单元。如:
DB 1,2,3,4,“ABCD”
DW 1234,5678
Debug用法
参数一览表
命令 | 含义 | 用法 |
---|---|---|
A | assemble | 在内存中直接编写代码 |
C | Compare | 比较内存 |
D | Dump | 查看内存内容 |
E | Enter | 修改内存内容 |
F | Full | 填充内存 |
G | Go | 执行代码 |
H | Hexarithmetic | 以16进制进行数学运算 |
I | Input | 从某个端口输入一个16进制并显示 |
L | load | 把文件或者绝对扇区内容读入内存 |
M | move | 数据传递(不同于汇编的move) |
N | name | 为读写磁盘文件定义文件名 |
O | output | 把指定字节发送到制定端口 |
Q | quit | 结束debug程序 |
R | Register | 寄存器命令 |
S | Search | 按照list清单查找内存range范围 |
T | track | 追踪命令 |
U | UNassemble | 反汇编内存中的指令 |
W | write | 把调试过的信息写到磁盘上 |
? | Help | 获取帮助信息,即现实所有支持的命令 |
详解
0.启动Debug的参数
启动形式:Debug [完整路径][文件名][.exe][exe的参数1][exe的参数2]
其中,方括号内的内容为可选值。若载入了一个文件(注意,不一定是exe,也有可能是转储文件),则载入的位置是CS指向的位置,偏移量为0
如果输入文件名 filename,那么 DEBUG 就把所指定的文件装入内存,然后可以输入命令来修改、显示或执行指定文件的内容。如果不输入文件名 filename,那么或使用当前存储器的内容进行工作,或使用命名命令 Name 和装入命令 Load 把需要的文件或者准确的磁盘扇区装入存储器中,然后可以输入命令来修改、显示或执行存储器的内容。
1.汇编指令A(assemble)
- 作用:键入汇编指令,并把它们汇编成机器代码,相继存放在从指定地址开始的存储区中。
形式:A[address] (A与addr有无空格均可) , A [基址寄存器:][偏移] (有无空格均可)
-
汇编指令有以下两种格式:
a ;从上次停下的地方继续输入汇编指令(上次a指令停下的地方)
a 开始地址 ;从起始位置开始编写汇编代码(举例:A CS:1100 ,即为从cs:1100的地方开始编写汇编代码)
2.比较指令C(compare)
作用:比较两个数据块的内容
格式: C range addr , 其中range为第一个数据块的起始地址加长度(用以构成数据块),
如果不写段寄存器,默认DS
,第二个只写目标地址
,不写段寄存器默认DS如果找到不相等的字节,则用下列形式显示地址和内容: addr1 byte1 byte2 addr2
此处,前一半(即 addr1 byte1)说明 range 内不相等单元的位置和内容,后面的一半指的是在 address 中找到的不相等的内容和位置。-
举例:
C 100L20 200
把 DS:100 开始的存储器的 32 个字节同从 DS:200 开始的 32 个字节进行比较。C表示比较指令,100表示起始地址,没有写段所以默认DS
L表示段长度,20是十六进制,换下来是32字节
3.显示内存指令D(Dump)
- 作用:显示存储器内容(16进制)
- 格式:D [addr] 或 D [range] , 有无空格均可。
- 详细:
- D DS:1100 ;从DS:1100开始显示
- D ;从上次停下的位置开始显示
- D 0100 ;
没有段寄存器,默认DS
- D [addr]L[size] ;从addr处开始显示
size(16进制)
个字节的数据,addr含义同1 - 3 - D [start_addr] [end_addr] ;从start_addr 显示到end_addr
4.修改内存指令E(enter)
作用:修改内存的值
-
形式:E addr [list]
不存在list时:显示addr的内容,并等待输入一个16进制数以替换之
数据段默认DS
存在list时:使用list的内容填充addr之后list长度的内存的内容
eg:E DS:1000 f3 ‘xyz’ d8 ;使用f3 x y z d8 五个字节的内容替换DS:1000 到 DS:1004的内容
例如:
E address
现在可以开始下列操作:
输入一个或两个十六进制值的字符去替换字节的内容,然后采取下面操作之一。
按空格步进到下个地址,并显示其内容。如果希望改变其内容就采取上述第一条操作。
输入连字符“—”退回到前一个地址,并显示其内容。如果希望改变其内容则采取上述第一条操作。
为了退回一个以上的字节且不改变当前字节,应输入另一个连字符。
为了结束 E 命令,按 ENTER 键。
例如:
E cs:100
可以得到如下显示内容:
04BA:0100 EB._
为了把 04BA:0100 内容由 EBH 改变成 41H,则输入 41:
04BA:0100 EB.41
为了查看下三个单元的内容,按三次空格,屏幕显示出:
04BA:0100 EB.41 10.00.BC._
为了把当前单元(04BA:0103)由 BCH 改成 42H,应输入 42:
04BA:0100 EB.41 10.00.BC.42
如果要退回并把 10H 改成 6FH,则按两次连字符和输入置换的字节之后,屏幕上显示:
04BA:0100 EB.41 10.00.BC.42
04BA:0102 00._
04BA:0101 10.6F
按 ENTER 键结束输入命令,将会看到提示符为连字符“—”。
5.内存填充指令F(Fill)
- 用清单中的内容填充range范围内存
- 形式: F range list
- 说明:如果清单中包含的字节数小于地址范围,则重复地使用该清单,直到把所指定范围内的存储器单元填满为止。如果清单中包含的字节数大于地址范围,就忽略不计超过的部分。
- 例如:
F4BA:100 L 5 F3‘XYZ’8D
用指定的 5 个字节填写到内存的 04BA:100 到 04BA:104 单元中。注意,存储清单字符是
ASCII 字符码,因此 100—104 单元中为 F3 58 59 5A 8D。
6.执行命令G(Go)
- 作用:执行正在调试的程序。
当达到所指定的断点地址处时,就停止执行,并显示寄存器、标志位以及下一条要执行的指令。断点在Track部分。
- 格式:G[=addr][断点1][断点2][断点n]…
- 不指定=addr参数时,从
CS:IP开始执行
7.十六进制运算指令H (Hexarithmetic)
作用:先把两个十六进制的值相加,然后第一个值减去第二个值。在一行上显示和与差。
-
格式:格式:H value value
例如:
H 0F 8
17 07
000F 和 0008 的 16 进制和是 0017,而其差是 0007
8.输入指令I(Input)
从指定的端口输入
并显示
-
格式:I portnum
例如:
- I 2F8
6B
显示由 02F8 端口读入的一个十六进制字节数(6BH)。
9.载入指令L(load)
作用:把制定的文件
或绝对扇区
装入内存。-
形式1:L [addr][driver][起始扇区][载入的扇区数量]
例如:
L 4BA:100 1 OF 6D
从驱动器 B 的盘上装入数据,并把数据存放在以 4BA:100 开始的内存中。从相对扇区 0FH驱动器以 1 2 3等区分
-
形式2:L 或者 L [addr] ;载入已经由N命令指定的文件。
默认CS:100
文件需在当前文件夹下
N file_test
L ;载入到CS:100
L CS:1000 ;载入到指定的内存位置 CS:1000
说明:用单个 Load 命令可装入的最大扇区数是
80H
。如果出现读盘错,则 DEBUG 显示出错信息。
10.传送指令M(move)
作用:
复制
指定内存块的内容到另一内存块-
形式:M range addr ;复制range的内容到addr
range内存块内容不变
例如:
M CS:100 110 500
把 CS:100 到 CS:110 的 17 个字节的数据,传送到以 DS:500 开始的内存区中。
11.命名指令N(name)
- 作用:为读写磁盘文件定义文件名
- 格式:N [name1][name2….]
- 说明:如果在无文件说明时启动 DEBUG,在用 L 命令装入文件之前,必须使用 Name 命令。
12.输出指令O(output)
作用:向端口发送数据
-
格式:O portNum byte
例如:为了把字节值 4F 发送到输出端口 2F8,输入:
O 2F8 4F
13.退出命令Q(quit)
- 说明:Q 命令不保存内存中正工作的文件,需要时可用 Write 命令保存文件。
14.寄存器命令R(Register)
-
用途:
- 显示并修改一个寄存器的值
- 显示全部寄存器、标志位、以及将被执行的下条指令。
- 显示 8 个标志位状态,并带有修改它们之中任一个或全部的选择
-
格式:R [regname]
- 其一:显示单个寄存器
有效寄存器是:AX、BX、CX、DX、SP、BP、SI、DI、DS、ES、SS、CS 和 IP。
R AX
系统显示如下:
AX F1E4
:_
现在可以采用下列两个操作中的某一个:
按 ENTER 键保留未修改的内容。
输入 1—4 字符的十六进制值来修改 AX 寄存器的内容,例如 FFFH。
AX F1F4
:FFF_
现在按ENTER键把AX寄存器内容改变成0FFFH。- 其二:显示所有的寄存器和标志位
其二:显示所有的寄存器和标志位
为了显示所有寄存器的内容和标志位(还有下条要执行的指令),输入:
R
则系统可能显示如下:
AX=0E00 BX=00FF CX=0007 DX=01FF
SP=039D BP=0000 SI=005C DI=0000
DS=04BA ES=04BA SS=04BA CS=04BA
IP=011A NV UP DI NG NZ AC PE NC
04BA:01lA CD21 1NT 21
头4行显示寄存器十六进制内容和8个标志位状态。最后一行指出下一条要执行的指令地址和它的16进制机器码以及反汇编形式,这是当前CS:IP指向的指令。- ③显示标志位有8个标志位,每位用2个字母表示是置“1”状态还是清除状态,详细说明见下表:
标志位名称 Set(置位) clear(清除) 溢出 OV NV 方向(减、加) DN UP 中断允许 DI DI 负号(正负) NZ PL 零(是否) ZR NZ 辅助进位 AC NA 奇偶 PE PO 进位 CY NC 为了显示所有的标志位,输入命令:
R F
如果所有标志位处于置1状态,就显示:
OV DN EI NGZR AC PE CY - 其一:显示单个寄存器
15.检索命令S(Search)
作用:按照给出的内容在一定范围内检索
形式:S range list
-
说明:以显示被查找到的匹配字符所在的地址来指明全部的匹配。显示没有地址的提示符
“—”,表示未找到任何匹配字符。例如:要想从 CS:100 到 CS:110 地址范围内检索 41H,那么输入:
S CS:100 110 41
如果找到两个匹配,则显示也许是:
04BA:0104
04BA:010D
16.跟踪命令T(Trace)
- 用途:从 CS:IP 或者=address(如果指定的话)单元中的指令开始单步执行一条或多条指令。这里的=号必须输入。
用 value 指定跟踪多条指令。
每条指令执行后,显示所有寄存器的内容、标志位的状态以及下一条要执行的指令。 - 形式: T [=addr][value]
例如,输入命令:
T
如果 IP 寄存器内容为 011A,而该地址指向的指令是 MOV AH,0EH,这可能显示:
AX=0E00 BX=00FF CX=0007 DX=01FF
SP=039D BP=0000 SI=005C D1=0000
DS=04BA ES=04BA SS=04BA CS=04BA
IP=011C NV UP DI NG NZ NC PE NC
04BA:01lC CD21 INT 21
这是执行 011A 中指令之后显示的结果,并且指出下条要执行的指令是 04BA:011C 单元中的
INT 21。
17.反汇编指令U(UNassemble)
- 作用:把内存中的机器码转换成汇编语句,并显示指令的地址、机器码以及汇
编语句 - 形式:
- U [range] , 用于反汇编不带指定地址的指令,或反汇编从指定地址开始的指令
- U [addr] , 用于反汇编从addr开始的指令。
反汇编多少由显示方式而定。用 40 列显示时,一次把 16 个字节反汇编;用 80 列显示时,一次把 32 个字节反汇编。,
18.文件转储指令W(Write)
用途:把调试过的信息写到磁盘上。
-
形式:
- 1.从指定地址开始把信息写到
绝对磁盘扇区
上,W address drive sector sector
从指定的开始相对扇区(第一个 sector)开始写数据,并且连续写,直到写完所要求的扇区数(第二个 sector)为止。这种方式以磁盘扇区的多少为限制,而不是内存内容的多少
例如,命令:
W 1FD 1 100 A
把从 CS:01FD 单元开始的数据写到驱动器 B 的软盘中,由相对扇区 100H(256)开始连续写 0AH(10)个扇区。- 2.内存内容转储到文件。 W addr
此时,写命令把文件写到磁盘上,把从
CS:100
或由参数 address 指定的单元
开始的文件按文件说明 filespec 写到磁盘上。此文件的文件说明被格式化在 CS:5C 文件控制块中。当启动 DEBUG 时指定文件说明,或者使用 N 命令,采用这两种方法都可满足这个条件。另外,必须把寄存器 BX 和 CX 置成被写的字节数目,它们可能已由 DEBUG 或 Load 命令设置过,也可能被修改过。必须确保 BX 和 CX 寄存器包含正确的值。
不确定对第一种方式是否是必须的
- 1.从指定地址开始把信息写到
Debug注意事项
可能与之前那个有点重复。这个更详细。
DEBUG支持基本的8086/8088汇编语言语法,DEBUG下的汇编语言有下面一些特点和规则:
① 数值都是十六进制数,并且不加尾缀“H”。
② 不能使用符号常量和符号地址。
③ 不能使用绝大部分伪指令,但两个最常用的伪指令 DB 和 DW 能被使用,用于直接把字节和字数据置入相应存储单元。如:
DB 1,2,3,4,“ABCD”
DW 1234,5678
④ 可以使用属性操作符“PTR”对 DEBUG 不能明确类型的操作数进行说明。如:INC BYTE
PTR [BX]。
⑤ DEBUG 的 A 命令汇编程序能根据转移目标地址的距离自动地汇编出短、近或远的转移
或调用指令。当然,这也能由“SHORT”、“NEAR PTR”或”FAR PTR”对转移目标地址
进行说明来实现。
⑥ 远返回指令的助记符在 DEBUG 中为 RETF。
⑦ 指令前缀助记符必须在相关的指令之前输入,也可以分别放在不同的行。
⑧ 串操作指令只能用其字节型或字型的助记符形式,如:MOVSB、CMPSW 等。
⑨ 可以使用段超越前缀助记符 CS:、DS:、ES:和 SS:。如:
DS:
MOV AL,[BP]