本文介绍使用调试器命令必须遵循的语法规则。使用Windbg调试时,应遵守以下一般语法规则:
- 您可以在命令和参数中使用大小写字母的任意组合,除非在本节的主题中特别指出。
- 可以用一个或多个空格或逗号(,)分隔多个命令参数。
- 通常可以省略命令与其第一个参数之间的空格。如果这种省略不会造成任何歧义,则可以经常省略其他空格。
阅读本文中的命令引用注意以下事项:
- 粗体字体的字符表示必须逐字键入的项目。
- 斜体字体的字符表示参考主题“参数”部分中解释的参数。
- 括号([xxx])中的参数是可选的。带有竖线([XXX|YYY])的括号表示可以使用一个或无一个封闭参数。
-
带竖线(XXX|YYY)的大括号表示必须仅使用其中一个封闭参数。
一、数字表达式
调试器接受两个不同类型的数值表达式:C++表达式和MASM 表达式。 每个这些表达式遵循用于输入和输出自己语法规则。
1.1、MASM 数字和运算符
- MASM表达式中的数字
在masm表达式中我们可以输入二进制、八进制、十进制、十六进制数字。使用n(设置基数)命令将默认基数设置为16、10或8。所有未固定的数字都将在此基数中解释。可以通过指定0x前缀(十六进制)、0n前缀(十进制)、0t前缀(八进制)或0y前缀(二进制)来重写默认基数。您还可以通过在数字后面添加h来指定十六进制数字。您可以在数字中使用大写或小写字母。例如,“0x4ab3”、“0x4ab3”、“4ab3h”、“4ab3h”和“4ab3h”具有相同的含义。如果不在表达式的前缀后面添加数字,则该数字将被读取为0。因此,您可以将0写为0,前缀后跟0,并且只写前缀。例如,在十六进制中,“0”、“0x0”和“0x”具有相同的含义。您可以以XXXXXXXX`XXXXXXXX格式输入十六进制64位值。 - MASM表达式中的符号
在masm表达式中,任何符号的数值都是其内存地址。根据符号所指的内容,此地址是全局变量、局部变量、函数、段、模块或任何其他可识别标签的地址。要指定与地址关联的模块,请包括模块名称和感叹号(!)在符号名称之前。如果符号可以解释为十六进制数,请在符号名之前包含模块名和感叹号,或仅包含感叹号。使用两个冒号(:)或两个下划线(_)指示类的成员。只有在符号名称前面添加模块名称和感叹号时,才能在符号名称中使用重音符(`)或撇号(')。 -
MASM表达式中的数字运算符
可以使用一元运算符修改表达式的任何组件。您可以使用二进制运算符组合任意两个组件。一元运算符优先于二元运算符。使用多个二进制运算符时,运算符遵循下表中描述的固定优先级规则。 您可以始终使用括号来覆盖优先规则。如果一个MASM表达式的一部分被括在括号中,并且在表达式之前出现两个符号(@),则表达式根据C++表达式规则进行解释。不能在两个at符号和左括号之间添加空格。还可以使用@ @ C++(…)指定表达式计算器。或@@masm(…).执行算术计算时,MASM表达式计算器将所有数字和符号视为ulong64类型。一元地址运算符将ds作为地址的默认段。表达式按运算符优先顺序计算。如果相邻运算符的优先级相等,则表达式将从左到右进行计算。
可以使用以下一元运算符:
运算符 含义 +
一元加
-
一元负
非
如果参数为零,则返回 1。 任何非零值的参数,则返回零。
hi
高 16 位
low
低 16 位
by
从指定的地址的低序位字节。
$pby
与相同通过,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。
wo
从指定的地址的低序位字。
$pwo
与相同wo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。
dwo
从指定的地址双字。
$pdwo
与相同dwo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。
qwo
从指定的地址四字。
$pqwo
与相同qwo ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。
poi
从指定的地址指针大小的数据。 指针大小为 32 位或 64 位。 在内核调试,此大小基于的处理器目标计算机。 在用户模式下调试在基于 Itanium 的计算机上,此大小为 32 位或 64 位,具体取决于目标应用程序。 因此, poi是要使用如果你想指针大小的数据的最佳运算符。
$ppoi
与相同poi ,但前者的物理地址。 可以读取仅使用默认缓存行为的物理内存。
可以使用以下二进制运算符。 每个单元格中的运算符优先于较小的单元中。 相同单元中的运算符均属于相同的优先级,从左到右进行分析。
运算符 含义 *
/
mod (或 %)
乘法
整数除法
取模 (余数)
+
-
添加
减法
<<
>>
>>>
左的移
逻辑右移位
算术右移位运算
= (或 = =)
<
>
<=
>=
!=
等于
小于
大于
小于或等于
大于或等于
不等于
和(或 &)
位与
xor (或 ^)
按位 XOR (异或)
或(或 |)
按位 OR 运算符
<, >、 =、 = =、 和 ! = 的比较运算符计算结果为 1,如果表达式为 true 或为零,如果表达式为 false。 单个等号 (=) 是双等号 (= =) 相同。 不能使用副作用或 MASM 表达式中的分配。在"操作数错误"中无效的操作 (如被零除) 结果返回到调试器命令窗口。
-
MASM表达式中的非数字运算符
此外可以在 MASM 表达式中使用以下其他运算符。
运算符 含义 $fnsucc(FnAddress, RetVal, Flag)
解释RetVal位于函数的返回值的值FnAddress地址。 如果此返回值被返回成功代码,称为$fnsucc返回TRUE。 否则为$fnsucc返回FALSE。
如果返回类型为布尔值、 bool、 句柄、 HRESULT 或 NTSTATUS, $fnsucc正确理解是否在指定的返回值被称为成功代码。 返回类型是否为指针,所有值,而NULL才会被视为成功代码。 成功的值对于任何其他类型进行定义标志。 如果标志为 0,一个非零值的RetVal为 success。 如果标志为 1,零值的RetVal为 success。
$iment (地址)
加载的模块列表中返回映像入口点的地址。 地址指定的可移植可执行文件 (PE) 映像基址。 通过查找映像的 PE 映像标头中的映像入口点找到该项,地址指定。
您可以使用此函数的是已在模块列表中,并设置这两个模块无法解析的断点通过使用bu命令。
$scmp("String1", "String2")
计算结果为-1、 0 或 1,如strcmp C 函数。
$sicmp("String1", "String2")
计算结果为-1、 0 或 1,如stricmp Microsoft Win32 函数。
$spat("String", "Pattern")
计算结果为,则返回 TRUE或FALSE取决于是否字符串匹配模式。 匹配不区分大小写。 模式可以包含各种通配符和说明符。 有关语法的详细信息,请参阅字符串通配符语法。
$vvalid(Address, Length)
确定是否内存范围的开始处地址,并为扩展长度字节是否有效。 如果有效,内存$vvalid的计算结果为 1。 如果内存是无效的$vvalid计算结果为 0。
- MASM表达式中的寄存器和伪寄存器
您可以在masm表达式中使用寄存器和伪寄存器。您可以在所有寄存器和伪寄存器之前添加at符号(@)。at符号使调试器更快地访问该值。对于最常见的基于x86的寄存器来说,这个at符号是不必要的。对于其他寄存器和伪寄存器,我们建议您添加at符号,但实际上并不需要它。如果省略了较不常用的寄存器的at符号,调试器将尝试将文本解析为十六进制数,然后作为符号,最后作为寄存器。还可以使用句点(.)指示当前指令指针。在此期间之前不应添加at符号,并且不能将期间用作r命令的第一个参数。此期间的含义与$IP伪寄存器相同。 - MASM表达式中的源行号
可以在masm表达式中使用源文件和行号表达式。必须使用重音符(`)将这些表达式括起来。
1.2、C++数字和运算符
Windbg中的C++表达式解析器支持所有形式的C++表达式语法。该语法包括所有数据类型(包括指针、浮点数和数组)和所有C++一元和二元运算符。
- C++表达式中的数字
C++表达式中的数字被解释为十进制数,除非用另一种方式指定它们。要指定十六进制整数,请在数字前面添加0x。要指定一个八进制整数,请在数字前面加0(零)。默认调试器基数不影响您输入C++表达式的方式。不能直接输入二进制数(除非在C++表达式中嵌套了一个MASM表达式)。您可以以XXXXXXX`XXXXXXXXX格式输入一个十六进制的64位值。(您也可以省略重音符('.))两种格式产生相同的值。可以使用带整数值的L、U和I64后缀。创建的数字的实际大小取决于后缀和输入的数字。有关此解释的更多信息,请参见C++语言引用。C++表达式计算器的输出保持C++表达式规则指定的数据类型。但是,如果将此表达式用作命令的参数,则始终进行强制转换。例如,当整数值用作命令参数中的地址时,不必向指针强制转换整数值。如果表达式的值不能有效地转换为整数或指针,则会出现语法错误。对于某些输出,可以使用0N(十进制)前缀,但不能将其用于C++表达式输入。 - C++表达式中的字符和字符串
您可以通过将字符用单引号(“)包围来输入字符。标准的C++转义字符是允许的。您可以通过将字符串文本用双引号(“)包围来输入字符串文本。您可以在这样的字符串中使用“作为转义序列。但是,字符串对表达式计算器没有意义。 - C++表达式中的符号
在C++表达式中,每个符号根据其类型来解释。根据符号所指的内容,可以将其解释为整数、数据结构、函数指针或任何其他数据类型。如果在C++表达式中使用与C++数据类型(如未修改的模块名)不符的符号,则会出现语法错误。如果符号可能不明确,可以添加模块名和感叹号(!)或者只在符号前加一个感叹号。只有在符号名称前添加模块名称和感叹号,才能在符号名称中使用重音符(`)或撇号(“)。在模板名称后面添加分隔符时,可以在这些分隔符之间添加空格。 -
C++表达式中的运算符您可以始终使用括号来覆盖优先规则。如果在括号中包含一部分C++表达式,并在表达式之前加上两个符号(@),则根据MASM表达式规则对表达式进行解释。不能在两个at符号和左括号之间添加空格。此表达式的最终值作为ULUN64值传递给C++表达式求值器。还可以使用@ @ C++(…)指定表达式计算器。或@@masm(…).数据类型通常以C++语言表示。指示数组([])、指针成员(->)和UDT成员(.)的符号。和类(::)的成员都可以识别。支持所有算术运算符,包括赋值和副作用运算符。但是,不能使用new、delete和throw运算符,也不能实际调用函数。支持指针算法并正确缩放偏移量。请注意,不能向函数指针添加偏移量。(如果必须向函数指针添加偏移量,请先将偏移量强制转换为字符指针。)与C++一样,如果使用具有无效数据类型的运算符,则会发生语法错误。调试器的C++表达式分析器使用的规则比大多数C++编译器稍微宽松一些,但是所有的主要规则都被强制执行。例如,不能移动非整数值。可以使用以下运算符。每个单元格中的运算符优先于较低单元格中的运算符。同一单元格中的运算符具有相同的优先级,并从左到右进行分析。与C++一样,表达式评估在其值已知时结束。这个结尾使您能够有效地使用表达式,例如??myptr和&*myptr。
运算符 含义 表达式 // 注释
忽略所有后续文本
类 ::成员
类 :: ~成员
::名称
类的成员
类 (析构函数) 的成员
全局
结构 。 字段
指针 - > 字段
Name [integer]
LValue ++
LValue --
dynamic_cast <type>(Value)
static_cast <type>(Value)
reinterpret_cast <type>(Value)
const_cast <type>(Value)
结构中的字段
引用结构中的字段
数组下标
增量 (之后评估版)
递减 (后评估版)
类型转换 (始终执行)
类型转换 (始终执行)
类型转换 (始终执行)
类型转换 (始终执行)
(type) Value
sizeof value
sizeof( type )
++ 左值
-- 左值
~ 值
! ReplTest1
ReplTest1
+ 值
& 左值
值
类型转换 (始终执行)
表达式的大小
数据类型的大小
增量 (之前评估版)
递减 (在之前评估版)
位求补
不 (布尔值)
一元负
一元加
数据类型的地址
取消引用
结构 。 指针
Pointer -> * Pointer
指向成员的结构的指针
指向引用结构成员的指针
Value Value
Value / Value
Value % Value
乘法
部门
取模
Value + Value
Value - Value
添加
减法
Value << Value
Value >> Value
按位左移
按位右移
Value < Value
Value <= Value
Value > Value
Value >= Value
早于 (比较)
小于或等于 (比较)
大于 (比较)
大于或等于 (比较)
Value == Value
Value != Value
等于 (比较)
不等于 (比较)
Value & Value
位与
Value ^ Value
按位 XOR (异或)
Value | Value
按位 OR 运算符
Value && Value
逻辑与
Value || Value
逻辑或
LValue =Value
LValue = Value
LValue /= Value
LValue %=Value
LValue +=Value
LValue -= Value
LValue <<= Value
LValue >>= Value
LValue &= Value
LValue |= Value
LValue ^= Value
分配
乘并赋值
相除并赋值
取模和分配
添加和分配
相减并赋值
左移位,并将分配
右移位和分配
和分配
或和分配
XOR 并赋值
值 ? 值 :值
条件评估
值 , 值
评估所有值,然后丢弃最右侧的值之外的所有
- C++语言中的寄存器和伪寄存器
可以在C++表达式中使用寄存器和伪寄存器。必须在寄存器或伪寄存器之前添加at符号(@)。表达式计算器自动执行正确的强制转换。实际寄存器和整数值伪寄存器被转换为ulong64。所有地址都转换为puchar,$thread转换为ethread*,$proc转换为eprocess*,$teb转换为teb*,$peb转换为peb*。不能通过赋值或副作用运算符更改寄存器或伪寄存器。必须使用r(寄存器)命令更改这些值。
- C++表达式中的宏
可以在C++表达式中使用宏。必须在宏之前添加数字符号(#)。可以使用以下宏。这些宏与具有相同名称的Microsoft Windows宏具有相同的定义。(Windows宏在winnt.h中定义。)
宏 返回值 #CONTAINING_RECORD (地址,类型,字段)
返回给定类型的结构和结构中的字段的地址结构的实例的基址。
#FIELD_OFFSET (类型,字段)
返回命名的字段的字节偏移量中的已知的结构类型。
#RTL_CONTAINS_FIELD (Struct,大小,字段)
指示给定的字节大小是否包括所需的字段。
#RTL_FIELD_SIZE(Type, Field)
而无需字段的类型返回已知类型的结构中的字段的大小。
#RTL_NUMBER_OF(Array)
以静态方式调整大小的数组中返回元素的数。
#RTL_SIZEOF_THROUGH_FIELD(Type, Field)
通过和包括在指定的字段会返回已知类型的结构的大小。