Dela via


MASM-nummer och operatorer

I det här avsnittet beskrivs användningen av masm-uttryckssyntaxen (Microsoft Macro Assembler) med Windows felsökningsverktyg.

Felsökningsprogrammet accepterar två olika typer av numeriska uttryck: C++-uttryck och MASM-uttryck. Vart och ett av dessa uttryck följer sina egna syntaxregler för indata och utdata.

Mer information om när varje syntaxtyp används finns i Utvärdera uttryck och ? (Utvärdera uttryck).

I det här exemplet... kommandot visar värdet för instruktionspekarens register med hjälp av MASM-uttrycksutvärderingen.

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

Ange uttrycksutvärderingen till MASM

Använd .expr (Välj uttrycksutvärdering) för att se vad standarduttrycksutvärderingen är och ändra den till MASM.

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

Nu när standarduttryckets utvärderare har ändrats, ? (Utvärdera uttryck) kan användas för att visa MASM-uttryck. Det här exemplet lägger till hexvärdet 8 i rip-registret.

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

Registerreferensen @rip för beskrivs mer detaljerat i Registersyntax.

Tal i MASM-uttryck för felsökningsprogram

Du kan placera tal i MASM-uttryck i bas 16, 10, 8 eller 2.

Använd kommandot n (Ange nummerbas) för att ange standardradixet till 16, 10 eller 8. Alla tal utan prefix tolkas sedan i denna bas. Du kan åsidosätta standardradixet genom att ange 0x-prefixet (hexadecimalt), 0n-prefixet (decimal), 0t-prefixet (oktalt) eller 0y-prefixet (binärt).

Du kan också ange hexadecimala tal genom att lägga till ett h efter talet. Du kan använda versaler eller gemener i siffror. Till exempel har "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" och "4aB3H" samma betydelse.

Om du inte lägger till ett tal efter prefixet i ett uttryck läss talet som 0. Därför kan du skriva 0 som 0, prefixet följt av 0 och endast prefixet. I hexadecimalt har till exempel "0", "0x0" och "0x" samma betydelse.

Du kan ange hexadecimala 64-bitarsvärden i formatet xxxxxxxx'xxxxxxxx. Du kan också utelämna gravaccenten ('). När du inkluderar grav accent inaktiveras det automatiska teckentillägget.

Det här exemplet visar hur du lägger till ett decimal-, oktalt och binärt värde för att registrera 10.

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

Symboler i MASM-uttryck för felsökningsprogram

I MASM-uttryck är det numeriska värdet för en symbol dess minnesadress. Beroende på vad symbolen refererar till är den här adressen adressen till en global variabel, lokal variabel, funktion, segment, modul eller någon annan identifierad etikett.

Om du vill ange vilken modul adressen är associerad med inkluderar du modulnamnet och ett utropstecken (!) före namnet på symbolen. Om symbolen kan tolkas som ett hexadecimalt tal ska du inkludera modulnamnet och ett utropstecken, eller bara ett utropstecken, före symbolnamnet. Mer information om symboligenkänning finns i Symbolsyntax och Symbolmatchning.

Använd två kolon (::) eller två understreck (__) för att ange medlemmarna i en klass.

Använd en grav accent (') eller en apostrofer (') i ett symbolnamn endast om du lägger till ett modulnamn och utropstecken före symbolen.

Numeriska operatorer i MASM-uttryck

Du kan ändra valfri komponent i ett uttryck med hjälp av en unary-operator. Du kan kombinera två komponenter med hjälp av en binär operator. Unary-operatorer har företräde framför binära operatorer. När du använder flera binära operatorer följer operatorerna de regler för fast prioritet som beskrivs i följande tabeller.

Du kan alltid använda parenteser för att åsidosätta prioritetsregler.

Om en del av ett MASM-uttryck omges av parenteser och två at-symboler (@@) förekommer före uttrycket, tolkas uttrycket enligt C++-uttrycksregler. Du kan inte lägga till ett blanksteg mellan de två vid tecken och den inledande parentesen. Du kan också ange uttrycksutvärderaren med hjälp av @@c++( ... ) eller @@masm( ... ).

När du utför aritmetiska beräkningar behandlar MASM-uttrycksutvärderingen alla tal och symboler som ULONG64 typer.

