共用方式為


地址和地址範圍語法

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

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

在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 來取值該位址,以查看其包含 0x409 的 CurrentLocale 值。

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

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

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

位址範圍

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

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

0x00001000  0x00001007

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

0x00001000  L8

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

0x00001000  0x00001007
0x00001000  L2

L 大小範圍規範

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

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

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

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

搜尋記憶體範圍範例

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

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

然後,我們將使用 s (Search Memory) 命令,從 00007ffc'0f180771 開始搜尋 100000。 我們會指定要使用 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 長度參數來向後搜尋記憶體範圍。

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 支援下列尋址模式。 這些模式會以其前置詞來區分。

Prefix 名稱 位址類型
% flat 32 位位址(也指向 32 位區段的 16 位選取器)和 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[[ +|\ ]] offset

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

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

另請參閱

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

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

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

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