共用方式為


Pseudo-Register 語法

偵錯工具支援數個保留特定值的虛擬暫存器。

調試程式會將 自動虛擬緩存器 設定為特定實用值。 使用者定義的虛擬緩存器 是您可以寫入或讀取的整數變數。

所有虛擬暫存器都以美元符號 ()$ 開頭。 如果您使用 MASM 語法,您可以在美元符號之前新增 at 符號 ( @ )。 這個@符號告知除錯器下列標記是暫存器或偽暫存器,而不是符號。 如果您省略 at 符號,偵錯工具的回應速度會更慢,因為它必須搜尋整個符號數據表。

例如,下列兩個命令會產生相同的輸出,但第二個命令更快。

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

如果存在與虛擬暫存器同名的符號,則必須新增 at 符號。

如果您使用 C++ 運算式語法,則一律需要 at 符號 ( @ )。

r (暫存器) 指令是此規則的例外。 偵錯工具一律會將其第一個引數解譯為暫存器或虛擬暫存器。 不需要或不允許使用 at 符號。如果 r 指令有第二個引數,則會按照預設表示式語法來解譯。 如果預設運算式語法是 C++,您必須使用下列命令將 $t 2 虛擬暫存器複製到 $t 1 虛擬暫存器。

0:000> r $t1 = @$t2

自動 Pseudo-Registers

偵錯工具會自動設定下列虛擬暫存器。

虛擬暫存器 說明

$ea

最後執行指令的有效位址。 如果此指令沒有有效位址,偵錯工具會顯示「錯誤暫存器錯誤」。 如果此指令有兩個有效位址,偵錯工具會顯示第一個位址。

$ea 2

最後一個執行指令的第二個有效位址。 如果此指令沒有兩個有效位址,偵錯工具會顯示「Bad register error」。

$exp

評估的最後一個運算式。

$ra

目前在堆疊上的傳回位址。

此位址在執行命令中特別有用。 例如,g @$ra 一直持續到找到傳回位址為止(雖然 gu(Go Up) 是更精確有效的方式來「退出」當前函數)。

$ip

指令指標緩存器。

基於 x86 的處理器:eip 相同。 基於 Itanium 的處理器:iip 有關。 (如需詳細資訊,請參閱此表後面的附註。)x64 位元處理器:rip 相同。

$eventip

目前事件發生時的指示指標。 此指標通常符合 $ip,除非您切換執行緒或手動變更指令指標的值。

$previp

前一個事件發生時的指示指標。 (闖入偵錯工具會算作事件。)

$relip

與現行事件相關的指令指標。 當您進行分支追蹤時,此指標是分支來源的指標。

$scopeip

目前 本機內容 的指令指標 (也稱為 範圍) 。

$exentry

目前進程的第一個可執行檔的進入點位址。

$retreg

主要傳回值寄存器。

基於 x86 的處理器:eax 相同。 基於 Itanium 的處理器:ret0 相同。 x64 型處理器:rax 相同。

$retreg 64

主要傳回值緩存器,格式為64位。

x86 處理器:edx:eax 配對相同。

$csp

目前的呼叫堆疊指標。 此指標是最能代表呼叫堆疊深度的暫存器。

基於 x86 的處理器:esp 一樣。 基於 Itanium 的處理器:bsp 相同。 x64 型處理器:rsp 相同。

$p

最後 d*(顯示記憶體)命令 列印的值。

$proc

現行處理程序的位址 (亦即 EPROCESS 區塊的位址)。

$thread

目前執行緒的位址。 在核心模式偵錯中,此位址是 ETHREAD 區塊的位址。 在使用者模式偵錯中,此位址是執行緒環境區塊 (TEB) 的位址。

$peb

目前進程的進程環境區塊 (PEB) 位址。

$teb

目前執行緒的執行緒環境區塊 (TEB) 位址。

$tpid

擁有目前執行緒之進程的進程識別碼 (PID)。

$tid

目前執行緒的識別碼。

$dtid

$dpid

$dsid

$bp號碼

對應岔斷點的位址。 例如, $bp 3 (或 $bp 03) 是指岔斷點 ID 為 3 的岔斷點。 數字 始終是十進制數。 如果沒有中斷點的 ID 為 Number,則 $bpNumber 的值會被評估為零。 如需中斷點的詳細資訊,請參閱 使用中斷點

$frame

目前的框架索引。 此索引與 .frame (設定本機內容) 命令使用的相同幀編號。

$dbgtime

目前的時間是根據正在執行偵錯工具的電腦而定。

$callret

最後一個由 .call(呼叫函式) 呼叫的函式的回傳值,或者用於 .fnret /s 命令的函式。 $callret的資料類型是此傳回值的資料類型。

$extret

$extin

$clrex

$lastclrex

僅限受控偵錯: 上次遇到的共用語言執行階段 (CLR) 例外狀況物件的位址。

$ptrsize

指標的大小。 在核心模式中,此大小是目標電腦上的指標大小。

$pagesize

一頁記憶體中的位元組數。 在核心模式中,此大小是目標電腦上的頁面大小。

$pcr

$pcrb

$argreg

$exr_機率

目前例外狀況記錄的機率。

$exr_code

目前例外狀況記錄的例外狀況碼。

$exr_numparams

目前異常狀況記錄中的參數數目。

$exr_param0

目前異常狀況記錄中參數 0 的值。

$exr_param1

目前異常狀況記錄中參數 1 的值。

