Delen via


MASM-nummers en -operators

In dit onderwerp wordt het gebruik van de expressiesyntaxis van Microsoft Macro Assembler (MASM) beschreven met de hulpprogramma's voor Windows-foutopsporing.

Het foutopsporingsprogramma accepteert twee verschillende soorten numerieke expressies: C++-expressies en MASM-expressies. Elk van deze expressies volgt zijn eigen syntaxisregels voor invoer en uitvoer.

Zie Evaluatie van expressies en ? voor meer informatie over wanneer elk syntaxistype wordt gebruikt . (Expressie evalueren).

In dit voorbeeld de ? opdracht geeft de waarde van het instructiepointerregister weer met behulp van de MASM-expressiebeoordelaar.

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

De expressie-evaluator instellen op MASM

Gebruik de .expr (Choose Expression Evaluator) om te zien wat de standaardexpressie-evaluator is en wijzig deze in MASM.

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

Nu de standaardexpressie-evaluator is gewijzigd, kan de opdracht ? (Expressie evalueren) worden gebruikt om MASM-expressies weer te geven. In dit voorbeeld wordt de hexwaarde 8 aan het rip-register toegevoegd.

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

De registerreferentie van @rip wordt uitgebreid beschreven in De syntaxis van register.

Getallen in MASM-expressies voor foutopsporingsprogramma

U kunt getallen in MASM-expressies plaatsen in basis 16, 10, 8 of 2.

Gebruik de opdracht n (Getalbasis instellen) om de standaard radix in te stellen op 16, 10 of 8. Alle niet-voorgefixeerde getallen worden vervolgens geïnterpreteerd in deze basis. U kunt de standaard radix overschrijven door het 0x-voorvoegsel (hexadecimaal), het 0n-voorvoegsel (decimaal), het 0t-voorvoegsel (octaal) of het 0y-voorvoegsel (binair) op te geven.

U kunt ook hexadecimale getallen opgeven door een h na het getal op te tellen. U kunt hoofdletters of kleine letters in cijfers gebruiken. Bijvoorbeeld: '0x4AB3', '0X4aB3', '4AB3h', '4ab3h' en '4aB3H' hebben dezelfde betekenis.

Als u geen getal toevoegt na het voorvoegsel in een expressie, wordt het getal gelezen als 0. Daarom kunt u 0 schrijven als 0, het voorvoegsel gevolgd door 0 en alleen het voorvoegsel. Bijvoorbeeld, in hexadecimaal, "0", "0x0" en "0x" hebben dezelfde betekenis.

