Condividi tramite


Numeri e operatori MASM

In questo argomento viene descritto l'uso della sintassi delle espressioni MASM (Microsoft Macro Assembler) con gli strumenti di debug di Windows.

Il debugger accetta due tipi diversi di espressioni numeriche: espressioni C++ ed espressioni MASM. Ognuna di queste espressioni segue le proprie regole di sintassi per l'input e l'output.

Per altre informazioni sull'uso di ogni tipo di sintassi, vedere Valutazione di espressioni e ? (Evaluate Expression).

In questo esempio ? Il comando visualizza usando l'analizzatore di espressioni MASM il valore del registro del puntatore di istruzione.

0:000> ? @rip
Evaluate expression: 140709230544752 = 00007ff9`6bb40770

Impostare l'analizzatore di espressioni su MASM

Usare .expr (Choose Expression Evaluator) per vedere che cos'è l'analizzatore di espressioni predefinito e modificarlo in MASM.

0:000> .expr /s masm
Current expression evaluator: MASM - Microsoft Assembler expressions

Ora che l'analizzatore di espressioni predefinito è stato modificato, il comando ? (Evaluate Expression) può essere utilizzato per visualizzare le espressioni MASM. In questo esempio viene aggiunto il valore esadecimale pari a 8 al registro rip.

0:000> ? @rip + 8
Evaluate expression: 140709230544760 = 00007ff9`6bb40778

Il riferimento al registro di @rip è descritto in modo più dettagliato nella sintassi register.

Numeri nelle espressioni MASM del debugger

È possibile inserire numeri nelle espressioni MASM in base 16, 10, 8 o 2.

Usare il comando n (Imposta base numerica) per impostare la base predefinita su 16, 10 o 8. Tutti i numeri senza prefisso vengono quindi interpretati in questa base. È possibile eseguire l'override del radix predefinito specificando il prefisso 0x (esadecimale), il prefisso 0n (decimale), il prefisso 0t (ottale) o il prefisso 0y (binary).

È anche possibile specificare numeri esadecimali aggiungendo un h dopo il numero. È possibile usare lettere maiuscole o minuscole all'interno di numeri. Ad esempio, "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" e "4aB3H" hanno lo stesso significato.

Se non si aggiunge un numero dopo il prefisso in un'espressione, il numero viene letto come 0. Pertanto, è possibile scrivere 0 come 0, il prefisso seguito da 0 e solo il prefisso. Ad esempio, in esadecimale, "0", "0x0" e "0x" hanno lo stesso significato.

