Pseudo-Register Syntax

The debugger supports several pseudo-registers that hold certain values.

The debugger sets automatic pseudo-registers to certain useful values. User-defined pseudo-registers are integer variables that you can write to or read.

All pseudo-registers begin with a dollar sign ($). If you are using MASM syntax, you can add an at sign ( @ ) before the dollar sign. This at sign tells the debugger that the following token is a register or pseudo-register, not a symbol. If you omit the at sign, the debugger responds more slowly, because it has to search the whole symbol table.

For example, the following two commands produce the same output, but the second command is faster.

0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f

If a symbol exists with the same name as the pseudo-register, you must add the at sign.

If you are using C++ expression syntax, the at sign ( @ ) is always required.

The r (Registers) command is an exception to this rule. The debugger always interprets its first argument as a register or pseudo-register. (An at sign is not required or permitted.) If there is a second argument for the r command, it is interpreted according to the default expression syntax. If the default expression syntax is C++, you must use the following command to copy the $t2 pseudo-register to the $t1 pseudo-register.

0:000> r $t1 = @$t2

Automatic Pseudo-Registers

The debugger automatically sets the following pseudo-registers.

Pseudo-register Description

$ea

The effective address of the last instruction that was executed. If this instruction does not have an effective address, the debugger displays "Bad register error". If this instruction has two effective addresses, the debugger displays the first address.

$ea2

The second effective address of the last instruction that was executed. If this instruction does not have two effective addresses, the debugger displays "Bad register error".

$exp

The last expression that was evaluated.

$ra

The return address that is currently on the stack.

This address is especially useful in execution commands. For example, g @$ra continues until the return address is found (although gu (Go Up) is a more precise effective way of "stepping out" of the current function).

$ip

The instruction pointer register.

x86-based processors: The same as eip. Itanium-based processors: Related to iip. (For more information, see the note following this table.) x64-based processors: The same as rip.

$eventip

The instruction pointer at the time of the current event. This pointer typically matches $ip, unless you switched threads or manually changed the value of the instruction pointer.

$previp

The instruction pointer at the time of the previous event. (Breaking into the debugger counts as an event.)

$relip

An instruction pointer that is related to the current event. When you are branch tracing, this pointer is the pointer to the branch source.

$scopeip

The instruction pointer for the current local context (also known as the scope).

$exentry

The address of the entry point of the first executable of the current process.

$retreg

The primary return value register.

x86-based processors: The same as eax. Itanium-based processors: The same as ret0. x64-based processors: The same as rax.

$retreg64

The primary return value register, in 64-bit format.

x86 processor: The same as the edx:eax pair.

$csp

The current call stack pointer. This pointer is the register that is most representative of call stack depth.

x86-based processors: The same as esp. Itanium-based processors: The same as bsp. x64-based processors: The same as rsp.

$p

The value that the last d* (Display Memory) command printed.

$proc

The address of the current process (that is, the address of the EPROCESS block).

$thread

The address of the current thread. In kernel-mode debugging, this address is the address of the ETHREAD block. In user-mode debugging, this address is the address of the thread environment block (TEB).

$peb

The address of the process environment block (PEB) of the current process.

$teb

The address of the thread environment block (TEB) of the current thread.

$tpid

The process ID (PID) for the process that owns the current thread.

$tid

The thread ID for the current thread.

$dtid

$dpid

$dsid

$bpNumber

The address of the corresponding breakpoint. For example, $bp3 (or $bp03) refers to the breakpoint whose breakpoint ID is 3. Number is always a decimal number. If no breakpoint has an ID of Number, $bpNumber evaluates to zero. For more information about breakpoints, see Using Breakpoints.

$frame

The current frame index. This index is the same frame number that the .frame (Set Local Context) command uses.

$dbgtime

The current time, according to the computer that the debugger is running on.

$callret

The return value of the last function that .call (Call Function) called or that is used in an .fnret /s command. The data type of $callret is the data type of this return value.

$extret

$extin

$clrex

$lastclrex

Managed debugging only: The address of the last-encountered common language runtime (CLR) exception object.

$ptrsize

The size of a pointer. In kernel mode, this size is the pointer size on the target computer.

$pagesize

The number of bytes in one page of memory. In kernel mode, this size is the page size on the target computer.

$pcr

$pcrb

$argreg

$exr_chance

The chance of the current exception record.

$exr_code

The exception code for the current exception record.

$exr_numparams

The number of parameters in the current exception record.

$exr_param0

The value of Parameter 0 in the current exception record.

$exr_param1

The value of Parameter 1 in the current exception record.

$exr_param2

The value of Parameter 2 in the current exception record.

$exr_param3

The value of Parameter 3 in the current exception record.

