Freigeben über


MASM-Nummern und -Operatoren

In diesem Thema wird die Verwendung der Microsoft Macro Assembler (MASM)-Ausdruckssyntax mit den Windows-Debugtools beschrieben.

Der Debugger akzeptiert zwei verschiedene Arten von numerischen Ausdrücken: C++-Ausdrücke und MASM-Ausdrücke. Jeder dieser Ausdrücke folgt seinen eigenen Syntaxregeln für Eingabe und Ausgabe.

Weitere Informationen dazu, wann die einzelnen Syntaxtypen verwendet werden, finden Sie unter Auswerten von Ausdrücken und ? (Ausdruck auswerten).

In diesem Beispiel ist der ? zeigt den Wert des Befehlszeigerregisters mithilfe des MASM-Ausdrucksauswerters an.

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

Festlegen der Ausdrucksauswertung auf MASM

Verwenden Sie expr (Ausdrucksauswertung auswählen), um den Standardauswertungsauswerter zu ermitteln und in MASM zu ändern.

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

Nachdem der Standardauswertungsauswertungsauswerter geändert wurde, ist der ? (Ausdruck auswerten) kann zum Anzeigen von MASM-Ausdrücken verwendet werden. In diesem Beispiel wird dem Rip-Register der Hexwert 8 hinzugefügt.

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

Die Registerreferenz von @rip wird ausführlicher unter Registersyntax beschrieben.

Zahlen in Debugger-MASM-Ausdrücken

Sie können Zahlen in MASM-Ausdrücken in Basis 16, 10, 8 oder 2 einfügen.

Verwenden Sie den Befehl n (Anzahlbasis festlegen), um den Standardradix auf 16, 10 oder 8 festzulegen. Alle nicht vorfixierten Zahlen werden dann in dieser Basis interpretiert. Sie können das Standardradix überschreiben, indem Sie das Präfix 0x (hexadezimal), das Präfix 0n (dezimal), das Präfix 0t (oktal) oder das Präfix 0y (binär) angeben.

Sie können auch hexadezimale Zahlen angeben, indem Sie nach der Zahl ein h hinzufügen. Sie können Groß- oder Kleinbuchstaben in Zahlen verwenden. Beispielsweise haben "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" und "4aB3H" dieselbe Bedeutung.

Wenn Sie keine Zahl nach dem Präfix in einem Ausdruck hinzufügen, wird die Zahl als 0 gelesen. Daher können Sie 0 als 0, das Präfix gefolgt von 0 und nur das Präfix schreiben. Beispielsweise haben "0", "0x0" und "0x" in hexadezimal die gleiche Bedeutung.

Sie können hexadezimale 64-Bit-Werte im Format xxxxxxxx'xxxxxxxx eingeben. Sie können auch den Grabakzent (') weglassen. Wenn Sie den Grabakzent einschließen, ist die automatische Vorzeichenerweiterung deaktiviert.

In diesem Beispiel wird gezeigt, wie Sie einen Dezimal-, Oktal- und Binärwert hinzufügen, um 10 zu registrieren.

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

Symbole in Debugger-MASM-Ausdrücken

In MASM-Ausdrücken ist der numerische Wert eines beliebigen Symbols die Speicheradresse. Je nachdem, worauf sich das Symbol bezieht, ist diese Adresse die Adresse einer globalen Variablen, einer lokalen Variablen, einer Funktion, eines Segments, eines Moduls oder einer anderen erkannten Bezeichnung.

Um anzugeben, welchem Modul die Adresse zugeordnet ist, fügen Sie den Modulnamen und ein Ausrufezeichen (!) vor den Namen des Symbols ein. Wenn das Symbol als hexadezimale Zahl interpretiert werden könnte, schließen Sie den Modulnamen und ein Ausrufezeichen oder nur ein Ausrufezeichen vor dem Symbolnamen ein. Weitere Informationen zur Symbolerkennung finden Sie unter Symbolsyntax und Symbolabgleich.

Verwenden Sie zwei Doppelpunkte (::) oder zwei Unterstriche (__), um die Member einer Klasse anzugeben.