È possibile immettere valori esadecimali a 64 bit nel formato xxxxxxxx'xxxxxxxx . È anche possibile omettere l'accento grave ('). Se includi l'accento grave, l'estensione automatica del segno viene disabilitata.

In questo esempio viene illustrato come aggiungere un valore decimale, ottale e binario per registrare 10.

? @r10 + 0x10 + 0t10 + 0y10
Evaluate expression: 26 = 00000000`0000001a

Simboli nelle espressioni MASM del debugger

Nelle espressioni MASM il valore numerico di qualsiasi simbolo è il relativo indirizzo di memoria. A seconda del simbolo a cui fa riferimento il simbolo, questo indirizzo è l'indirizzo di una variabile globale, una variabile locale, una funzione, un segmento, un modulo o qualsiasi altra etichetta riconosciuta.

Per specificare il modulo a cui è associato l'indirizzo, includere il nome del modulo e un punto esclamativo (!) prima del nome del simbolo. Se il simbolo può essere interpretato come numero esadecimale, includere il nome del modulo e un punto esclamativo o solo un punto esclamativo, prima del nome del simbolo. Per altre informazioni sul riconoscimento dei simboli, vedere Sintassi dei simboli e corrispondenza dei simboli.

Usare due punti (::) o due caratteri di sottolineatura (__) per indicare i membri di una classe.

Utilizzare un accento grave (') o un apostrofo (') in un nome di simbolo solo se si aggiunge un nome di modulo e un punto esclamativo prima del simbolo.

Operatori numerici nelle espressioni MASM

È possibile modificare qualsiasi componente di un'espressione usando un operatore unario. È possibile combinare due componenti usando un operatore binario. Gli operatori unari hanno la precedenza sugli operatori binari. Quando si usano più operatori binari, gli operatori seguono le regole di precedenza fisse descritte nelle tabelle seguenti.

È sempre possibile usare le parentesi per sostituire le regole di precedenza.

Se una parte di un'espressione MASM è racchiusa tra parentesi e due segni di corrispondenza (@@) vengono visualizzati prima dell'espressione, l'espressione viene interpretata in base alle regole dell'espressione C++. Non è possibile aggiungere uno spazio tra i due segni e la parentesi di apertura. È anche possibile specificare l'analizzatore di espressioni usando @@c++( ... ) o @@masm( ... ).

Quando si eseguono calcoli aritmetici, l'analizzatore di espressioni MASM considera tutti i numeri e i simboli come tipi di ULONG64.

Gli operatori di indirizzi unari presuppongono DS come segmento predefinito per gli indirizzi. Le espressioni vengono valutate in ordine di precedenza dell'operatore. Se gli operatori adiacenti hanno la stessa precedenza, l'espressione viene valutata da sinistra a destra.

È possibile usare gli operatori unari seguenti.

Operatore Significato

+

Più unario

-

Meno unario

non

Restituisce 1 se l'argomento è zero. Restituisce zero per qualsiasi argomento diverso da zero.

ciao

16 bit più significativi

basso

bassi 16 bit

da

Byte di ordine basso dall'indirizzo specificato.

$pby

Uguale a ad eccezione del fatto che accetta un indirizzo fisico. È possibile leggere solo la memoria fisica che usa il comportamento di memorizzazione nella cache predefinito.

Wo

Parola in ordine basso dall'indirizzo specificato.

$pwo

Uguale a wo tranne che accetta un indirizzo fisico. È possibile leggere solo la memoria fisica che usa il comportamento di memorizzazione nella cache predefinito.

dwo

Parola doppia dall'indirizzo specificato.

$pdwo

Uguale a dwo , ad eccezione del fatto che accetta un indirizzo fisico. È possibile leggere solo la memoria fisica che usa il comportamento di memorizzazione nella cache predefinito.

qwo

Quadrupla parola dall'indirizzo indicato.

$pqwo

Uguale a qwo , ad eccezione del fatto che accetta un indirizzo fisico. È possibile leggere solo la memoria fisica che usa il comportamento di memorizzazione nella cache predefinito.

punto di interesse

Dati della dimensione di un puntatore dall'indirizzo specificato. La dimensione del puntatore è di 32 bit o 64 bit. Nel debug del kernel, queste dimensioni si basano sul processore del computer di destinazione . Di conseguenza, poi è l'operatore migliore da usare per ottenere dati delle dimensioni di un puntatore.

$ppoi

Uguale a poi , ad eccezione del fatto che accetta un indirizzo fisico. È possibile leggere solo la memoria fisica che usa il comportamento di memorizzazione nella cache predefinito.

Esempi

Nell'esempio seguente viene illustrato come usare poi per dereferenziare un puntatore per visualizzare il valore archiviato in tale posizione di memoria.

Determinare innanzitutto l'indirizzo di memoria di interesse. Ad esempio, è possibile esaminare la struttura del thread e decidere di voler visualizzare il valore di CurrentLocale.

0:000> dx @$teb
@$teb                 : 0x8eed57b000 [Type: _TEB *]
    [+0x000] NtTib            [Type: _NT_TIB]
    [+0x038] EnvironmentPointer : 0x0 [Type: void *]
    [+0x040] ClientId         [Type: _CLIENT_ID]
    [+0x050] ActiveRpcHandle  : 0x0 [Type: void *]
    [+0x058] ThreadLocalStoragePointer : 0x1f8f9d634a0 [Type: void *]
    [+0x060] ProcessEnvironmentBlock : 0x8eed57a000 [Type: _PEB *]
    [+0x068] LastErrorValue   : 0x0 [Type: unsigned long]
    [+0x06c] CountOfOwnedCriticalSections : 0x0 [Type: unsigned long]
    [+0x070] CsrClientThread  : 0x0 [Type: void *]
    [+0x078] Win32ThreadInfo  : 0x0 [Type: void *]
    [+0x080] User32Reserved   [Type: unsigned long [26]]
    [+0x0e8] UserReserved     [Type: unsigned long [5]]
    [+0x100] WOW32Reserved    : 0x0 [Type: void *]
    [+0x108] CurrentLocale    : 0x409 [Type: unsigned long]

"Il termine 'CurrentLocale' si trova a 0x108 oltre l'inizio del TEB."

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

Usare poi per dereferenziare l'indirizzo.

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

Il valore restituito 409 corrisponde al valore CurrentLocale nella struttura TEB.

In alternativa, usare punti e parentesi per dereferenziare l'indirizzo calcolato.

0:000> ? poi(@$teb + 0x108)
Evaluate expression: 1033 = 00000000`00000409

Utilizzare l'operatore unario by o wo per restituire un byte o una word dall'indirizzo di destinazione.

0:000> ? by(0000008e`ed57b108)
Evaluate expression: 9 = 00000000`00000009
0:000> ? wo(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409

Operatori binari

È possibile usare gli operatori binari seguenti. Gli operatori in ogni cella hanno la precedenza su quelli nelle celle inferiori. Gli operatori nella stessa cella hanno la stessa precedenza e vengono analizzati da sinistra a destra.

Operatore Significato

*

/

mod (o %)

Moltiplicazione

Divisione di interi

Modulo (resto)

+

-

Aggiunta

Sottrazione

<<

>>

>>>

Spostamento a sinistra

Spostamento logico a destra

Spostamento a destra aritmetico

= (o ==)

<

>

<=

>=

!=

Uguale a

Meno di

Maggiore di

Minore o uguale a

Maggiore o uguale a

Non uguale a

e (o &)

AND bit per bit

xor (o ^)

XOR bit per bit (OR esclusivo)

o (o |)

OR bit per bit

Gli operatori di confronto <, >, =, == e != restituiscono 1 se l'espressione è true o 0 se l'espressione è false. Un singolo segno di uguale (=) è uguale a un doppio segno di uguale (==). Non è possibile usare effetti collaterali o assegnazioni all'interno di un'espressione MASM.

Un'operazione non valida, come la divisione per zero, risulta in un errore di operando, che viene restituito alla finestra di comando del debugger.

È possibile verificare che il valore restituito corrisponda 0x409 usando l'operatore di confronto ==.

0:000> ? poi(@$teb + 0x108)==0x409
Evaluate expression: 1 = 00000000`00000001

Operatori non numerici nelle espressioni MASM

È anche possibile usare gli operatori aggiuntivi seguenti nelle espressioni MASM.

Operatore Significato

$fnsucc(FnAddress, RetVal, Flag)

Interpreta il valore RetVal come valore restituito per la funzione che si trova nell'indirizzo FnAddress . Se questo valore restituito viene qualificato come codice di esito positivo, $fnsucc restituisce TRUE. In caso contrario, $fnsucc restituisce FALSE.

Se il tipo restituito è BOOL, bool, HANDLE, HRESULT o NTSTATUS, $fnsucc riconosce correttamente se il valore restituito specificato viene qualificato come codice di esito positivo. Se il tipo restituito è un puntatore, tutti i valori diversi da NULL sono qualificati come codici di esito positivo. Per qualsiasi altro tipo, l'esito positivo viene definito dal valore di Flag. Se Flag è 0, un valore diverso da zero di RetVal indica un successo. Se Flag è 1, un valore pari a zero di RetVal indica successo.

$iment (indirizzo)

Restituisce l'indirizzo del punto di ingresso dell'immagine nell'elenco dei moduli caricati. Address specifica l'indirizzo di base dell'immagine PE (Portable Executable). La voce viene trovata cercando il punto di ingresso dell'immagine nell'intestazione PE dell'immagine specificata da Address.

È possibile usare questa funzione per entrambi i moduli già presenti nell'elenco dei moduli e per impostare punti di interruzione non risolti usando il comando bu .

$scmp("String1", "String2")

Restituisce -1, 0 o 1, come strcmp utilizzando la funzione C strcmp .

$sicmp("String1", "String2")

Valuta a -1, 0 o 1, come la funzione stricmp Microsoft Win32.

$spat("String", "Pattern")

Restituisce TRUE o FALSE a seconda che string corrisponda a Pattern. La corrispondenza non fa distinzione tra maiuscole e minuscole. Pattern può contenere un'ampia gamma di caratteri jolly e specificatori. Per ulteriori informazioni sulla sintassi, consultare Sintassi della stringa con caratteri jolly.

$vvalid(Address,Length)

Determina se l'intervallo di memoria che inizia in Indirizzo ed estende per i byte di lunghezza è valido. Se la memoria è valida, $vvalid restituisce 1. Se la memoria non è valida, $vvalid restituisce 0.

Esempi

Di seguito viene illustrato come usare l'analisi dell'intervallo di memoria valida intorno a un modulo caricato

Determinare innanzitutto l'indirizzo dell'area di interesse, ad esempio usando il comando lm (Elenca moduli caricati ).


0:000> lm
start             end                 module name
00007ff6`0f620000 00007ff6`0f658000   notepad    (deferred)
00007ff9`591d0000 00007ff9`5946a000   COMCTL32   (deferred)        
...

Usare $vvalid per controllare un intervallo di memoria.

0:000> ? $vvalid(0x00007ff60f620000, 0xFFFF)
Evaluate expression: 1 = 00000000`00000001

Usare $vvalid per verificare che questo intervallo più ampio sia un intervallo di memoria non valido.

0:000> ? $vvalid(0x00007ff60f620000, 0xFFFFF)
Evaluate expression: 0 = 00000000`00000000

Si tratta anche di un intervallo non valido.

0:000> ? $vvalid(0x0, 0xF)
Evaluate expression: 0 = 00000000`00000000

Utilizzare not per restituire zero quando l'intervallo di memoria è valido.

0:000> ? not($vvalid(0x00007ff60f620000, 0xFFFF))
Evaluate expression: 0 = 00000000`00000000

Usare $imnet per esaminare il punto di ingresso di COMCTL32, usando il comando lm in precedenza per determinare l'indirizzo. Inizia da 00007ff9'591d0000.

0:000> ? $iment(00007ff9`591d0000)
Evaluate expression: 140708919287424 = 00007ff9`59269e80

Disassemblare l'indirizzo restituito per esaminare il codice del punto di ingresso.

0:000> u 00007ff9`59269e80
COMCTL32!DllMainCRTStartup:
00007ff9`59269e80 48895c2408      mov     qword ptr [rsp+8],rbx
00007ff9`59269e85 4889742410      mov     qword ptr [rsp+10h],rsi
00007ff9`59269e8a 57              push    rdi

COMCTL32 viene visualizzato nell'output che conferma che si tratta del punto di ingresso per questo modulo.

Registri e Pseudo-Registers nelle espressioni MASM

È possibile usare registri e pseudoregistri nelle espressioni MASM. È possibile aggiungere il simbolo chiocciola (@) prima di registri e pseudoregistri. Il segno at fa in modo che il debugger accava più rapidamente il valore. Questo segno @ non è necessario per i registri basati su x86 più comuni. Per altri registri e pseudoregistri, è consigliabile aggiungere il simbolo chiocciola, ma non è effettivamente obbligatorio. Se si omette il simbolo per i registri meno comuni, il debugger tenta di analizzare il testo come numero esadecimale, quindi come simbolo e infine come registro.

È anche possibile usare un punto (.) per indicare il puntatore all'istruzione corrente. Non è consigliabile aggiungere un segno @ prima di questo periodo e non è possibile usare un punto come primo parametro del comando r. Questo periodo ha lo stesso significato del $ip pseudoregistro.

Per ulteriori informazioni sui registri e sugli pseudoregistri, vedere Sintassi dei registri e Pseudo-Register Sintassi.

Usare il comando r register per verificare che il valore del @rip registro sia 00007ffb'7ed00770.

0:000> r
rax=0000000000000000 rbx=0000000000000010 rcx=00007ffb7eccd2c4
rdx=0000000000000000 rsi=00007ffb7ed61a80 rdi=00000027eb6a7000
rip=00007ffb7ed00770 rsp=00000027eb87f320 rbp=0000000000000000
 r8=00000027eb87f318  r9=0000000000000000 r10=0000000000000000
r11=0000000000000246 r12=0000000000000040 r13=0000000000000000
r14=00007ffb7ed548f0 r15=00000210ea090000
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffb`7ed00770 cc              int     3

Questo stesso valore può essere visualizzato usando . punto di scelta rapida.

0:000> ? .
Evaluate expression: 140718141081456 = 00007ffb`7ed00770

È possibile verificare che tali valori siano tutti equivalenti e restituire zero se sono, usando questa espressione MASM.

0:000>  ? NOT(($ip = .) AND ($ip = @rip) AND (@rip =. ))
Evaluate expression: 0 = 00000000`00000000

Numeri di riga del codice sorgente nelle espressioni MASM

È possibile usare espressioni di file di origine e numeri di riga all'interno di espressioni MASM. È necessario racchiudere queste espressioni utilizzando accenti gravi ('). Per altre informazioni sulla sintassi, vedere Sintassi della riga di origine.

Vedere anche

Espressioni MASM e espressioni C++

Esempi di espressioni miste

Numeri e operatori C++

Estensione del segno

? (Valuta Espressione)