$exr_param4

The value of Parameter 4 in the current exception record.

$exr_param5

The value of Parameter 5 in the current exception record.

$exr_param6

The value of Parameter 6 in the current exception record.

$exr_param7

The value of Parameter 7 in the current exception record.

$exr_param8

The value of Parameter 8 in the current exception record.

$exr_param9

The value of Parameter 9 in the current exception record.

$exr_param10

The value of Parameter 10 in the current exception record.

$exr_param11

The value of Parameter 11 in the current exception record.

$exr_param12

The value of Parameter 12 in the current exception record.

$exr_param13

The value of Parameter 13 in the current exception record.

$exr_param14

The value of Parameter 14 in the current exception record.

$bug_code

If a bug check has occurred, this is the bug code. Applies to live kernel-mode debugging and kernel crash dumps.

$bug_param1

If a bug check has occurred, this is the value of Parameter 1. Applies to live kernel-mode debugging and kernel crash dumps.

$bug_param2

If a bug check has occurred, this is the value of Parameter 2. Applies to live kernel-mode debugging and kernel crash dumps.

$bug_param3

If a bug check has occurred, this is the value of Parameter 3. Applies to live kernel-mode debugging and kernel crash dumps.

$bug_param4

If a bug check has occurred, this is the value of Parameter 4. Applies to live kernel-mode debugging and kernel crash dumps.

Some of these pseudo-registers might not be available in certain debugging scenarios. For example, you cannot use $peb, $tid, and $tpid when you are debugging a user-mode minidump or certain kernel-mode dump files. There will be situations where you can learn thread information from ~ (Thread Status) but not from $tid. You cannot use the $previp pseudo-register on the first debugger event. You cannot use the $relip pseudo-register unless you are branch tracing. If you use an unavailable pseudo-register, a syntax error occurs.

A pseudo-register that holds the address of a structure -- such as $thread, $proc, $teb, $peb, and $lastclrex -- will be evaluated according to the proper data type in the C++ expression evaluator, but not in the MASM expression evaluator. For example, the command ? $teb displays the address of the TEB, while the command ?? @$teb displays the entire TEB structure. For more information, see Evaluating Expressions.

On an Itanium-based processor, the iip register is bundle-aligned, which means that it points to slot 0 in the bundle containing the current instruction, even if a different slot is being executed. So iip is not the full instruction pointer. The $ip pseudo-register is the actual instruction pointer, including the bundle and the slot. The other pseudo-registers that hold address pointers ($ra, $retreg, $eventip, $previp, $relip, and $exentry) have the same structure as $ip on all processors.

You can use the r command to change the value of $ip. This change also automatically changes the corresponding register. When execution resumes, it resumes at the new instruction pointer address. This register is the only automatic pseudo-register that you can change manually.

Note   In MASM syntax, you can indicate the $ip pseudo-register with a period ( . ). You do not add an at sign (@) before this period, and do not use the period as the first parameter of the r command. This syntax is not permitted within a C++ expression.

Automatic pseudo-registers are similar to automatic aliases. But you can use automatic aliases together with alias-related tokens (such as ${ }), and you cannot use pseudo-registers with such tokens.

User-Defined Pseudo-Registers

There are 20 user-defined pseudo-registers ($t0, $t1, ..., $t19). These pseudo-register are variables that you can read and write through the debugger. You can store any integer value in these pseudo-registers. They can be especially useful as loop variables.

To write to one of these pseudo-registers, use the r (Registers) command, as the following example shows.

0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)

Like all pseudo-registers, you can use the user-defined pseudo-register in any expression, as the following example shows.

0:000> bp $t3 
0:000> bp @$t4 
0:000> ?? @$t1 + 4*@$t2 

A pseudo-register is always typed as an integer, unless you use the ? switch together with the r command. If you use this switch, the pseudo-register acquires the type of whatever is assigned to it. For example, the following command assigns the UNICODE_STRING** type and the 0x0012FFBC value to $t15.

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

User-defined pseudo-registers use zero as the default value when the debugger is started.

Note  The aliases $u0, $u1, ..., $u9 are not pseudo-registers, despite their similar appearance. For more information about these aliases, see Using Aliases.

Example

The following example sets a breakpoint that is hit every time that the current thread calls NtOpenFile. But this breakpoint is not hit when other threads call NtOpenFile.

kd> bp /t @$thread nt!ntopenfile

Example

The following example executes a command until the register holds a specified value. First, put the following code for conditional stepping in a script file named "eaxstep".

.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }

Next, issue the following command.

t "$<eaxstep"

The debugger performs a step and then runs your command. In this case, the debugger runs the script, which either displays 1234 or repeats the process.