Condividi tramite


Operatori e numeri 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 l'oggetto ? il comando visualizza il valore del registro del puntatore all'istruzione usando l'analizzatore di espressioni MASM.

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, l'oggetto ? (Evaluate Expression) è possibile usare il comando per visualizzare 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 numeri) per impostare il numero predefinito 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 si include l'accento grave, l'estensione del segno automatico è 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

not

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

Ciao

16 bit alti

low

16 bit bassi

by

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

Parola quad dall'indirizzo specificato.

$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 di dimensioni del 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, l'operatore migliore da usare se si desiderano dati di dimensioni del 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]

CurrentLocale si trova 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 gli operatori unari by o wo per restituire un byte o una parola 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

Minore di

Maggiore di

Minore di o uguale a

Maggiore di o uguale a

Diverso da

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 zero 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, ad esempio divisione per zero, genera un errore di "Operando" viene restituita 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 FAL edizione Standard.

Se il tipo restituito è BOOL, bool, HANDLE, HRESULT o NTSTATUS, $fnsucc riconosce correttamente se il valore restituito specificato è 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, il valore RetVal è diverso da zero. Se Flag è 1, il valore RetVal è zero.

$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 dell'immagine PE 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 usando lafunzione strcmp C.

$sicmp("String1", "String2")

Restituisce -1, 0 o 1, ad esempio la funzione stricmp Microsoft Win32 .

$spat("String", "Pattern")

Restituisce TRUE o FAL edizione Standard a seconda che string corrisponda al criterio. La corrispondenza non fa distinzione tra maiuscole e minuscole. Il criterio può contenere un'ampia gamma di caratteri jolly e identificatori. Per altre informazioni sulla sintassi, vedere Sintassi stringhe 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 usato in precedenza il comando lm 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.

Registra e pseudoregistri nelle espressioni MASM

È possibile usare registri e pseudoregistri nelle espressioni MASM. È possibile aggiungere un simbolo all'indirizzo (@) prima di tutti i registri e gli 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 alla firma, 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 altre informazioni sui registri e gli pseudoregistri, vedere Register Syntax and Pseudo-Register Syntax.

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 di origine nelle espressioni MASM

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

Vedi anche

Espressioni MASM e espressioni C++

Esempi di espressioni miste

Numeri e operatori C++

Firma estensione

? (Evaluate Expression)