Sintassi indirizzo e intervallo di indirizzi
Esistono diversi modi per specificare gli indirizzi nel debugger.
Gli indirizzi sono normalmente indirizzi virtuali, tranne quando la documentazione indica in modo specifico un altro tipo di indirizzo. In modalità utente il debugger interpreta gli indirizzi virtuali in base alla directory di pagina del processo corrente. In modalità kernel il debugger interpreta gli indirizzi virtuali in base alla directory di pagina del processo specificato dal contesto del processo . È anche possibile impostare direttamente il contesto di indirizzo in modalità utente. Per altre informazioni sul contesto dell'indirizzo in modalità utente, vedere .context (Set User-Mode Address Context).
Nelle espressioni MASM è possibile usare l'operatore poi per dereferenziare qualsiasi puntatore. Ad esempio, se il puntatore all'indirizzo 0x0000008e'ed57b108 punta alla posizione dell'indirizzo 0x805287637256, i due comandi seguenti sono equivalenti.
0:000> dd 805287637256
0:000> dd poi(000000bb`7ee23108)
Esempio di indirizzo di memoria
Per visualizzare un esempio di utilizzo di poi, determinare l'offset per CurrentLocale del blocco di ambiente thread (TEB). Usare il comando dx per visualizzare @$teb, ovvero un esempio di pseudoregistrazioni, che contengono indirizzi comuni, ad esempio la posizione del contatore del programma corrente.
0:000> dx @$teb
@$teb : 0x1483181000 [Type: _TEB *]
...
[+0x108] CurrentLocale : 0x409 [Type: unsigned long]
CurrentLocale è +0x108 dall'inizio del TEB. Determinare quindi l'indirizzo di memoria di tale posizione.
0:000> ? @$teb + 0x108
Evaluate expression: 613867303176 = 0000008e`ed57b108
Usare il punto per dereferenziare tale indirizzo per vedere che contiene il valore CurrentLocale di 0x409.
0:000> ? poi(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
Nelle espressioni del debugger C++ i puntatori si comportano come puntatori in C++. Tuttavia, i numeri vengono interpretati come interi. Se è necessario rinviare un numero effettivo, potrebbe essere necessario eseguirne prima il cast, come illustrato nell'esempio seguente.
Per provare questa operazione, usare .expr per impostare l'analizzatore di espressioni su C++.
0:000> .expr /s C++
Current expression evaluator: C++ - C++ source expressions
Con l'analizzatore di espressioni impostato su C++, è possibile eseguire il cast usando long.
0:000> d *((long*)0x00000014`83181108 )
00000000`00000409 ???????? ???????? ???????? ????????
Per altre informazioni sul cast di valori numerici, vedere Numeri e operatori C++.
Se l'analizzatore di espressioni è impostato su c++, è possibile eseguire il wrapping del puntatore dei punti con @@masm(), per avere solo tale parte dell'espressione valutata dall'analizzatore di espressioni MASM.
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions
0:000> ? @@masm(poi(00000078`267d7108))
Evaluate expression: 1033 = 00000000`00000409
Per altre informazioni sui due analizzatori di espressioni, vedere Valutazione di espressioni.
È anche possibile indicare un indirizzo in un'applicazione specificando il nome del file di origine originale e il numero di riga. Per altre informazioni su come specificare queste informazioni, vedere Sintassi della riga di origine.
Intervalli di indirizzi
È possibile specificare un intervallo di indirizzi da una coppia di indirizzi o da un indirizzo e un numero di oggetti.
Per specificare un intervallo in base a una coppia di indirizzi, specificare l'indirizzo iniziale e l'indirizzo finale. Ad esempio, l'esempio seguente è un intervallo di 8 byte, a partire dall'indirizzo 0x00001000.
0x00001000 0x00001007
Per specificare un intervallo di indirizzi in base a un indirizzo e al conteggio degli oggetti, specificare un argomento indirizzo, la lettera L (maiuscola o minuscola) e un argomento valore. L'indirizzo specifica l'indirizzo iniziale. Il valore specifica il numero di oggetti da esaminare o visualizzare. Le dimensioni dell'oggetto dipendono dal comando. Ad esempio, se la dimensione dell'oggetto è 1 byte, l'esempio seguente è un intervallo di 8 byte, a partire dall'indirizzo 0x00001000.
0x00001000 L8
Tuttavia, se la dimensione dell'oggetto è una parola doppia (32 bit o 4 byte), i due intervalli seguenti danno un intervallo di 8 byte.
0x00001000 0x00001007
0x00001000 L2
Identificatore dell'intervallo di dimensioni L
Esistono due altri modi per specificare il valore (l'identificatore dell'intervallo di dimensioni L):
L?Le dimensioni (con un punto interrogativo) indicano lo stesso valore di LSize, ad eccezione di L?Le dimensioni rimuove il limite di intervallo automatico del debugger. In genere, esiste un limite di intervallo di 256 MB, perché gli intervalli più grandi sono errori tipografici. Se si vuole specificare un intervallo maggiore di 256 MB, è necessario usare L?Sintassi delle dimensioni.
L-Size (con un trattino) specifica un intervallo di lunghezza Dimensione che termina all'indirizzo specificato. Ad esempio, 80000000 L20 specifica l'intervallo compreso tra 0x80000000 e 0x8000001F e 80000000 L-20 specifica l'intervallo da 0x7FFFFFE0 a 0x7FFFFFFF.
Alcuni comandi che richiedono intervalli di indirizzi accettano un singolo indirizzo come argomento. In questa situazione, il comando usa un numero di oggetti predefinito per calcolare le dimensioni dell'intervallo. In genere, i comandi per i quali l'intervallo di indirizzi è il parametro finale consentono questa sintassi. Per la sintassi esatta e le dimensioni predefinite dell'intervallo per ogni comando, vedere gli argomenti di riferimento per ogni comando.
Esempio di intervallo di memoria di ricerca
Prima di tutto si determinerà l'indirizzo del registro del puntatore alle istruzioni rip usando l'analizzatore di espressioni MASM.
0:000> ? @rip
Evaluate expression: 140720561719153 = 00007ffc`0f180771
Verrà quindi eseguita una ricerca a partire da 00007ffc'0f180771, per 100000 usando il comando s (Memoria di ricerca). Specificare l'intervallo da cercare usando 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.
...
È anche possibile specificare lo stesso intervallo usando due indirizzi di memoria.
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.
...
Infine, è possibile eseguire ricerche indietro nell'intervallo di memoria usando il parametro 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
Esempio di memoria di unassemble
In questo esempio viene usato il comando u (unassemble) e il parametro L per annullare ilassembling di tre byte di codice.
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
In alternativa, specificare un intervallo di tre byte di memoria da annullare.
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
Modalità di indirizzo e supporto segmento
Nelle piattaforme basate su x86, CDB e KD supportano le modalità di indirizzamento seguenti. Queste modalità sono distinte dai prefissi.
Prefisso | Nome | Tipi di indirizzi |
---|---|---|
% | flat | Indirizzi a 32 bit (anche selettori a 16 bit che puntano a segmenti a 32 bit) e indirizzi a 64 bit nei sistemi a 64 bit. |
& | virtuale 86 | Indirizzi in modalità reale. Solo basato su x86. |
# | plain | Indirizzi in modalità reale. Solo basato su x86. |
La differenza tra le modalità normale e virtuale 86 è che un indirizzo a 16 bit normale usa il valore del segmento come selettore e cerca il descrittore di segmento. Ma un indirizzo virtuale 86 non usa i selettore e esegue invece il mapping direttamente in 1 MB inferiore.
Se si accede alla memoria tramite una modalità di indirizzamento che non è la modalità predefinita corrente, è possibile usare i prefissi della modalità indirizzo per eseguire l'override della modalità indirizzo corrente.
Argomenti di indirizzo
Gli argomenti di indirizzo specificano la posizione delle variabili e delle funzioni. La tabella seguente illustra la sintassi e il significato dei vari indirizzi che è possibile usare in CDB e KD.
Sintassi | Significato |
---|---|
offset |
Indirizzo assoluto nello spazio di memoria virtuale, con un tipo che corrisponde alla modalità di esecuzione corrente. Ad esempio, se la modalità di esecuzione corrente è a 16 bit, l'offset è a 16 bit. Se la modalità di esecuzione è segmentata a 32 bit, l'offset è segmentato a 32 bit. |
&[[ segmento:]] offset |
Indirizzo reale. basato su x86 e basato su x64. |
%segmento:[offset]] |
Indirizzo a 32 bit o a 64 bit segmentato. basato su x86 e basato su x64. |
%[[ offset]] |
Indirizzo assoluto (a 32 bit o a 64 bit) nello spazio di memoria virtuale. basato su x86 e basato su x64. |
name[[ +|- ]] offset |
Indirizzo flat a 32 bit o a 64 bit. il nome può essere qualsiasi simbolo. offset specifica l'offset . Questo offset può essere qualsiasi modalità di indirizzo indica il prefisso. Nessun prefisso specifica un indirizzo di modalità predefinito. È possibile specificare l'offset come valore positivo (+) o negativo (−). |
Usare il comando dg (Display Selector) per visualizzare le informazioni sul descrittore segmento.
Vedere anche
Per visualizzare informazioni sulla memoria, usare il comando !address .
Per cercare memoria, usare il comando s (Memoria di ricerca).
Per visualizzare il contenuto della memoria, usare il comando d, da, db, dc, dd, dD, df, dp, dq, du, dw (Memoria visualizzata).
Per informazioni su come visualizzare e modificare la memoria usando una finestra memoria, vedere Uso di una finestra memoria.
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per