Verwenden Sie einen Grabakzent (') oder einen Apostroph (') in einem Symbolnamen nur, wenn Sie einen Modulnamen und ein Ausrufezeichen vor dem Symbol hinzufügen.

Numerische Operatoren in MASM-Ausdrücken

Sie können jede Komponente eines Ausdrucks mit einem unären Operator ändern. Sie können zwei beliebige Komponenten mit einem binären Operator kombinieren. Unäre Operatoren haben Vorrang vor binären Operatoren. Wenn Sie mehrere binäre Operatoren verwenden, befolgen die Operatoren die festen Rangfolgeregeln, die in den folgenden Tabellen beschrieben werden.

Sie können immer Klammern verwenden, um Rangfolgeregeln außer Kraft zu setzen.

Wenn ein Teil eines MASM-Ausdrucks in Klammern eingeschlossen ist und vor dem Ausdruck zwei Zeichen (@@) angezeigt werden, wird der Ausdruck gemäß den C++-Ausdrucksregeln interpretiert. Zwischen den beiden Zeichen und der öffnenden Klammer kann kein Leerzeichen hinzugefügt werden. Sie können den Ausdrucksauswerter auch mit @@c++( ... ) oder @@masm( ... ) angeben.

Wenn Sie arithmetische Berechnungen durchführen, behandelt der MASM-Ausdrucksauswerter alle Zahlen und Symbole als ULONG64 Typen.

Unäre Adressoperatoren gehen davon aus, dass DS das Standardsegment für Adressen ist. Ausdrücke werden in der Reihenfolge der Operatorrangfolge ausgewertet. Wenn benachbarte Operatoren die gleiche Priorität haben, wird der Ausdruck von links nach rechts ausgewertet.

Sie können die folgenden unären Operatoren verwenden.

Operator Bedeutung

+

Unäres Plus

-

Unäres Minus

not

Gibt 1 zurück, wenn das Argument 0 ist. Gibt null für ein beliebiges Nonzero-Argument zurück.

Hallo

Hohe 16 Bits

Niedrig

Niedrige 16 Bits

by

Byte mit niedriger Reihenfolge aus der angegebenen Adresse.

$pby

Identisch mit der Ausnahme , dass es eine physische Adresse benötigt. Nur physischer Arbeitsspeicher, der das Standardcacheverhalten verwendet, kann gelesen werden.

wo

Wort mit niedriger Reihenfolge aus der angegebenen Adresse.

$pwo

Identisch mit wo , außer dass es eine physische Adresse benötigt. Nur physischer Arbeitsspeicher, der das Standardcacheverhalten verwendet, kann gelesen werden.

dwo

Double-Word aus der angegebenen Adresse.

$pdwo

Identisch mit dwo , außer dass es eine physische Adresse benötigt. Nur physischer Arbeitsspeicher, der das Standardcacheverhalten verwendet, kann gelesen werden.

qwo

Quad-Word aus der angegebenen Adresse.

$pqwo

Identisch mit qwo , außer dass es eine physische Adresse benötigt. Nur physischer Arbeitsspeicher, der das Standardcacheverhalten verwendet, kann gelesen werden.

Poi

Daten in Zeigergröße von der angegebenen Adresse. Die Zeigergröße beträgt 32 Bit oder 64 Bit. Beim Kerneldebuggen basiert diese Größe auf dem Prozessor des Zielcomputers . Daher ist poi der beste Operator, der verwendet werden kann, wenn Sie Daten in Zeigergröße verwenden möchten.

$ppoi

Identisch mit poi , mit der Ausnahme, dass eine physische Adresse benötigt wird. Nur physischer Arbeitsspeicher, der das Standardcacheverhalten verwendet, kann gelesen werden.

Beispiele

Das folgende Beispiel zeigt, wie Sie poi verwenden, um einen Zeiger zu dereferenzieren, um den Wert anzuzeigen, der an diesem Speicherort gespeichert ist.

Ermitteln Sie zunächst die speicherinteressente Adresse. Beispielsweise können wir uns die Threadstruktur ansehen und entscheiden, dass wir den Wert von CurrentLocale anzeigen möchten.

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 befindet sich 0x108 über den Anfang des TEB hinaus.

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