U kunt hexadecimale 64-bits waarden invoeren in het formaat xxxxxxxx`xxxxxxxx. U kunt ook het grafaccent (')weglaten. Als u het accent grave opneemt, wordt de automatische tekenextensie uitgeschakeld.

In dit voorbeeld ziet u hoe u een decimale, octale en binaire waarde toevoegt om 10 te registreren.

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

Symbolen in MASM-expressies voor foutopsporingsprogramma

In MASM-expressies is de numerieke waarde van een symbool het geheugenadres. Afhankelijk van wat het symbool verwijst, is dit adres het adres van een globale variabele, lokale variabele, functie, segment, module of een ander herkend label.

Als u wilt opgeven aan welke module het adres is gekoppeld, moet u de modulenaam en een uitroepteken (!) vóór de naam van het symbool opnemen. Als het symbool kan worden geïnterpreteerd als een hexadecimaal getal, neemt u de modulenaam en een uitroepteken op, of alleen een uitroepteken, vóór de symboolnaam. Zie Symboolsyntaxis en Symboolkoppeling voor meer informatie over symboolherkenning.

Gebruik twee dubbele punten (::) of twee onderstrepingstekens (__) om de leden van een klasse aan te geven.

Gebruik alleen een accent (') of een apostrof (') in een symboolnaam als u een modulenaam en uitroepteken voor het symbool toevoegt.

Numerieke operatoren in MASM-expressies

U kunt elk onderdeel van een expressie wijzigen met behulp van een unaire operator. U kunt twee onderdelen combineren met behulp van een binaire operator. Unaire operators hebben voorrang op binaire operators. Wanneer u meerdere binaire operators gebruikt, volgen de operators de vaste prioriteitsregels die worden beschreven in de volgende tabellen.

U kunt altijd haakjes gebruiken om voorrangsregels te overschrijven.

Als een deel van een MASM-expressie tussen haakjes staat en twee bijtekens (@@) vóór de expressie worden weergegeven, wordt de expressie geïnterpreteerd volgens C++-expressieregels. U kunt geen spatie tussen de twee aantekens en het haakje openen toevoegen. U kunt ook de expressie-evaluator opgeven met behulp van @@c++( ... ) of @@masm( ... ).

Wanneer u rekenkundige berekeningen uitvoert, behandelt de MASM-expressie-evaluator alle getallen en symbolen als ULONG64 typen.

Unaire adresoperators gaan ervan uit dat DS als het standaardsegment voor adressen wordt gebruikt. Expressies worden geëvalueerd in volgorde van operatorprecedentie. Als aangrenzende operators gelijke prioriteit hebben, wordt de expressie van links naar rechts geëvalueerd.

U kunt de volgende unaire operatoren gebruiken.

Operateur Betekenis

+

Unary plus

-

Unair min

niet

Retourneert 1 als het argument nul is. Retourneert nul voor een niet-nulargument.

Hallo

Hoogste 16 bits

lage

Lagere 16 bits

bij

Byte met lage volgorde vanaf het opgegeven adres.

$pby

Hetzelfde als door , behalve dat het een fysiek adres nodig heeft. Alleen fysiek geheugen dat gebruikmaakt van het standaardgedrag voor opslaan in cache kan worden gelezen.

wo

Woord met lage volgorde van het opgegeven adres.

$pwo

Hetzelfde als wo behalve dat het een fysiek adres nodig heeft. Alleen fysiek geheugen dat gebruikmaakt van het standaardgedrag voor opslaan in cache kan worden gelezen.

dwo

Dubbelwoord van het opgegeven adres.

$pdwo

Hetzelfde als dwo , behalve dat het een fysiek adres nodig heeft. Alleen fysiek geheugen dat gebruikmaakt van het standaardgedrag voor opslaan in cache kan worden gelezen.

qwo

Quad-woord van het opgegeven adres.

$pqwo

Hetzelfde als qwo , behalve dat het een fysiek adres nodig heeft. Alleen fysiek geheugen dat gebruikmaakt van het standaardgedrag voor opslaan in cache kan worden gelezen.

Poi

Gegevens van pointergrootte van het opgegeven adres. De grootte van de aanwijzer is 32 bits of 64 bits. Bij kernelfoutopsporing is deze grootte gebaseerd op de processor van de doelcomputer . Daarom is poi de beste operator die u kunt gebruiken als u gegevens van aanwijzerformaat wilt.

$ppoi

Hetzelfde als poi, behalve dat het een fysiek adres benodigd. Alleen fysiek geheugen dat gebruikmaakt van het standaardgedrag voor opslaan in cache kan worden gelezen.

Voorbeelden

In het volgende voorbeeld ziet u hoe u poi gebruikt om een aanwijzer te dereferen en de waarde te zien die is opgeslagen op die geheugenlocatie.

Bepaal eerst het geheugenadres van belang. We kunnen bijvoorbeeld kijken naar de threadstructuur en besluiten dat we de waarde van currentlocale willen zien.

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 bevindt zich 0x108 buiten het begin van de TEB.

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

Gebruik poi om dat adres te dereferenceren.

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

De geretourneerde waarde van 409 komt overeen met de waarde van CurrentLocale in de TEB-structuur.

Of gebruik punten en haakjes om het berekende adres te deducteren.

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

Gebruik de by of wo unaire operators om een byte of woord van het doeladres te retourneren.

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

Binaire operatoren

U kunt de volgende binaire operators gebruiken. De operatoren in elke cel hebben voorrang op de operatoren in lagere cellen. Operatoren in dezelfde cel hebben dezelfde prioriteit en worden van links naar rechts geparseerd.

Operateur Betekenis

*

/

mod (of %)

Vermenigvuldiging

Deling van gehele getallen

Modulus (restgetal)

+

-

Toevoeging

Aftrekking

<<

>>

>>>

Verschuiving naar links

Logische rechtsschift

Rekenkundige verschuiving naar rechts

= (of ==)

<

>

<=

>=

!=

Gelijk aan

Kleiner dan

Groter dan

Kleiner dan of gelijk aan

Groter dan of gelijk aan

Niet gelijk aan

en (of &)

Bitwise AND

xor (of ^)

Bitwise XOR (exclusief OF)

of (of |)

Bitsgewijze OR

De <vergelijkingsoperatoren , = >, =, ==en != evalueren tot 1 als de expressie waar of nul is als de expressie onwaar is. Een enkel gelijkteken (=) is hetzelfde als een dubbel gelijkteken (==). U kunt geen bijwerkingen of toewijzingen in een MASM-expressie gebruiken.

Een ongeldige bewerking (zoals delen door nul) resulteert in een 'Operand-fout' die wordt geretourneerd in het opdrachtvenster Foutopsporingsprogramma.

We kunnen controleren of de geretourneerde waarde overeenkomt met 0x409 met behulp van de vergelijkingsoperator ==.

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

Niet-numerieke operatoren in MASM-expressies

U kunt ook de volgende extra operators in MASM-expressies gebruiken.

Operateur Betekenis

$fnsucc(FnAddress, RetVal, Flag)

Interpreteert de RetVal-waarde als een retourwaarde voor de functie die zich op het FnAddress-adres bevindt. Als deze retourwaarde in aanmerking komt als een succescode, geeft $fnsuccTRUE als resultaat. Anders retourneert $fnsuccONWAAR.

Als het retourtype BOOL, bool, HANDLE, HRESULT of NTSTATUS is, begrijpt $fnsucc goed of de opgegeven retourwaarde in aanmerking komt als een succescode. Als het retourtype een aanwijzer is, komen alle andere waarden dan NULL in aanmerking als succescodes. Voor elk ander type wordt succes gedefinieerd door de waarde van Flag. Als Vlag 0 is, is een niet-nulwaarde van RetVal geslaagd. Als Vlag 1 is, is een nulwaarde van RetVal geslaagd.

$iment (adres)

Retourneert het adres van het instappunt van de afbeelding in de geladen modulelijst. Adres specificeert het basisadres van de Portable Executable (PE) afbeelding. De vermelding wordt gevonden door het toegangspunt voor de afbeelding in de PE-afbeeldingskoptekst op te zoeken van de afbeelding die wordt opgegeven door Adres .

U kunt deze functie gebruiken voor beide modules die al in de modulelijst staan en om onopgeloste onderbrekingspunten in te stellen met behulp van de bu-opdracht.

$scmp("String1", "String2")

Evalueert naar -1, 0 of 1, zoals de strcmp met behulp van de strcmp C-functie.

$sicmp("Tekenreeks1", "Tekenreeks2")

Evalueert naar -1, 0 of 1, zoals de stricmp Microsoft Win32-functie.

$spat("Tekenreeks", "Patroon")

Evalueert naar TRUE of FALSE , afhankelijk van of tekenreeks overeenkomt met patroon. De vergelijking is niet hoofdlettergevoelig. Patroon kan verschillende jokertekens en aanduidingen bevatten. Zie String Wildcard Syntax voor meer informatie over de syntaxis.

$vvalid(adres,lengte)

Bepaalt of het geheugenbereik dat begint bij Adres en wordt uitgebreid voor Lengte bytes geldig is. Als het geheugen geldig is, $vvalid evalueert naar 1. Als het geheugen ongeldig is, wordt $vvalid geëvalueerd op 0.

Voorbeelden

Hieronder ziet u hoe u het bereik van geldig geheugen rond een geladen module kunt onderzoeken

Bepaal eerst het adres van het interessegebied, bijvoorbeeld met behulp van de opdracht Lm (opdracht Geladen modules weergeven).


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

Gebruik $vvalid om een geheugenbereik te controleren.

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

Gebruik $vvalid om te bevestigen dat dit grotere bereik een ongeldig geheugenbereik is.

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

Dit is ook een ongeldig bereik.

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

Gebruik not om nul te retourneren wanneer het geheugenbereik geldig is.

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

Gebruik $imnet om te kijken naar het toegangspunt van COMCTL32 waarvoor we eerder de lm-opdracht gebruikten om het adres te bepalen. Het begint bij 00007ff9'591d0000.

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

Demoneer het geretourneerde adres om de invoerpuntcode te onderzoeken.

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 wordt weergegeven in de uitvoer die bevestigt dat dit het toegangspunt voor deze module is.

Registreert en Pseudo-Registers in MASM-expressies

U kunt registers en pseudoregisters in MASM-expressies gebruiken. U kunt een bijteken (@) toevoegen voor alle registers en pseudoregisters. Het at-teken zorgt ervoor dat het foutopsporingsprogramma sneller toegang heeft tot de waarde. Dit @-teken is niet nodig voor de meest voorkomende x86-registers. Voor andere registers en pseudoregisters raden we u aan het teken toe te voegen, maar dit is niet echt vereist. Als u het teken weglaat voor de minder gangbare registers, probeert het foutopsporingsprogramma de tekst te parseren als een hexadecimaal getal, vervolgens als een symbool en ten slotte als een register.

U kunt ook een punt (.) gebruiken om de huidige instructiepointer aan te geven. U moet vóór deze periode geen @-teken toevoegen en u kunt een punt niet gebruiken als de eerste parameter van de opdracht r. Deze periode heeft dezelfde betekenis als het $ip pseudoregister.

Zie Registersyntaxis en Pseudo-Register-syntaxis voor meer informatie over registers en pseudoregisters.

Gebruik de opdracht r register om te zien dat de waarde van het @rip register 00007ffb'7ed00770 is.

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

Dezelfde waarde kan worden weergegeven met behulp van de . sneltoets voor punt

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

We kunnen bevestigen dat deze waarden allemaal gelijkwaardig zijn en nul retourneren als dat zo is, met behulp van deze MASM-expressie.

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

Regelnummers van de bron in MASM-expressies

U kunt bronbestand- en regelnummerexpressies in MASM-expressies gebruiken. U moet deze expressies insluiten met behulp van graveaccenten ('). Zie De syntaxis van de bronregel voor meer informatie over de syntaxis.

Zie ook

MASM-expressies versus C++-expressies

Voorbeelden van gemengde expressies

C++ Getallen en Operators

Tekenextensie

? (Expressie evalueren)