Unary-adressoperatorer förutsätter att DS är standardsegmentet för adresser. Uttryck utvärderas i ordning enligt operatorprecedens. Om intilliggande operatorer har samma prioritet utvärderas uttrycket från vänster till höger.

Du kan använda följande unary-operatorer.

Operatör Innebörd

+

Unary plus

-

Unärt minus

inte

Returnerar 1 om argumentet är noll. Returnerar noll för alla argument som inte är noll.

Hej

Hög 16 bitar

låg

de låga 16 bitarna

vid

Byte med låg ordning från den angivna adressen.

$pby

Samma som by förutom att den tar en fysisk adress. Endast fysiskt minne som använder standardbeteendet för cachelagring kan läsas.

Wo

Ord med låg ordning från den angivna adressen.

$pwo

Samma som wo förutom att det tar en fysisk adress. Endast fysiskt minne som använder standardbeteendet för cachelagring kan läsas.

dwo

Dubbelord från den angivna adressen.

$pdwo

Samma som dwo förutom att den tar en fysisk adress. Endast fysiskt minne som använder standardbeteendet för cachelagring kan läsas.

qwo

64-bit värde från den angivna adressen.

$pqwo

Samma som qwo förutom att den tar en fysisk adress. Endast fysiskt minne som använder standardbeteendet för cachelagring kan läsas.

Poi

Data av pekarstorlek från den angivna adressen. Pekarstorleken är 32 bitar eller 64 bitar. Vid kernelfelsökning baseras den här storleken på måldatorns processor. Därför är poi den bästa operatorn att använda om du vill ha data i pekarstorlek.

$ppoi

Samma som poi förutom att den tar en fysisk adress. Endast fysiskt minne som använder standardbeteendet för cachelagring kan läsas.

Exempel

I följande exempel visas hur du använder poi för att avreferera en pekare och visa värdet som lagras på den minnesplatsen.

Bestäm först minnesadressen av intresse. Vi kan till exempel titta på trådstrukturen och bestämma att vi vill se värdet för 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 finns 0x108 bortom TEB:s början.

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

Använd poi för att avreferera den adressen.

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

Det returnerade värdet 409 matchar värdet för CurrentLocale i TEB-strukturen.

Eller använd poi och parenteser för att avreferera den beräknade adressen.

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

Använd operatorerna by eller wo unary för att returnera en byte eller ett ord från måladressen.

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

Binära operatorer

Du kan använda följande binära operatorer. Operatorerna i varje cell har företräde framför operatorerna i lägre celler. Operatorer i samma cell har samma prioritet och parsas från vänster till höger.

Operatör Innebörd

*

/

mod (eller %)

Multiplikation

Heltalsdivision

Modulus (rest)

+

-

Tillägg

Subtraktion

<<

>>

>>>

Vänster skifte

Logiskt högerskifte

Aritmetisk högerförskjutning

= (eller ==)

<

>

<=

>=

!=

Lika med

Mindre än

Större än

Mindre än eller lika med

Större än eller lika med

Inte lika med

och (eller &)

Bitvis OCH

xor (eller ^)

Bitvis XOR (exklusiv ELLER)

eller (eller |)

Bitvis ELLER

Jämförelseoperatorerna <, >, =, == och != utvärderas till 1 om uttrycket är sant eller noll om uttrycket är falskt. Ett enda likhetstecken (=) är detsamma som ett dubbelt likhetstecken (==). Du kan inte använda biverkningar eller tilldelningar i ett MASM-uttryck.

En ogiltig åtgärd (till exempel division med noll) resulterar i att ett "Operand-fel" returneras till felsökningskommandofönstret.

Vi kan kontrollera att det returnerade värdet matchar 0x409 med hjälp av jämförelseoperatorn == .

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

Icke-numeriska operatorer i MASM-uttryck

Du kan också använda följande ytterligare operatorer i MASM-uttryck.

Operatör Innebörd

$fnsucc(FnAddress, RetVal, Flag)

Tolkar RetVal-värdet som ett returvärde för funktionen som finns på FnAddress-adressen . Om det här returvärdet kvalificerar sig som en lyckad kod returnerar $fnsuccTRUE. Annars returnerar $fnsuccFALSE.

