Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
MASM-Nummern und -Operatoren
Artikel
24.06.2024
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.
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.
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.
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.
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.
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.
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.
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.
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.