Sdílet prostřednictvím


Syntaxe adres a rozsahu adres

Existuje několik způsobů, jak zadat adresy v ladicím programu.

Adresy jsou obvykle virtuální adresy, s výjimkou případů, kdy dokumentace výslovně označuje jiný druh adresy. V uživatelském režimu ladicí program interpretuje virtuální adresy podle adresáře stránky aktuálního procesu. V režimu jádra ladicí program interpretuje virtuální adresy podle tabulky stránek procesu, kterou určuje kontext procesu. Můžete také přímo nastavit kontext adresy v uživatelském režimu. Další informace o kontextu adresy v uživatelském režimu naleznete v tématu .context (nastavení User-Mode kontextu adresy).

Ve výrazech MASM můžete pomocí operátoru poi převést libovolný ukazatel. Pokud například ukazatel na adrese 0x0000008e'ed57b108 odkazuje na umístění adresy 0x805287637256, jsou ekvivalentní následující dva příkazy.

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

Příklad zobrazované adresy paměti

Pokud chcete zobrazit příklad použití poi, určete posun pro currentLocale bloku prostředí vlákna (TEB). Příkaz dx slouží k zobrazení @$teb, což je příklad pseudoregistrů, které obsahují běžné adresy, například aktuální umístění čítače programu.

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

...

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

CurrentLocale je +0x108 od začátku TEB. Poté určete adresu paměti tohoto umístění.

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

Pomocí příkazu poi dereferencujte tuto adresu, abyste zjistili, že obsahuje hodnotu CurrentLocale rovnou 0x409.

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

Ve výrazech ladicího programu jazyka C++ se ukazatele chovají jako ukazatele v jazyce C++. Čísla se ale interpretují jako celá čísla. Pokud potřebujete odvodit skutečné číslo, možná ho budete muset nejdřív přetypovat, jak ukazuje následující příklad.

Chcete-li to vyzkoušet, použijte .expr k nastavení vyhodnocovače výrazů na C++.

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

Při nastavení vyhodnocovače výrazů na C++ můžeme přetypovat na datový typ 'long'.

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

Další informace o přetypování číselných hodnot naleznete v tématu Čísla a operátory jazyka C++.

Pokud je vyhodnocovač výrazů nastavený na c++, můžeme ukazatel poi zabalit pomocí @@masm() a nechat jen tu část výrazu vyhodnocenou vyhodnocovačem výrazu MASM.

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

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

Další informace o dvou vyhodnocovacích modulech výrazů najdete v tématu Vyhodnocení výrazů.

Adresu v aplikaci můžete také označit zadáním původního názvu zdrojového souboru a čísla řádku. Další informace o tom, jak tyto informace zadat, naleznete v tématu Syntaxe řádku zdroje.

Rozsahy adres

Rozsah adres můžete zadat podle dvojice adres nebo podle adresy a počtu objektů.

Pokud chcete zadat rozsah podle dvojice adres, zadejte počáteční a koncovou adresu. Například následující příklad ukazuje rozsah 8 bajtů začínající na adrese 0x00001000.

0x00001000  0x00001007

Pokud chcete zadat rozsah adres podle adresy a počtu objektů, zadejte argument adresy, písmeno L (velká nebo malá písmena) a argument hodnoty. Adresa určuje počáteční adresu. Hodnota určuje počet objektů, které se mají prověřit nebo zobrazit. Velikost objektu závisí na příkazu. Pokud je například velikost objektu 1 bajt, následující příklad je rozsah 8 bajtů, počínaje adresou 0x00001000.

0x00001000  L8

Pokud je však velikost objektu dvojitým slovem (32 bitů nebo 4 bajty), následující dvě oblasti poskytují osmi bajtový rozsah.

0x00001000  0x00001007
0x00001000  L2

Specifikátor rozsahu velikostí L

Existují dva další způsoby, jak zadat hodnotu (specifikátor rozsahu velikostí L):

  • L?Velikost (s otazníkem) znamená to samé jako LVelikost, s tím rozdílem, že L?Velikost odebere automatický rozsah ladicího programu. Obvykle existuje limit rozsahu 256 MB, protože větší rozsahy jsou typografické chyby. Pokud chcete zadat rozsah, který je větší než 256 MB, musíte použít L?Syntaxe velikosti

  • L-Size (s pomlčkou) určuje rozsah délky Velikost, která končí na dané adrese. Například 80000000 L20 určuje rozsah od 0x80000000 do 0x8000001F a 80000000 L-20 určuje rozsah od 0x7FFFFFE0 až 0x7FFFFFFF.