$exr_param2

目前例外狀況記錄中參數 2 的值。

$exr_param3

目前例外狀況記錄中參數 3 的值。

$exr_param4

目前例外狀況記錄中參數 4 的值。

$exr_param5

目前例外狀況記錄中參數 5 的值。

$exr_param6

目前異常狀況記錄中參數 6 的值。

$exr_param7

目前異常狀況記錄中參數 7 的值。

$exr_param8

目前異常狀況記錄中參數 8 的值。

$exr_param9

目前例外狀況記錄中參數 9 的值。

$exr_param10

目前例外狀況記錄中參數 10 的值。

$exr_param11

目前異常狀況記錄中參數 11 的值。

$exr_param12

目前異常狀況記錄中參數 12 的值。

$exr_param13

目前例外狀況記錄中參數 13 的值。

$exr_param14

目前異常狀況記錄中參數 14 的值。

$bug_code

如果發生錯誤檢查,則這是錯誤代碼。 適用於即時核心模式偵錯和核心損毀傾印。

$bug_param1

如果發生錯誤檢查,則這是參數 1 的值。 適用於即時核心模式除錯和核心崩潰轉儲。

$bug_param2

如果發生錯誤檢查,則這是參數 2 的值。 適用於即時核心模式偵錯和核心崩潰轉儲。

$bug_param3

如果錯誤檢查已發生,則參數 3 的值為此。 適用於即時核心模式偵錯和核心損毀傾印。

$bug_param4

如果發生錯誤檢查,這是參數 4 的值。 適用於即時核心模式偵錯和核心當機傾印。

其中一些虛擬暫存器在某些調試情境中可能無法使用。 例如,當您偵錯使用者模式小型傾印或特定核心模式傾印檔案時,您無法使用 $peb$tid$tpid 。 在某些情況下,您可以從 ~(線程狀態) 中學習線程信息,但不能從 $tid中學習線程信息。 您無法在第一個偵錯工具事件上使用 $previp 虛擬暫存器。 除非您進行分支追蹤,否則您無法使用 $relip 虛擬暫存器。 如果您使用不可用的虛擬暫存器,則會發生語法錯誤。

保存結構位址的虛擬暫存器 (例如 $thread$proc$teb$peb$lastclrex ) 將根據 C++ 運算式評估器中的適當資料類型進行評估,但不會在 MASM 運算式評估器中進行評估。 例如,指令 ? $teb 會顯示 TEB 的位址,而指令 ?? @$teb 會顯示整個 TEB 結構。 如需詳細資訊,請參閱 評估運算式

在 Itanium 處理器上,iip 暫存器是 組塊對齊的,這表示它會指向包含目前指令的組塊中的插槽 0,即使執行的是組塊中的不同插槽。 所以 iip 不是完整的指令指標。 $ip偽暫存器是實際的指令指標,包括捆綁包和插槽。 保存位址指標的其他虛擬暫存器 ($ra$retreg$eventip$previp$relip$exentry) 具有與所有處理器上的 $ip 相同的結構。

您可以使用 r 指令來變更 $ip 的值。 此變更也會自動變更對應的暫存器。 執行恢復時,它會從新的指令指標位址開始。 此暫存器是唯一可以手動變更的自動虛擬暫存器。

注意 在MASM語法中,可以用句點(.)來表示$ip虛擬暫存器。 您不會在此句點之前新增 at 符號 (@) ,也不要使用句點作為 r 指令的第一個參數。 C++ 運算式中不允許使用此語法。

自動偽暫存器類似於 自動別名。 但您可以將自動別名與與別名相關的標記(例如 ${ })一起使用,並且不能將虛擬寄存器與此類標記一起使用。

User-Defined Pseudo-Registers

有 20 個使用者定義的虛擬暫存器 ($t 0$t 1, ..., $t 19)。 這些虛擬暫存器是您可以透過偵錯工具讀取和寫入的變數。 您可以在這些虛擬暫存器中儲存任何整數值。 它們作為循環變數特別有用。

若要寫入其中一個虛擬暫存器,請使用 r (暫存器) 命令,如下列範例所示。

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

如同所有虛擬暫存器,您可以在任何運算式中使用使用者定義的虛擬暫存器,如下列範例所示。

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

偽暫存器預設為整數類型,除非您將 開關與 r 命令一起使用。 如果您使用此開關,虛擬暫存器會取得指派給它的任何類型的類型。 例如,下列指令會將UNICODE_STRING**類型和0x0012FFBC值指派給 $t 15

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

使用者定義的虛擬暫存器會在偵錯工具啟動時使用零作為預設值。

注意 別名 $u0$u1、...、$u9 不是偽寄存器,儘管它們的外觀相似。 如需這些別名的詳細資訊,請參閱 使用別名

範例

下列範例會設定一個中斷點,這個中斷點在目前執行緒每次呼叫 NtOpenFile 時會被觸發。 但當其他執行線呼叫 NtOpenFile 時,此中斷點不會被觸發。

kd> bp /t @$thread nt!ntopenfile

範例

下列範例會執行命令,直到暫存器保留指定的值為止。 首先,將以下條件步進的程式碼放入名為「eaxstep」的腳本檔案中。

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

接下來,發出以下命令。

t "$<eaxstep"

偵錯工具會執行一個步驟,然後執行您的命令。 在此情況下,偵錯工具會執行腳本,以顯示 1234 或重複過程。