地址和地址範圍語法

有數種方式可以在調試程式中指定位址。

位址通常是 虛擬位址,除非文件特別指出另一種位址。 在使用者模式中,調試程式會根據 目前進程的頁面目錄來解譯虛擬位址。 在核心模式中,調試程式會根據 進程內容 所指定的進程頁面目錄來解譯虛擬位址。 您也可以直接設定 使用者模式地址內容。 如需使用者模式地址內容的詳細資訊,請參閱 .context (設定 User-Mode 位址內容)

在MASM運算式中,您可以使用 poi 運算符來取值任何指標。 例如,如果位址0x0000008e『ed57b108 的指標指向位址位置0x805287637256,則下列兩個命令相等。

0:000> dd 805287637256
0:000> dd poi(000000bb`7ee23108)

顯示記憶體位址範例

若要查看使用 poi 的範例,請判斷線程環境區塊 的 CurrentLocale 位移, (TEB) 。 使用 dx 命令來顯示 @$teb,這是 虛擬緩存器範例,可保存常見位址,例如目前的程式計數器位置。

0:000> dx @$teb
@$teb                 : 0x1483181000 [Type: _TEB *]

...

    [+0x108] CurrentLocale    : 0x409 [Type: unsigned long]

CurrentLocale 是從 TEB 開始的 +0x108。 接下來,判斷該位置的記憶體位址。

0:000> ? @$teb + 0x108
Evaluate expression: 613867303176 = 0000008e`ed57b108

使用 poi 來取值該位址,以查看其包含 currentLocale 值的 0x409。

0:000> ? poi(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409

在 C++ 調試程式運算式中,指標的行為就像 C++ 中的指標。 不過,數位會解譯為整數。 如果您必須延遲實際數位,您可能需要先轉換它,如下列範例所示。

若要嘗試這樣做,請使用 .expr 將運算式評估工具設定為 C++。

0:000> .expr /s C++
Current expression evaluator: C++ - C++ source expressions

當表達式評估工具設定為 C++ 時,我們可以使用 long 進行轉換。

0:000> d *((long*)0x00000014`83181108 ) 
00000000`00000409  ???????? ???????? ???????? ????????

如需轉換數值的詳細資訊,請參閱 C++ 數位和運算元

如果表達式評估工具設定為 c++,我們可以將 poi 指標包裝為 @@masm () ,讓 MASM 運算式評估工具評估的運算式只有該部分。

0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions

0:000> ? @@masm(poi(00000078`267d7108))
Evaluate expression: 1033 = 00000000`00000409

如需兩個表達式評估工具的詳細資訊,請參閱 評估表達式

您也可以指定原始原始程式檔名稱和行號,以指出應用程式中的位址。 如需如何指定這項資訊的詳細資訊,請參閱 源行語法

位址範圍

您可以透過一對位址或位址和物件計數來指定位址範圍。

若要依一對位址指定範圍,請指定起始地址和結束位址。 例如,下列範例是從位址0x00001000開始的8個字節範圍。

0x00001000  0x00001007

若要依位址和物件計數指定位址範圍,請指定位址自變數、字母 L (大寫或小寫) ,以及值自變數。 位址會指定起始位址。 值會指定要檢查或顯示的物件數目。 物件的大小取決於 命令。 例如,如果物件大小為1位元組,則下列範例是8個字節的範圍,從位址0x00001000開始。

0x00001000  L8

不過,如果物件大小是雙字 (32 位或 4 個字節) ,則下列兩個範圍各提供 8 位元組的範圍。

0x00001000  0x00001007
0x00001000  L2

L 大小範圍規範

有兩種方式可以指定 L Size 範圍規範 (值) :

  • 我?大小 (加上問號) 表示與 L大小相同,但 L 除外?大小 會移除調試程式的自動範圍限制。 一般而言,範圍限製為 256 MB,因為較大的範圍是印刷錯誤。 如果您想要指定大於 256 MB 的範圍,則必須使用 L?大小 語法。

  • L-Size (與連字元) 指定以指定位址結尾的長度 Size 範圍。 例如, 80000000 L20 指定從0x80000000到0x8000001F的範圍,而 80000000 L-20 指定從0x7FFFFFE0到0x7FFFFFFF的範圍。

某些要求位址範圍的命令會接受單一位址做為自變數。 在此情況下,此命令會使用一些默認物件計數來計算範圍的大小。 一般而言,位址範圍是最後一個參數的命令允許此語法。 如需每個命令的確切語法和預設範圍大小,請參閱每個命令的參考主題。

搜尋記憶體範圍範例

首先,我們將使用MASM表達式評估工具來判斷擷取指令指標緩存器的位址。

0:000> ? @rip 
Evaluate expression: 140720561719153 = 00007ffc`0f180771

然後,我們會使用 s (Search Memory) 命令,從 00007ffc『0f180771 開始搜尋 1000000。 我們會使用 L100000 指定要搜尋的範圍。

0:000> s -a 00007ffc`0f180771 L100000 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec
00007ffc`0f1d4ad2  6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00  ntdll\ldrsnap.c.
...

我們也可以使用兩個記憶體位址來指定相同的範圍,就像這樣。

0:000> s -a 0x00007ffc`0f180771 0x00007ffc`0f280771 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec
00007ffc`0f1d4ad2  6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00  ntdll\ldrsnap.c.
...

最後,我們可以使用 L- length 參數,在記憶體範圍中向後搜尋。

0:000> s -a 00007ffc`0f1d4ad2 L-100000 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec

Unassemble 記憶體範例

這個範例會使用 u (unassemble) 命令和 L 參數來取消組合三個字節的程式代碼。

0:000> u 00007ffc`0f1d48fa L3
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e              outs    dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464            je      ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c              ins     byte ptr [rdi],dx

或者,指定三個字節的記憶體範圍,以便像這樣取消組譯。

0:000> u 00007ffc`0f1d48fa 00007ffc`0f1d48fd
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e              outs    dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464            je      ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c              ins     byte ptr [rdi],dx

位址模式和區段支援

在 x86 型平臺上,CDB 和 KD 支援下列尋址模式。 這些模式會以其前置詞來區別。

前置詞 名稱 位址類型
% 沼地 32 位位址 (16 位選取器,指向 32 位區段) 和 64 位系統上的 64 位位址。
& virtual 86 實際模式位址。 僅限 x86 型。
# plain 實際模式位址。 僅限 x86 型。

純文本和虛擬 86 模式之間的差異在於,一般 16 位位址會使用區段值作為選取器,並查閱區段描述元。 但虛擬 86 位址不會使用選取器,而是直接對應到較低的 1 MB。

如果您透過不是目前預設模式的尋址模式來存取記憶體,您可以使用位址模式前置詞來覆寫目前的位址模式。

位址自變數

位址自變數會指定變數和函式的位置。 下表說明您可以在CDB和 KD 中使用的各種位址文法和意義。

語法 意義

Offset

虛擬記憶體空間中的絕對位址,具有對應至目前執行模式的類型。 例如,如果目前的執行模式為16位,則位移為16位。 如果執行模式為32位區隔,則位移為32位區段。

&[[ segment:]] offset

實際位址。 x86 型和 x64 型。

%segment:[[ offset]]

分段 32 位或 64 位位址。 x86 型和 x64 型。

%[[ offset]]

虛擬記憶體空間中的絕對位址 (32 位或 64 位) 。 x86 型和 x64 型。

name[[ +|\ ]] 位移

一般32位或64位位址。 name 可以是任何符號。 offset 會指定位移。 這個位移可以是其前置詞所指出的任何位址模式。 沒有前置詞指定預設模式位址。 您可以將位移指定為正 (+) 或負數 (-) 值。

使用 dg (顯示選取器) 命令來檢視區段描述元資訊。

另請參閱

若要顯示記憶體的相關信息,請使用 !address 命令。

若要搜尋記憶體,請使用 (Search Memory) 命令。

若要顯示記憶體的內容,請使用 d、da、db、dc、dd、dD、df、dp、dq、du、dw (Display Memory) 命令。

如需如何使用記憶體視窗檢視和編輯記憶體的資訊,請參閱 使用記憶體視窗