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.