Share via


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.