Sintaxe de intervalo de endereços e endereços

Há várias maneiras de especificar endereços no depurador.

Os endereços normalmente são endereços virtuais, exceto quando a documentação indica especificamente outro tipo de endereço. No modo de usuário, o depurador interpreta endereços virtuais de acordo com o diretório de página do processo atual. No modo kernel, o depurador interpreta endereços virtuais de acordo com o diretório de página do processo especificado pelo contexto do processo . Você também pode definir diretamente o contexto de endereço do modo de usuário. Para obter mais informações sobre o contexto de endereço do modo de usuário, consulte .context (Definir User-Mode Contexto de Endereço).

Em expressões MASM, você pode usar o operador poi para desreferenciar qualquer ponteiro. Por exemplo, se o ponteiro no endereço 0x0000008e'ed57b108 pontos para o local de endereço 0x805287637256, os dois comandos a seguir serão equivalentes.

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

Exemplo de endereço de memória de exibição

Para ver um exemplo de uso de poi, determine o deslocamento para CurrentLocale do bloco de ambiente de thread (TEB). Use o comando dx para exibir @$teb, que é um exemplo de pseudo-registros, que contém endereços comuns, como o local atual do contador do programa.

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

...

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

CurrentLocale é +0x108 desde o início do TEB. Em seguida, determine o endereço de memória desse local.

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

Use poi para desreferenciar esse endereço para ver se ele contém o valor CurrentLocale de 0x409.

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

Em expressões do depurador C++, os ponteiros se comportam como ponteiros em C++. No entanto, os números são interpretados como inteiros. Se você precisar deferenciar um número real, talvez seja necessário convertê-lo primeiro, como mostra o exemplo a seguir.

Para tentar isso, use .expr para definir o avaliador de expressão como C++.

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

Com o avaliador de expressão definido como C++, podemos converter usando long.

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

Para obter mais informações sobre como converter valores numéricos, consulte Operadores e números C++.

Se o avaliador de expressão estiver definido como c++, poderemos encapsular o ponteiro poi com @@masm(), para ter apenas essa parte da expressão avaliada pelo avaliador de expressão MASM.

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

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

Para obter mais informações sobre os dois avaliadores de expressão, consulte Avaliando expressões.

Você também pode indicar um endereço em um aplicativo especificando o nome do arquivo de origem original e o número de linha. Para obter mais informações sobre como especificar essas informações, consulte Sintaxe de linha de origem.

Intervalos de endereços

Você pode especificar um intervalo de endereços por um par de endereços ou por um endereço e contagem de objetos.

Para especificar um intervalo por um par de endereços, especifique o endereço inicial e o endereço final. Por exemplo, o exemplo a seguir é um intervalo de 8 bytes, começando no endereço 0x00001000.

0x00001000  0x00001007

Para especificar um intervalo de endereços por um endereço e uma contagem de objetos, especifique um argumento de endereço, a letra L (maiúsculas ou minúsculas) e um argumento de valor. O endereço especifica o endereço inicial. O valor especifica o número de objetos a serem examinados ou exibidos. O tamanho do objeto depende do comando . Por exemplo, se o tamanho do objeto for de 1 byte, o exemplo a seguir será um intervalo de 8 bytes, começando no endereço 0x00001000.

0x00001000  L8

No entanto, se o tamanho do objeto for uma palavra dupla (32 bits ou 4 bytes), os dois intervalos a seguir fornecerão um intervalo de 8 bytes.

0x00001000  0x00001007
0x00001000  L2

Especificador de intervalo de tamanho L

Há duas outras maneiras de especificar o valor (o especificador de intervalo de tamanhoL):

  • L?Tamanho (com um ponto de interrogação) significa o mesmo que TamanhoL, exceto que L?O tamanho remove o limite de intervalo automático do depurador. Normalmente, há um limite de intervalo de 256 MB, pois intervalos maiores são erros de digitação. Se você quiser especificar um intervalo maior que 256 MB, deverá usar o L?Sintaxe de tamanho .

  • L-Size (com um hífen) especifica um intervalo de tamanho tamanho que termina no endereço fornecido. Por exemplo, 800000000 L20 especifica o intervalo de 0x80000000 a 0x8000001F e 800000000 L-20 especifica o intervalo de 0x7FFFFFE0 a 0x7FFFFFFF.

