Freigeben über


MASM-Nummern und -Operatoren

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

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

Weitere Informationen dazu, wann welcher Syntaxtyp verwendet wird, finden Sie unter Auswerten von Ausdrücken und ? (Auswerten von Ausdrücken).

In diesem Beispiel zeigt der ?- Befehl den Wert des Anweisungszeigerregisters mithilfe der MASM-Ausdrucksauswertung an.

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

Festlegen der Ausdrucksauswertung auf MASM

Verwenden Sie .expr (Ausdrucksauswertung auswählen), um zu sehen, was die Standard-Ausdrucksauswertung ist, und ändern Sie ihn in MASM.

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

Nachdem die standardmäßige Ausdrucksauswertung geändert wurde, kann der Befehl ? (Ausdruck auswerten) zum Anzeigen von MASM-Ausdrücken verwendet werden. In diesem Beispiel wird der Hexwert 8 zum Rip-Register hinzugefügt.

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

Die Registerreferenz @rip wird in der Registersyntax detaillierter besprochen.

Zahlen in Debugger-MASM-Ausdrücken

Sie können Zahlen in MASM-Ausdrücken mit der Basis 16, 10, 8 oder 2 eingeben.

Verwenden Sie den Befehl n (Set Number Base), um die Standardbasis auf 16, 10 oder 8 festzulegen. Alle nicht festgelegten Zahlen werden dann in dieser Basis interpretiert. Sie können die Standardbasis außer Kraft setzen, 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 innerhalb von Zahlen verwenden. Beispielsweise haben „0x4AB3“, „0X4aB3“, „4AB3h“, „4ab3h“ und „4aB3H“ dieselbe Bedeutung.

Wenn Sie nach dem Präfix in einem Ausdruck keine Zahl 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 im Hexadezimalsystem „0“, „0x0“ und „0x“ die gleiche Bedeutung.

Sie können hexadezimale 64-Bit-Werte im Format xxxxxxxx'xxxxxx eingeben. Sie können das Gravis (`) auch weglassen. Wenn Sie das Graviszeichen einschließen, wird die automatische Zeichenerweiterung deaktiviert.

In diesem Beispiel wird gezeigt, wie Sie einen dezimalen, oktalen und binären Wert 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 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, schließen Sie den Modulnamen und ein Ausrufezeichen (!) vor dem Namen des Symbols ein. Wenn das Symbol als hexadezimale Zahl interpretiert werden kann, 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 Mitglieder einer Klasse anzugeben.

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

Numerische Operatoren in MASM-Ausdrücken

Sie können eine beliebige Komponente eines Ausdrucks mithilfe eines unären Operators ändern. Sie können zwei beliebige Komponenten kombinieren, indem Sie einen binären Operator verwenden. Unäre Operatoren haben Vorrang vor binären Operatoren. Wenn Sie mehrere binäre Operatoren verwenden, folgen die Operatoren den in den folgenden Tabellen beschriebenen festen Rangfolgeregeln.

Sie können Klammern immer verwenden, um Rangfolgeregeln zu überschreiben.

Wenn ein Teil eines MASM-Ausdrucks in Klammern steht und vor dem Ausdruck zwei at-Zeichen (@@) erscheinen, wird der Ausdruck gemäß C++-Ausdrucksregeln interpretiert. Sie können kein Leerzeichen zwischen den beiden Zeichen und der öffnenden Klammer hinzufügen. Sie können die Ausdrucksauswertung auch mithilfe von @@c++( ... ) oder @@masm( ... ) angeben.

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

Unäre Adressoperatoren gehen von DS als Standardsegment für Adressen aus. Ausdrücke werden in der Reihenfolge der Rangfolge des Operators 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 null ist. Gibt für jedes Argument ungleich Null Null zurück.

Hallo

Hohe 16 Bits

low

Niedrige 16 Bits

by

Niederwertigstes Byte von der angegebenen Adresse.

$pby

Genau wie by, mit der Ausnahme, das eine physische Adresse erforderlich ist. Es kann nur physischer Speicher gelesen werden, der das Standardverhalten für die Zwischenspeicherung verwendet.

wo

Wort mit niedriger Reihenfolge aus der angegebenen Adresse.

$pwo

Genau wie wo, mit der Ausnahme, das eine physische Adresse erforderlich ist. Es kann nur physischer Speicher gelesen werden, der das Standardverhalten für die Zwischenspeicherung verwendet.

dwo

Doppeltes Wort aus der angegebenen Adresse.

$pdwo

Genau wie dwo, mit der Ausnahme, das eine physische Adresse erforderlich ist. Es kann nur physischer Speicher gelesen werden, der das Standardverhalten für die Zwischenspeicherung verwendet.

qwo

Vier-Wort-Wert aus der angegebenen Adresse.

$pqwo

Genau wie qwo, mit der Ausnahme, das eine physische Adresse erforderlich ist. Es kann nur physischer Speicher gelesen werden, der das Standardverhalten für die Zwischenspeicherung verwendet.

poi

Daten der Zeigergröße aus der angegebenen Adresse. Die Zeigergröße beträgt 32 Bit oder 64 Bit. Im Kerneldebugging basiert diese Größe auf dem Prozessor des Zielcomputers . Daher ist poi der beste Operator, wenn Sie Daten in Zeigergröße wünschen.

$ppoi

Genau wie poi, mit der Ausnahme, das eine physische Adresse erforderlich ist. Es kann nur physischer Speicher gelesen werden, der das Standardverhalten für die Zwischenspeicherung verwendet.

Beispiele

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

