Delen via


Syntaxis van adressen en adresbereiken

Er zijn verschillende manieren om adressen op te geven in het foutopsporingsprogramma.

Adressen worden normaal gesproken virtuele adressen, behalve wanneer de documentatie specifiek een ander soort adres aangeeft. In de gebruikersmodus interpreteert het foutopsporingsprogramma virtuele adressen op basis van de paginamap van het huidige proces. In de kernelmodus interpreteert het foutopsporingsprogramma virtuele adressen op basis van de paginamap van het proces dat de procescontext opgeeft. U kunt ook de adrescontext van de gebruikersmodus rechtstreeks instellen. Zie .context (Set User-Mode Address Context)voor meer informatie over de adrescontext in de gebruikersmodus.

In MASM-expressies kunt u de poi-operator gebruiken om elke aanwijzer te derefereren. Als de aanwijzer op adres bijvoorbeeld 0x0000008e'ed57b108 verwijst naar adreslocatie 0x805287637256, zijn de volgende twee opdrachten gelijk.

0:000> dd 805287637256
0:000> dd poi(000000bb`7ee23108)

Voorbeeld van geheugenadres weergeven

Als u een voorbeeld wilt zien van het gebruik van poi, bepaal dan de offset voor de CurrentLocale van het draadomgevingsblok (TEB). Gebruik de dx-opdracht om @$teb weer te geven, wat een voorbeeld is van een pseudoregister, dat algemene adressen bevat, zoals de huidige locatie van de programmatuur teller.

0:000> dx @$teb
@$teb                 : 0x1483181000 [Type: _TEB *]

...

    [+0x108] CurrentLocale    : 0x409 [Type: unsigned long]

CurrentLocale bevindt zich +0x108 vanaf het begin van de TEB. Bepaal vervolgens het geheugenadres van die locatie.

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

Gebruik poi om dit adres te derefereren zodat je kunt zien dat het de waarde 0x409 voor CurrentLocale bevat.

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

In C++ foutopsporingsprogramma-expressies gedragen pointers zich als aanwijzers in C++. Getallen worden echter geïnterpreteerd als gehele getallen. Als u een werkelijk getal moet deducteren, moet u dit mogelijk eerst casten, zoals in het volgende voorbeeld wordt weergegeven.

Als u dit wilt proberen, gebruikt u .expr om de expressie-evaluator in te stellen op C++.

0:000> .expr /s C++
Current expression evaluator: C++ - C++ source expressions

Als de expressie-evaluator is ingesteld op C++, kunnen we casten met behulp van lange.

0:000> d *((long*)0x00000014`83181108 ) 
00000000`00000409  ???????? ???????? ???????? ????????

Zie C++ Numbers and Operatorsvoor meer informatie over het casten van numerieke waarden.

Als de expressie-evaluator is ingesteld op c++, kunnen we de puntwijzer verpakken met @@masm()om alleen dat deel van de expressie te laten evalueren door de MASM-expressie-evaluator.

0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions

0:000> ? @@masm(poi(00000078`267d7108))
Evaluate expression: 1033 = 00000000`00000409

Zie Evaluatie van expressiesvoor meer informatie over de twee expressie-evaluators.

U kunt ook een adres in een toepassing aangeven door de oorspronkelijke bronbestandsnaam en het regelnummer op te geven. Zie bronregelsyntaxisvoor meer informatie over het opgeven van deze informatie.

Adresreeksen

U kunt een adresbereik opgeven op basis van een paar adressen of op basis van een aantal adressen en objecten.

Als u een bereik met een paar adressen wilt opgeven, geeft u het beginadres en het eindadres op. Het volgende voorbeeld is bijvoorbeeld een bereik van 8 bytes, beginnend bij het adres 0x00001000.

0x00001000  0x00001007

Als u een adresbereik wilt opgeven op basis van een aantal adressen en objecten, geeft u een adresargument, de letter L (hoofdletter of kleine letter) en een waardeargument op. Het adres geeft het beginadres aan. De waarde geeft het aantal objecten op dat moet worden onderzocht of weergegeven. De grootte van het object is afhankelijk van de opdracht. Als de objectgrootte bijvoorbeeld 1 byte is, is het volgende voorbeeld een bereik van 8 bytes, beginnend bij het adres 0x00001000.

0x00001000  L8

Als de objectgrootte echter een dubbel woord is (32 bits of 4 bytes), geven de volgende twee bereiken elk een bereik van 8 bytes.

0x00001000  0x00001007
0x00001000  L2

L Groottebereikaanduiding

Er zijn twee andere manieren om de waarde op te geven (de LGrootte bereikaanduiding):

  • L?Grootte (met een vraagteken) betekent hetzelfde als LGrootte, behalve dat L?Grootte de automatische bereiklimiet van het foutopsporingsprogramma verwijdert. Normaal gesproken is er een bereiklimiet van 256 MB, omdat grotere bereiken typografische fouten zijn. Als u een bereik wilt opgeven dat groter is dan 256 MB, moet u de L gebruiken?grootte syntaxis.

  • L-Grootte (met een afbreekstreepje) geeft een bereik van lengte Grootte dat eindigt op het opgegeven adres. Bijvoorbeeld, 80000000 L20 geeft het bereik van 0x80000000 tot 0x8000001F en 80000000 L-20 het bereik van 0x7FFFFFE0 tot 0x7FFFFFFF.

Sommige opdrachten die om adresbereiken vragen, accepteren één adres als argument. In deze situatie gebruikt de opdracht een standaard aantal objecten om de grootte van het bereik te berekenen. Opdrachten waarvoor het adresbereik de laatste parameter is, staat deze syntaxis doorgaans toe. Zie de naslagonderwerpen voor elke opdracht voor de exacte syntaxis en de standaardbereikgrootte voor elke opdracht.

Voorbeeld van zoekgeheugenbereik

Eerst bepalen we het adres van het RIP-instructiewijzerregister met behulp van de MASM-expressie-evaluator.

0:000> ? @rip 
Evaluate expression: 140720561719153 = 00007ffc`0f180771

