Share via


Sintaxis de intervalo de direcciones y direcciones

Hay varias maneras de especificar direcciones en el depurador.

Las direcciones son normalmente direcciones virtuales, excepto cuando la documentación indica específicamente otro tipo de dirección. En el modo de usuario, el depurador interpreta las direcciones virtuales según el directorio de página del proceso actual. En el modo kernel, el depurador interpreta las direcciones virtuales según el directorio de página del proceso que especifica el contexto del proceso . También puede establecer directamente el contexto de dirección en modo de usuario. Para obtener más información sobre el contexto de dirección en modo de usuario, vea .context (Establecer User-Mode contexto de dirección).

En las expresiones MASM, puede usar el operador poi para desreferenciar cualquier puntero. Por ejemplo, si el puntero en la dirección 0x0000008e'ed57b108 apunta a la ubicación de la dirección 0x805287637256, los dos comandos siguientes son equivalentes.

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

Ejemplo de dirección de memoria para mostrar

Para ver un ejemplo de uso de poi, determine el desplazamiento de CurrentLocale del bloque de entorno de subprocesos (TEB). Use el comando dx para mostrar @$teb, que es un ejemplo de pseudo-registers, que contienen direcciones comunes, como la ubicación del contador del programa actual.

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

...

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

CurrentLocale es +0x108 desde el principio del TEB. A continuación, determine la dirección de memoria de esa ubicación.

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

Use poi para desreferenciar esa dirección para ver que contiene el valor CurrentLocale de 0x409.

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

En las expresiones del depurador de C++, los punteros se comportan como punteros en C++. Sin embargo, los números se interpretan como enteros. Si tiene que deferir un número real, es posible que tenga que convertirlo primero, como se muestra en el ejemplo siguiente.

Para probarlo, use .expr para establecer el evaluador de expresiones en C++.

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

Con el evaluador de expresiones establecido en C++, podemos convertir mediante long.

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

Para obtener más información sobre la conversión de valores numéricos, vea Números y operadores de C++.

Si el evaluador de expresiones se establece en c++, podemos encapsular el puntero de punto con @@masm(), para que solo esa parte de la expresión se evalúe por el evaluador de expresiones 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 obtener más información sobre los dos evaluadores de expresiones, vea Evaluación de expresiones.

También puede indicar una dirección en una aplicación especificando el nombre de archivo de origen original y el número de línea. Para obtener más información sobre cómo especificar esta información, vea Sintaxis de línea de origen.

Intervalos de direcciones

Puede especificar un intervalo de direcciones por un par de direcciones o por un número de direcciones y objetos.

Para especificar un intervalo por un par de direcciones, especifique la dirección inicial y la dirección final. Por ejemplo, el ejemplo siguiente es un intervalo de 8 bytes, empezando por la dirección 0x00001000.

0x00001000  0x00001007

Para especificar un intervalo de direcciones por una dirección y un recuento de objetos, especifique un argumento address, la letra L (mayúsculas o minúsculas) y un argumento value. La dirección especifica la dirección inicial. El valor especifica el número de objetos que se van a examinar o mostrar. El tamaño del objeto depende del comando . Por ejemplo, si el tamaño del objeto es de 1 byte, el ejemplo siguiente es un intervalo de 8 bytes, empezando por la dirección 0x00001000.

0x00001000  L8

Sin embargo, si el tamaño del objeto es una palabra doble (32 bits o 4 bytes), los dos intervalos siguientes proporcionan un intervalo de 8 bytes.

0x00001000  0x00001007
0x00001000  L2

Especificador de intervalo de tamaño L

Hay otras dos maneras de especificar el valor (el especificador de intervalode tamaño L):

  • ¿L?Tamaño (con un signo de interrogación) significa lo mismo que LSize, excepto la L?El tamaño quita el límite de intervalo automático del depurador. Normalmente, hay un límite de intervalo de 256 MB, ya que los intervalos más grandes son errores tipográficos. Si desea especificar un intervalo mayor que 256 MB, debe usar la L?Sintaxis de tamaño .

  • L-Size (con un guión) especifica un intervalo de longitud Tamaño que termina en la dirección especificada. Por ejemplo, 80000000 L20 especifica el intervalo entre 0x80000000 y 0x8000001F y 80000000 L-20 especifica el intervalo de 0x7FFFFFE0 a 0x7FFFFFFF.