Bestimmen Sie zunächst die gewünschte Speicheradresse. Wir können uns beispielsweise die Threadstruktur ansehen und entscheiden, dass wir den Wert von CurrentLocale sehen 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 hinter dem Anfang des TEB.

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 darunterliegenden Zellen. Operatoren in derselben Zelle haben dieselbe Priorität und werden von links nach rechts analysiert.

Operator Bedeutung

*

/

mod (oder %)

Multiplikation

Ganzzahldivision

Modulus (Rest)

+

-

Hinzufügung

Subtraktion

<<

>>

>>>

Verschiebung nach links

Logische Rechtsverschiebung

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 ^)

Bitweises XOR (exklusives OR)

or (oder |)

Bitweises OR

Die Vergleichsoperatoren <, >, =, ==, and != werten auf 1 aus, wenn der Ausdruck wahr ist, und als 0, wenn der Ausdruck falsch ist. Ein einzelnes Gleichheitszeichen (=) ist identisch mit einem doppelten Gleichheitszeichen (==). Sie können innerhalb eines MASM-Ausdrucks keine Nebeneffekte oder Zuweisungen verwenden.

Ein ungültiger Vorgang (z. B. Division durch Null) führt zu einem „Operanden-Fehler“ und wird an das Fenster Debuggerbefehl zurückgegeben.

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

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

Nicht numerische Operatoren in MASM-Ausdrücken

Sie können in MASM-Ausdrücken auch die folgenden zusätzlichen Operatoren 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 $fnsucc den Wert TRUE zurück. Andernfalls gibt $fnsucc den Wert FALSE zurück.

Wenn der Rückgabewert BOOL, bool, HANDLE, HRESULT oder NTSTATUS ist, versteht $fnsucc richtig, ob sich der angegebene Rückgabewert als Erfolgscode qualifiziert. Wenn der Rückgabetyp ein Zeiger ist, gelten alle anderen Werte als NULL als Erfolgscodes. Bei jedem anderen Typ wird der Erfolg durch den Wert Flag definiert. Wenn Flag 0 ist, ist ein Wert ungleich null von RetVal ein Erfolg. Wenn Flag 1 ist, ist ein Null-Wert von RetVal ein Erfolg.

$iment (Adresse)

Gibt die Adresse des Bildeinstiegspunkts in der geladenen Modulliste zurück. Address gibt die Basisadresse für portable ausführbare Dateien (PE) an. Der Eintrag wird gefunden, indem der Bildeinstiegspunkt in der PE-Bildkopfzeile des Bilds gesucht wird, das Address angibt.

Sie können diese Funktion sowohl für Module verwenden, die sich bereits in der Modulliste befinden, als auch zum Festlegen von nicht aufgelösten Haltepunkten durch Verwendung des Befehls bu.

$scmp("String1", "String2")

Ergibt -1, 0, oder 1 wie strcmp durch Verwendung der strcmp-C-Funktion.

$sicmp("String1", "String2")

Ergibt -1, 0 oder 1 wie die stricmp-Microsoft Win32-Funktion.

$spat("String", "Pattern")

Ergibt TRUE oder FALSE, je nachdem, ob String mit Pattern übereinstimmt. Bei der Übereinstimmung wird die Groß-/Kleinschreibung nicht beachtet. Pattern kann verschiedene Platzhalterzeichen und Spezifizierer enthalten. Weitere Informationen über die Syntax finden Sie unter String Wildcard Syntax.

$vvalid(Adresse, Länge)

Legt fest, ob der Speicherbereich, der bei Address beginnt und auf Length-Bytes verlängert wird, gültig ist. Wenn der Arbeitsspeicher gültig ist, ergibt $vvalid 1. Wenn der Arbeitsspeicher ungültig ist, ergibt $vvalid 0.

Beispiele

Nachfolgend wird gezeigt, wie Sie den Bereich des gültigen Speichers für ein geladenes Modul untersuchen können.

Ermitteln Sie zunächst die Adresse des gewünschten Gebiets, zum Beispiel 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 Speicherbereich gültig ist.

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

Verwenden Sie $imnet, um sich den Einstiegspunkt COMCTL32 anzusehen, mit dem wir zuvor den lm-Befehl verwendet haben, um die Adresse zu bestimmen. Er 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, die bestätigt, dass dies der Einstiegspunkt für dieses Modul ist.

Register und Pseudoregister in MASM-Ausdrücken

Sie können Register und Pseudoregister in MASM-Ausdrücken verwenden. Sie können vor allen Registern und Pseudoregistern ein at-Zeichen (@) hinzufügen. Das at-Zeichen bewirkt, dass der Debugger schneller auf den Wert zugreift. Dieses @-Zeichen ist für die am häufigsten verwendeten x86-basierten Register nicht erforderlich. Bei anderen Registern und Pseudoregistern wird empfohlen, das at-Zeichen hinzuzufügen, aber es ist nicht tatsächlich erforderlich. Wenn Sie das at-Zeichen für die weniger allgemeinen 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 Punkt kein @-Zeichen hinzufügen und Sie können keinen Punkt als ersten Parameter des Befehls r verwenden. Dieser Punkt hat die gleiche Bedeutung wie das $ip-Pseudoregister.

Weitere Informationen zu Registern und Pseudoregistern finden Sie unter Registersyntax und Pseudoregister-Syntax.

Verwenden Sie den Befehl r register, um zu sehen, 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

Derselbe Wert kann mit der Tastenkombination „Punkt“ . angezeigt werden.

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

Wir können bestätigen, dass diese Werte alle gleichwertig sind und bei Verwendung dieses MASM-Ausdrucks 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 Graviszeichen (`) einschließen. Weitere Informationen über die 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)