Alguns comandos que solicitam intervalos de endereços aceitam um único endereço como o argumento. Nessa situação, o comando usa alguma contagem de objetos padrão para calcular o tamanho do intervalo. Normalmente, os comandos para os quais o intervalo de endereços é o parâmetro final permitem essa sintaxe. Para obter a sintaxe exata e o tamanho do intervalo padrão para cada comando, consulte os tópicos de referência para cada comando.

Exemplo de intervalo de memória de pesquisa

Primeiro, determinaremos o endereço do registro do ponteiro de instrução rip usando o avaliador de expressão MASM.

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

Em seguida, pesquisaremos a partir de 00007ffc'0f180771, para 100000 usando o comando s (Pesquisar Memória). Especificamos o intervalo a ser pesquisado usando 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.
...

Também podemos especificar o mesmo intervalo como este usando dois endereços de memória.

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

Por fim, podemos pesquisar para trás no intervalo de memória usando o parâmetro 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

Exemplo de memória desmontada

Este exemplo usa o comando u (unassemble) e o parâmetro L para desmontar três bytes de código.

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

Ou especifique um intervalo de três bytes de memória para desmontar desta forma.

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

Modos de endereço e suporte a segmentos

Em plataformas baseadas em x86, CDB e KD dão suporte aos seguintes modos de endereçamento. Esses modos são diferenciados por seus prefixos.

Prefixo Nome Tipos de endereço
% flat Endereços de 32 bits (também seletores de 16 bits que apontam para segmentos de 32 bits) e endereços de 64 bits em sistemas de 64 bits.
& virtual 86 Endereços no modo real. Somente baseado em x86.
# sem formatação Endereços no modo real. Somente baseado em x86.

A diferença entre os modos simples e virtual de 86 é que um endereço simples de 16 bits usa o valor do segmento como seletor e pesquisa o descritor de segmento. Mas um endereço virtual 86 não usa seletores e, em vez disso, mapeia diretamente para os 1 MB inferiores.

Se você acessar a memória por meio de um modo de endereçamento que não seja o modo padrão atual, poderá usar os prefixos do modo de endereço para substituir o modo de endereço atual.

Argumentos de endereço

Os argumentos de endereço especificam o local de variáveis e funções. A tabela a seguir explica a sintaxe e o significado dos vários endereços que você pode usar em CDB e KD.

Sintaxe Significado

deslocamento

O endereço absoluto no espaço de memória virtual, com um tipo que corresponde ao modo de execução atual. Por exemplo, se o modo de execução atual for de 16 bits, o deslocamento será de 16 bits. Se o modo de execução for segmentado de 32 bits, o deslocamento será segmentado de 32 bits.

&[[ segment:]] offset

O endereço real. Baseado em x86 e baseado em x64.

%segment:[[ offset]]

Um endereço segmentado de 32 bits ou 64 bits. Baseado em x86 e baseado em x64.

%[[ offset]]

Um endereço absoluto (32 bits ou 64 bits) no espaço de memória virtual. Baseado em x86 e baseado em x64.

name[[ +| ]] offset

Um endereço simples de 32 bits ou 64 bits. name pode ser qualquer símbolo. offset especifica o deslocamento. Esse deslocamento pode ser qualquer modo de endereço que seu prefixo indica. Nenhum prefixo especifica um endereço de modo padrão. Você pode especificar o deslocamento como um valor positivo (+) ou negativo (−).

Use o comando dg (Seletor de Exibição) para exibir informações do descritor de segmento.

Consulte Também

Para exibir informações sobre memória, use o comando !address .

Para pesquisar memória, use o comando s (Pesquisar Memória).

Para exibir o conteúdo da memória, use o comando d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory).

Para obter informações sobre como você pode exibir e editar a memória usando uma janela Memória, consulte Usando uma janela de memória.