Om returtypen är BOOL, bool, HANDLE, HRESULT eller NTSTATUS $fnsucc korrekt förstår om det angivna returvärdet kvalificerar sig som en lyckad kod. Om returtypen är en pekare kvalificeras alla andra värden än NULL som lyckade koder. För alla andra typer definieras framgång av värdet för Flagga. Om Flag är 0, betyder ett icke-noll värde på RetVal att det är en framgång. Om Flag är 1, innebär ett nollvärde för RetVal framgång.

$iment (adress)

Returnerar adressen till startpunkten för bilden i listan över inlästa moduler. Adress anger basadressen för PE (Portable Executable) avbildning. Posten hittas genom att leta upp startpunkten för bilden i PE-bildrubriken för den bild som Adress anger.

Du kan använda den här funktionen för båda modulerna som redan finns i modullistan och för att ange olösta brytpunkter med hjälp av kommandot bu .

$scmp("String1", "String2")

Utvärderas till -1, 0 eller 1, likt strcmp genom att använda C-funktionen strcmp.

$sicmp("String1", "String2")

Utvärderas till -1, 0 eller 1, som Microsoft Win32-funktionen stricmp.

$spat("String", "Pattern")

Utvärderas till TRUE eller FALSE beroende på om Strängen matchar Mönster. Matchningen är inte skiftlägeskänslig. Mönstret kan innehålla en mängd olika jokertecken och specificerare. För mer information om syntaxen, se Strängsyntax för wildcards.

$vvalid(adress,längd)

Avgör om minnesintervallet som börjar på Adress och utökas för Längdbyte är giltigt. Om minnet är giltigt utvärderas $vvalid till 1. Om minnet är ogiltigt utvärderas $vvalid till 0.

Exempel

Följande visar hur du undersöker intervallet av giltigt minne runt en inläst modul.

Bestäm först adressen för det intressanta området, till exempel med hjälp av kommandot lm (List Loaded Modules ).


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

Använd $vvalid för att kontrollera ett minnesintervall.

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

Använd $vvalid för att bekräfta att det här större intervallet är ett ogiltigt minnesintervall.

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

Det här är också ett ogiltigt intervall.

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

Använd inte för att returnera noll när minnesintervallet är giltigt.

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

Använd $imnet för att titta på startpunkten för COMCTL32 som vi tidigare använde lm-kommandot för att fastställa adressen. Den börjar på 00007ff9'591d0000.

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

Demontera den returnerade adressen för att undersöka ingångspunktkoden.

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 visas i utdata som bekräftar att det här är startpunkten för den här modulen.

Register och Pseudo-Registers i MASM-uttryck

Du kan använda register och pseudoregister i MASM-uttryck. Du kan lägga till ett vidtecken (@) innan alla register och pseudoregister. Vid-tecknet gör att felsökaren kommer åt värdet snabbare. Det här @-tecknet är onödigt för de vanligaste x86-baserade registren. För andra register och pseudoregister rekommenderar vi att du lägger till vid-tecknet, men det krävs faktiskt inte. Om du utelämnar vid tecknet för de mindre vanliga registren försöker felsökaren parsa texten som ett hexadecimalt tal, sedan som en symbol och slutligen som ett register.

Du kan också använda en punkt (.) för att ange den aktuella instruktionspekaren. Du bör inte lägga till ett @-tecken före den här perioden och du kan inte använda en punkt som den första parametern i r-kommandot. Den här perioden har samma betydelse som $ip pseudoregister.

Mer information om register och pseudoregister finns i Registersyntax och Pseudo-Register syntax.

Använd kommandot r register för att se att värdet för @rip registret är 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

Samma värde kan visas med hjälp av . periodgenväg.

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

Vi kan bekräfta att alla dessa värden är likvärdiga och returnera noll om de är det, med hjälp av det här MASM-uttrycket.

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

Källradsnummer i MASM-uttryck

Du kan använda källfils- och radnummeruttryck i MASM-uttryck. Du måste omsluta dessa uttryck med hjälp av allvarliga accenter ('). Mer information om syntaxen finns i Källradssyntax.

Se även

MASM-uttryck jämfört med C++-uttryck

Exempel på blandade uttryck

C++-tal och operatorer

Signalförlängning

? (Utvärdera uttryck)