Některé příkazy, které se ptají na rozsahy adres, přijímají jako argument jednu adresu. V takovém případě příkaz použije k výpočtu velikosti rozsahu určitý výchozí počet objektů. Příkazy, pro které je rozsah adres konečným parametrem, obvykle umožňují tuto syntaxi. Přesná syntaxe a výchozí velikost rozsahu pro každý příkaz najdete v referenčních tématech pro každý příkaz.

Příklad rozsahu paměti vyhledávání

Nejprve určíme adresu registru ukazatele instrukce rip pomocí vyhodnocovače výrazů MASM.

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

Pak budeme hledat od 00007ffc`0f180771 na 100000 pomocí příkazu s (Hledat paměť). Pomocí L100000 určíme rozsah, který se má prohledávat.

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.
...

Stejnou oblast můžeme zadat také pomocí dvou adres paměti.

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.
...

Nakonec můžeme hledat zpětně v rozsahu paměti pomocí parametru L-length.

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

Příklad rozložení paměti

V tomto příkladu se používá příkaz u (unassemble) a parametr L k zrušení sestavení tří bajtů kódu.

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

Nebo zadejte tříbajtový rozsah paměti, který chcete dekompilovat takto.

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

Režimy adres a podpora segmentů

Na platformách založených na platformě x86 podporují CDB a KD následující režimy adresování. Tyto režimy se rozlišují podle jejich předpon.

Předpona Název Typy adres
% byt 32bitové adresy (také 16bitové selektory, které odkazují na 32bitové segmenty) a 64bitové adresy v 64bitových systémech.
& virtuální 86 Adresy v reálném režimu. pouze na platformě x86.
# planina Adresy v reálném režimu. pouze na platformě x86.

Rozdíl mezi režimy prostého a virtuálního 86 je v tom, že prostá 16bitová adresa používá hodnotu segmentu jako selektor a vyhledává popisovač segmentu. Virtuální adresa 86 ale nepoužívá selektory a místo toho se mapuje přímo do nižšího 1 MB.

Pokud přistupujete k paměti prostřednictvím režimu adresování, který není aktuálním výchozím režimem, můžete k přepsání aktuálního režimu adresy použít předpony režimu adresy.

Řešit argumenty

Argumenty adresy určují umístění proměnných a funkcí. Následující tabulka vysvětluje syntaxi a význam různých adres, které můžete použít v CDB a KD.

Syntaxe Význam

offset

Absolutní adresa v prostoru virtuální paměti s typem, který odpovídá aktuálnímu režimu spuštění. Pokud je například aktuální režim provádění 16 bitů, posun je 16 bitů. Pokud je režim provádění 32bitový segmentovaný, posun je 32bitový segmentovaný.

&[[ segment:]] posun

Skutečná adresa. založené na platformě x86 a x64.

%segment:[[ posun]]

Segmentovaná 32bitová nebo 64bitová adresa. založené na platformě x86 a x64.

%[[ posun]]

Absolutní adresa (32bitová nebo 64bitová) v prostoru virtuální paměti. založené na platformě x86 a x64.

name[[ +| ]] ofset

Plochá 32bitová nebo 64bitová adresa. název může být libovolný symbol. offset určuje hodnotu posunu. Tento offset může být jakýkoliv adresní režim, který určuje jeho předpona. Žádná předpona určuje výchozí adresu režimu. Posun můžete zadat jako kladnou (+) nebo zápornou hodnotu (−).

K zobrazení informací popisovače segmentů použijte příkaz dg (Display Selector ).

Viz také

K zobrazení informací o paměti použijte příkaz !address .

Pokud chcete hledat paměť, použijte příkaz s (Search Memory).

K zobrazení obsahu paměti použijte příkaz d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory).

Informace o tom, jak můžete zobrazit a upravit paměť pomocí okna Paměť naleznete v tématu Použití okna Paměť.