Algunos comandos que solicitan intervalos de direcciones aceptan una sola dirección como argumento. En esta situación, el comando usa algún recuento de objetos predeterminado para calcular el tamaño del intervalo. Normalmente, los comandos para los que el intervalo de direcciones es el parámetro final permiten esta sintaxis. Para obtener la sintaxis exacta y el tamaño del intervalo predeterminado para cada comando, consulte los temas de referencia de cada comando.

Ejemplo de intervalo de memoria de búsqueda

En primer lugar, determinaremos la dirección del registro del puntero de instrucción rip mediante el evaluador de expresiones MASM.

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

A continuación, buscaremos a partir de 00007ffc'0f180771, para 100000 mediante el comando s (Memoria de búsqueda). Especificamos el intervalo que se va a buscar mediante 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.
...

También podemos especificar el mismo intervalo como este con dos direcciones de memoria.

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 último, podemos buscar hacia atrás en el intervalo de memoria mediante el parámetro de longitud L.

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

Ejemplo de memoria no ensamblable

En este ejemplo, se usa el comando u (unassemble) y el parámetro L para anular el ensamblado de tres 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

O bien, especifique un intervalo de memoria de tres bytes para no ensamblar como este.

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 dirección y compatibilidad con segmentos

En las plataformas basadas en x86, CDB y KD admiten los siguientes modos de direccionamiento. Estos modos se distinguen por sus prefijos.

Prefijo Nombre Tipos de direcciones
% piso Direcciones de 32 bits (también selectores de 16 bits que apuntan a segmentos de 32 bits) y direcciones de 64 bits en sistemas de 64 bits.
& virtual 86 Direcciones en modo real. Solo basado en x86.
# plain Direcciones en modo real. Solo basado en x86.

La diferencia entre los modos simple y virtual 86 es que una dirección de 16 bits sin formato usa el valor de segmento como selector y busca el descriptor de segmento. Pero una dirección virtual 86 no usa selectores y, en su lugar, se asigna directamente a los 1 MB inferiores.

Si accede a la memoria a través de un modo de direccionamiento que no es el modo predeterminado actual, puede usar los prefijos del modo de dirección para invalidar el modo de dirección actual.

Argumentos de dirección

Los argumentos address especifican la ubicación de variables y funciones. En la tabla siguiente se explica la sintaxis y el significado de las distintas direcciones que puede usar en CDB y KD.

Sintaxis Significado

offset

Dirección absoluta en el espacio de memoria virtual, con un tipo que corresponde al modo de ejecución actual. Por ejemplo, si el modo de ejecución actual es de 16 bits, el desplazamiento es de 16 bits. Si el modo de ejecución está segmentado de 32 bits, el desplazamiento es segmentado de 32 bits.

&Desplazamiento [[ segment:]]

Dirección real. Basado en x86 y basado en x64.

%segment:[[ offset]]

Una dirección segmentada de 32 o 64 bits. Basado en x86 y basado en x64.

%[[ offset]]

Una dirección absoluta (de 32 o 64 bits) en el espacio de memoria virtual. Basado en x86 y basado en x64.

name[[ +| ]] offset

Una dirección plana de 32 o 64 bits. name puede ser cualquier símbolo. offset especifica el desplazamiento. Este desplazamiento puede ser cualquier modo de dirección que indique su prefijo. Ningún prefijo especifica una dirección de modo predeterminada. Puede especificar el desplazamiento como un valor positivo (+) o negativo (-).

Use el comando dg (Selector de pantalla) para ver la información del descriptor de segmento.

Consulte también

Para mostrar información sobre la memoria, use el comando !address .

Para buscar memoria, use el comando s (Memoria de búsqueda).

Para mostrar el contenido de la memoria, use el comando d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory).

Para obtener información sobre cómo puede ver y editar la memoria mediante una ventana Memoria, vea Usar una ventana de memoria.