Vervolgens zoeken we vanaf 00007ffc'0f180771 voor 100000 met behulp van de s (zoekgeheugen) opdracht. We geven het bereik op dat moet worden gezocht met behulp van L100000.

0:000> s -a 00007ffc`0f180771 L100000 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec
00007ffc`0f1d4ad2  6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00  ntdll\ldrsnap.c.
...

We kunnen ook hetzelfde bereik als dit opgeven met behulp van twee geheugenadressen.

0:000> s -a 0x00007ffc`0f180771 0x00007ffc`0f280771 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec
00007ffc`0f1d4ad2  6e 74 64 6c 6c 5c 6c 64-72 73 6e 61 70 2e 63 00  ntdll\ldrsnap.c.
...

Ten slotte kunnen we achterwaarts zoeken in het geheugenbereik met behulp van de parameter L-lengte.

0:000> s -a 00007ffc`0f1d4ad2 L-100000 "ntdll"  
00007ffc`0f1d48fa  6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00  ntdll\ldrinit.c.
00007ffc`0f1d49c2  6e 74 64 6c 6c 5c 6c 64-72 6d 61 70 2e 63 00 00  ntdll\ldrmap.c..
00007ffc`0f1d4ab2  6e 74 64 6c 6c 5c 6c 64-72 72 65 64 69 72 65 63  ntdll\ldrredirec

Voorbeeld van het demonteren van geheugen

In dit voorbeeld wordt de u (unassemble) opdracht en de parameter L gebruikt om drie bytes code los te maken.

0:000> u 00007ffc`0f1d48fa L3
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e              outs    dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464            je      ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c              ins     byte ptr [rdi],dx

U kunt ook een drie-bytebereik van het geheugen opgeven om te disassembleren zoals dit.

0:000> u 00007ffc`0f1d48fa 00007ffc`0f1d48fd
ntdll!`string'+0xa:
00007ffc`0f1d48fa 6e              outs    dx,byte ptr [rsi]
00007ffc`0f1d48fb 7464            je      ntdll!`string'+0x21 (00007ffc`0f1d4961)
00007ffc`0f1d48fd 6c              ins     byte ptr [rdi],dx

Ondersteuning voor adresmodi en segmenten

Op x86-platforms ondersteunen CDB en KD de volgende adresseringsmodi. Deze modi onderscheiden zich door hun voorvoegsels.

Voorvoegsel Naam Adrestypen
% plat 32-bit adressen (ook 16-bitselectors die naar 32-bitsegmenten wijzen) en 64-bitadressen op 64-bitsystemen.
& virtueel 86 Adressen in reële modus. alleen op x86 gebaseerd.
# eenvoudig Adressen in de reële modus. alleen op x86 gebaseerd.

Het verschil tussen de normale en virtuele 86 modi is dat een gewone 16-bits adres de segmentwaarde als selector gebruikt en de segmentdescriptor opzoekt. Maar een virtueel 86-adres gebruikt geen selectors en wordt in plaats daarvan rechtstreeks toegewezen aan de lagere 1 MB.

Als u geheugen opent via een adresseringsmodus die niet de huidige standaardmodus is, kunt u de adresmodusvoorvoegsels gebruiken om de huidige adresmodus te overschrijven.

Argumenten behandelen

Adresargumenten geven de locatie van variabelen en functies op. In de volgende tabel worden de syntaxis en betekenis van de verschillende adressen uitgelegd die u in CDB en KD kunt gebruiken.

Syntaxis Betekenis

offset

Het absolute adres in de ruimte voor virtueel geheugen, met een type dat overeenkomt met de huidige uitvoeringsmodus. Als de huidige uitvoeringsmodus bijvoorbeeld 16 bits is, is de offset 16 bits. Als de uitvoeringsmodus gesegmenteerd is in 32 bits, is de offset ook gesegmenteerd in 32 bits.

&[[ segment:]] offset

Het echte adres. x86 en x64-gebaseerd.

%segment:[[ offset]]

Een gesegmenteerd 32-bits of 64-bits adres. x86 en x64-gebaseerd.

%[[ offset]]

Een absoluut adres (32-bits of 64-bits) in virtuele geheugenruimte. x86 en x64-gebaseerd.

name[[ +| ]] offset

Een adres van 32 bits of 64 bits met een plat formaat. naam kan elk symbool zijn. offset specificeert de offset. Deze offset kan elke adresmodus zijn die het voorvoegsel aangeeft. Geen voorvoegsel geeft een standaardmodusadres op. U kunt de offset opgeven als een positieve (+) of negatieve waarde (−).

Gebruik de opdracht dg (Display Selector) om descriptorgegevens van segmenten weer te geven.

Zie ook

Als u informatie over geheugen wilt weergeven, gebruikt u de opdracht !address.

Als u geheugen wilt doorzoeken, gebruikt u de opdracht s (Zoekgeheugen).

Als u de inhoud van het geheugen wilt weergeven, gebruikt u de d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory) opdracht.

Zie Een geheugenvenster gebruikenvoor meer informatie over hoe u geheugen kunt weergeven en bewerken met behulp van een geheugenvenster.