Verwenden Sie poi, um diese Adresse zu dereferenzieren.

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

Der zurückgegebene Wert 409 entspricht dem Wert von CurrentLocale in der TEB-Struktur.

Oder verwenden Sie poi und Klammern, um die berechnete Adresse zu dereferenzieren.

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

Verwenden Sie die unären Operatoren by oder wo , um ein Byte oder Wort von der Zieladresse zurückzugeben.

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

Binäre Operatoren

Sie können die folgenden binären Operatoren verwenden. Die Operatoren in jeder Zelle haben Vorrang vor denen in den unteren Zellen. Operatoren in derselben Zelle haben dieselbe Rangfolge und werden von links nach rechts analysiert.

Operator Bedeutung

*

/

mod (oder %)

Multiplikation

Ganzzahldivision

Modulus (Rest)

+

-

Addition

Subtraktion

<<

>>

>>>

Nach links verschieben

Logische Verschiebung nach rechts

Arithmetische Rechtsverschiebung

= (oder ==)

<

>

<=

>=

!=

Gleich

Kleiner als

Größer als

Kleiner als oder gleich

Größer als oder gleich

Ungleich

und (oder &)

Bitweises AND

xor (oder ^)

Bitweiser XOR (exklusives OR)

oder (oder |)

Bitweises OR

Die <Vergleichsoperatoren , >, =, ==und != werden auf 1 ausgewertet, wenn der Ausdruck true oder null ist, wenn der Ausdruck false ist. Ein einzelnes Gleichheitszeichen (=) entspricht einem doppelten Gleichheitszeichen (==). Sie können keine Nebeneffekte oder Zuweisungen innerhalb eines MASM-Ausdrucks verwenden.

Ein ungültiger Vorgang (z. B. Division durch null) führt dazu, dass ein "Operandenfehler" an das Debuggerbefehlsfenster zurückgegeben wird.

Wir können überprüfen, ob der zurückgegebene Wert mit 0x409 übereinstimmt, indem wir den Vergleichsoperator == verwenden.

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

Nicht numerische Operatoren in MASM-Ausdrücken

Sie können auch die folgenden zusätzlichen Operatoren in MASM-Ausdrücken verwenden.

Operator Bedeutung

$fnsucc(FnAddress, RetVal, Flag)

Interpretiert den RetVal-Wert als Rückgabewert für die Funktion, die sich an der FnAddress-Adresse befindet. Wenn dieser Rückgabewert als Erfolgscode gilt, gibt $fnsuccTRUE zurück. Andernfalls gibt $fnsuccFALSE zurück.

Wenn der Rückgabetyp BOOL, bool, HANDLE, HRESULT oder NTSTATUS ist, versteht $fnsucc richtig, ob der angegebene Rückgabewert als Erfolgscode gilt. Wenn der Rückgabetyp ein Zeiger ist, gelten alle anderen Werte als NULL als Erfolgscodes. Für jeden anderen Typ wird erfolg durch den Wert von Flag definiert. Wenn Flag 0 ist, ist der Wert RetVal erfolgreich. Wenn Flag 1 ist, ist der Nullwert RetVal erfolgreich.

$iment (Adresse)

Gibt die Adresse des Bildeinstiegspunkts in der geladenen Modulliste zurück. Address gibt die Basisadresse des portablen ausführbaren Images (PE) an. Der Eintrag wird gefunden, indem der Bildeinstiegspunkt im PE-Bildheader des Bilds gesucht wird, das address angibt.

Sie können diese Funktion sowohl für Module verwenden, die bereits in der Modulliste enthalten sind, als auch, um nicht aufgelöste Haltepunkte mit dem Befehl bu festzulegen.

$scmp("String1", "String2")

Ergibt -1, 0 oder 1, z. B. strcmp mithilfe der C-Funktion strcmp .

$sicmp("String1", "String2")

Wird wie die Microsoft Win32-Funktion stricmp zu -1, 0 oder 1 ausgewertet.

$spat("String", "Pattern")

