地址和地址範圍語法
有數種方式可以在調試程式中指定位址。
位址通常是 虛擬位址,除非文件特別指出另一種位址。 在使用者模式中,調試程式會根據 目前進程的頁面目錄來解譯虛擬位址。 在核心模式中,調試程式會根據 進程內容 所指定的進程頁面目錄來解譯虛擬位址。 您也可以直接設定 使用者模式地址內容。 如需使用者模式地址內容的詳細資訊,請參閱 .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) 命令。
如需如何使用記憶體視窗檢視和編輯記憶體的資訊,請參閱 使用記憶體視窗。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應