Wird je nachdem, ob String mit dem Muster übereinstimmt, zu TRUE oder FALSE ausgewertet. Beim Abgleich wird die Groß-/Kleinschreibung nicht beachtet. Das Muster kann eine Vielzahl von Wildcardzeichen und Spezifizierern enthalten. Weitere Informationen zur Syntax finden Sie unter Zeichenfolgenplatzhaltersyntax.

$vvalid(Adresse,Länge)

Bestimmt, ob der Speicherbereich, der bei Adresse beginnt und für Längenbytes erweitert wird, gültig ist. Wenn der Arbeitsspeicher gültig ist, wird $vvalid zu 1 ausgewertet. Wenn der Arbeitsspeicher ungültig ist, wird $vvalid zu 0 ausgewertet.

Beispiele

Im Folgenden wird gezeigt, wie Sie den Bereich des gültigen Arbeitsspeichers um ein geladenes Modul untersuchen.

Ermitteln Sie zunächst die Adresse des Interessenbereichs, z. B. mithilfe des Befehls lm (List Loaded Modules ).


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

Verwenden Sie $vvalid, um einen Speicherbereich zu überprüfen.

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

Verwenden Sie $vvalid, um zu bestätigen, dass dieser größere Bereich ein ungültiger Speicherbereich ist.

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

Dies ist auch ein ungültiger Bereich.

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

Verwenden Sie nicht , um null zurückzugeben, wenn der Arbeitsspeicherbereich gültig ist.

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

Verwenden Sie $imnet, um den Einstiegspunkt von COMCTL32 zu untersuchen, den wir zuvor mit dem Lm-Befehl verwendet haben, um die Adresse zu bestimmen. Sie beginnt bei 00007ff9'591d0000.

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

Disassemblieren Sie die zurückgegebene Adresse, um den Einstiegspunktcode zu untersuchen.

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 wird in der Ausgabe angezeigt und bestätigt, dass dies der Einstiegspunkt für dieses Modul ist.

Registrierungen und Pseudo-Registers in MASM-Ausdrücken

Sie können Register und Pseudoregister in MASM-Ausdrücken verwenden. Sie können ein at-Zeichen (@) vor allen Registern und Pseudoregistern hinzufügen. Das At-Zeichen bewirkt, dass der Debugger schneller auf den Wert zugreift. Dieses @-Zeichen ist für die gängigsten x86-basierten Register nicht erforderlich. Für andere Register und Pseudoregister wird empfohlen, das At-Zeichen hinzuzufügen, es ist jedoch nicht erforderlich. Wenn Sie das At-Zeichen für die weniger gängigen Register weglassen, versucht der Debugger, den Text als hexadezimale Zahl, dann als Symbol und schließlich als Register zu analysieren.

Sie können auch einen Punkt (.) verwenden, um den aktuellen Anweisungszeiger anzugeben. Sie sollten vor diesem Zeitraum kein @-Zeichen hinzufügen, und Sie können keinen Punkt als ersten Parameter des r-Befehls verwenden. Dieser Zeitraum hat die gleiche Bedeutung wie das $ip Pseudoregister.

Weitere Informationen zu Registern und Pseudoregistern finden Sie unter Registersyntax und Pseudoregistersyntax.

Verwenden Sie den Befehl r register, um festzustellen, dass der Wert des @rip Registers 00007ffb'7ed00770 ist.

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

Dieser Wert kann mithilfe von angezeigt werden. Punktverknüpfung.

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

Wir können mithilfe dieses MASM-Ausdrucks bestätigen, dass alle diese Werte gleichwertig sind und wenn dies der Fall ist, null zurückgeben.

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

Quellzeilennummern in MASM-Ausdrücken

Sie können Quelldatei- und Zeilennummernausdrücke in MASM-Ausdrücken verwenden. Sie müssen diese Ausdrücke mit ernsten Akzenten (') einschließen. Weitere Informationen zur Syntax finden Sie unter Quellzeilensyntax.

Weitere Informationen

MASM-Ausdrücke im Vergleich zu C++-Ausdrücken

Beispiele für gemischte Ausdrücke

C++-Nummern und -Operatoren

Zeichenerweiterung

? (Ausdruck auswerten)