Sintaxis de Pseudo-Register
El depurador admite varios pseudo-registros que contienen determinados valores.
El depurador establece los pseudo-registros automáticos en determinados valores útiles. Los pseudo-registros definidos por el usuario son variables enteras que se pueden escribir en o leer.
Todos los pseudo-registros comienzan con un signo de dólar ($). Si usa la sintaxis de MASM, puede agregar un signo en signo ( @ ) antes del signo de dólar. Esto en signo indica al depurador que el siguiente token es un registro o pseudo-registro, no un símbolo. Si omite el signo, el depurador responde más lentamente, ya que tiene que buscar en toda la tabla de símbolos.
Por ejemplo, los dos comandos siguientes generan la misma salida, pero el segundo comando es más rápido.
0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f
Si existe un símbolo con el mismo nombre que el pseudo-registro, debe agregar el signo at.
Si usa la sintaxis de expresión de C++, siempre se requiere el signo at ( @ ).
El comando r (Registers) es una excepción a esta regla. El depurador siempre interpreta su primer argumento como registro o pseudo-registro. (No se requiere ni permite un signo). Si hay un segundo argumento para el comando r , se interpreta según la sintaxis de expresión predeterminada. Si la sintaxis de expresión predeterminada es C++, debe usar el siguiente comando para copiar el pseudo-registro de $t 2 en el pseudo-register de $t 1 .
0:000> r $t1 = @$t2
Pseudo-Registers automática
El depurador establece automáticamente los pseudo-registros siguientes.
Pseudo-registro | Descripción |
---|---|
$ea |
Dirección efectiva de la última instrucción que se ejecutó. Si esta instrucción no tiene una dirección efectiva, el depurador muestra "Error de registro incorrecto". Si esta instrucción tiene dos direcciones eficaces, el depurador muestra la primera dirección. |
$ea 2 |
Segunda dirección efectiva de la última instrucción que se ejecutó. Si esta instrucción no tiene dos direcciones eficaces, el depurador muestra "Error de registro incorrecto". |
$exp |
Última expresión que se evaluó. |
$ra |
Dirección de devolución que se encuentra actualmente en la pila. Esta dirección es especialmente útil en los comandos de ejecución. Por ejemplo, g @$ra continúa hasta que se encuentra la dirección de retorno (aunque gu (Ir arriba) es una manera más precisa de "salir" de la función actual). |
$ip |
Registro del puntero de instrucción. Procesadores basados en x86: Igual que eip. Procesadores basados en Itanium: Relacionado con iip. (Para obtener más información, consulte la nota siguiente a esta tabla). Procesadores basados en x64: Lo mismo que rasgar. |
$eventip |
Puntero de instrucción en el momento del evento actual. Este puntero suele coincidir con $ip, a menos que cambie los subprocesos o cambie manualmente el valor del puntero de instrucción. |
$previp |
Puntero de instrucción en el momento del evento anterior. (La separación en el depurador cuenta como un evento). |
$relip |
Puntero de instrucción relacionado con el evento actual. Cuando se realiza el seguimiento de ramas, este puntero es el puntero al origen de la rama. |
$scopeip |
Puntero de instrucción para el contexto local actual (también conocido como ámbito). |
$exentry |
Dirección del punto de entrada del primer ejecutable del proceso actual. |
$retreg |
Registro del valor devuelto principal. Procesadores basados en x86: Igual que eax. Procesadores basados en Itanium: Igual que ret0. Procesadores basados en x64: Igual que rax. |
$retreg 64 |
Registro del valor devuelto principal, en formato de 64 bits. Procesador x86: Igual que el par edx:eax . |
$csp |
Puntero de pila de llamadas actual. Este puntero es el registro más representativo de la profundidad de la pila de llamadas. Procesadores basados en x86: Igual que esp. Procesadores basados en Itanium: Igual que bsp. Procesadores basados en x64: Igual que rsp. |
$p |
Valor que imprimió el último comando d* (Memoria para mostrar ). |
$proc |
Dirección del proceso actual (es decir, la dirección del bloque EPROCESS). |
$thread |
Dirección del subproceso actual. En la depuración en modo kernel, esta dirección es la dirección del bloque ETHREAD. En la depuración en modo de usuario, esta dirección es la dirección del bloque de entorno de subprocesos (TEB). |
$peb |
Dirección del bloque de entorno de proceso (PEB) del proceso actual. |
$teb |
Dirección del bloque de entorno de subprocesos (TEB) del subproceso actual. |
$tpid |
Identificador de proceso (PID) del proceso que posee el subproceso actual. |
$tid |
Identificador del subproceso del subproceso actual. |
$dtid |
|
$dpid |
|
$dsid |
|
número de $bp |
Dirección del punto de interrupción correspondiente. Por ejemplo, $bp 3 (o $bp 03) hace referencia al punto de interrupción cuyo identificador de punto de interrupción es 3. Number siempre es un número decimal. Si ningún punto de interrupción tiene un identificador de Number, $bpNumber se evalúa como cero. Para obtener más información sobre los puntos de interrupción, vea Uso de puntos de interrupción. |
$frame |
Índice de marco actual. Este índice es el mismo número de fotograma que usa el comando .frame (Establecer contexto local ). |
$dbgtime |
La hora actual, según el equipo en el que se ejecuta el depurador. |
$callret |
Valor devuelto de la última función a la que llamó .call (Call Function) o que se usa en un comando .fnret /s . El tipo de datos de $callret es el tipo de datos de este valor devuelto. |
$extret |
|
$extin |
|
$clrex |
|
$lastclrex |
Solo depuración administrada: Dirección del último objeto de excepción de Common Language Runtime (CLR). |
$ptrsize |
Tamaño de un puntero. En el modo kernel, este tamaño es el tamaño del puntero en el equipo de destino. |
$pagesize |
Número de bytes en una página de memoria. En el modo kernel, este tamaño es el tamaño de página en el equipo de destino. |
$pcr |
|
$pcrb |
|
$argreg |
|
$exr_chance |
Posibilidad del registro de excepción actual. |
$exr_code |
Código de excepción del registro de excepción actual. |
$exr_numparams |
Número de parámetros del registro de excepción actual. |
$exr_param0 |
Valor del parámetro 0 en el registro de excepción actual. |
$exr_param1 |
Valor del parámetro 1 en el registro de excepción actual. |
$exr_param2 |
Valor del parámetro 2 en el registro de excepción actual. |
$exr_param3 |
Valor del parámetro 3 en el registro de excepción actual. |
$exr_param4 |
Valor del parámetro 4 en el registro de excepción actual. |
$exr_param5 |
Valor del parámetro 5 en el registro de excepción actual. |
$exr_param6 |
Valor del parámetro 6 en el registro de excepción actual. |
$exr_param7 |
Valor del parámetro 7 en el registro de excepción actual. |
$exr_param8 |
Valor del parámetro 8 en el registro de excepción actual. |
$exr_param9 |
Valor del parámetro 9 en el registro de excepción actual. |
$exr_param10 |
Valor del parámetro 10 en el registro de excepción actual. |
$exr_param11 |
Valor del parámetro 11 en el registro de excepción actual. |
$exr_param12 |
Valor del parámetro 12 en el registro de excepción actual. |
$exr_param13 |
Valor del parámetro 13 en el registro de excepción actual. |
$exr_param14 |
Valor del parámetro 14 en el registro de excepción actual. |
$bug_code |
Si se ha producido una comprobación de errores, este es el código de error. Se aplica a la depuración en modo kernel activo y a los volcados de memoria del kernel. |
$bug_param1 |
Si se ha producido una comprobación de errores, este es el valor del parámetro 1. Se aplica a la depuración en modo kernel activo y a los volcados de memoria del kernel. |
$bug_param2 |
Si se ha producido una comprobación de errores, este es el valor del parámetro 2. Se aplica a la depuración en modo kernel activo y a los volcados de memoria del kernel. |
$bug_param3 |
Si se ha producido una comprobación de errores, este es el valor del parámetro 3. Se aplica a la depuración en modo kernel activo y a los volcados de memoria del kernel. |
$bug_param4 |
Si se ha producido una comprobación de errores, este es el valor del parámetro 4. Se aplica a la depuración en modo kernel activo y a los volcados de memoria del kernel. |
Es posible que algunos de estos pseudo-registros no estén disponibles en determinados escenarios de depuración. Por ejemplo, no puede usar $peb, $tid y $tpid al depurar un minivolcado en modo de usuario o determinados archivos de volcado de modo kernel. Habrá situaciones en las que puede aprender información de subprocesos de ~ (estado del subproceso), pero no de $tid. No se puede usar el $previp pseudo-register en el primer evento del depurador. No puede usar el $relip pseudo-register a menos que sea el seguimiento de ramas. Si usa un pseudo-registro no disponible, se produce un error de sintaxis.
Un pseudo-registro que contiene la dirección de una estructura (como $thread, $proc, $teb, $peb y $lastclrex ) se evaluará según el tipo de datos adecuado en el evaluador de expresiones de C++, pero no en el evaluador de expresiones masm. Por ejemplo, el comando ? $teb muestra la dirección del TEB, mientras que el comando ?? @$teb muestra toda la estructura TEB. Para obtener más información, vea Evaluación de expresiones.
En un procesador basado en Itanium, el registro iip está alineado con agrupación, lo que significa que apunta a la ranura 0 del lote que contiene la instrucción actual, incluso si se ejecuta una ranura diferente. Por lo tanto , iip no es el puntero de instrucción completa. El $ip pseudo-register es el puntero de instrucción real, incluido el lote y la ranura. Los demás pseudo-registros que contienen punteros de dirección ($ra, $retreg, $eventip, $previp, $relip y $exentry) tienen la misma estructura que $ip en todos los procesadores.
Puede usar el comando r para cambiar el valor de $ip. Este cambio también cambia automáticamente el registro correspondiente. Cuando se reanuda la ejecución, se reanuda en la nueva dirección del puntero de instrucción. Este registro es el único pseudo-registro automático que puede cambiar manualmente.
Nota En la sintaxis de MASM, puede indicar el $ip pseudo-register con un punto ( . ). No agregue un signo a signo (@) antes de este período y no use el punto como primer parámetro del comando r . Esta sintaxis no se permite dentro de una expresión de C++.
Los pseudo-registros automáticos son similares a los alias automáticos. Sin embargo, puede usar alias automáticos junto con tokens relacionados con alias (como ${ }) y no puede usar pseudo-registros con dichos tokens.
Pseudo-Registers definidas por el usuario
Hay 20 pseudo-registros definidos por el usuario ($t 0, $t 1, ..., $t 19). Estos pseudo-registro son variables que se pueden leer y escribir a través del depurador. Puede almacenar cualquier valor entero en estos pseudo-registros. Pueden ser especialmente útiles como variables de bucle.
Para escribir en uno de estos pseudo-registros, use el comando r (Registers), como se muestra en el ejemplo siguiente.
0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)
Al igual que todos los pseudo-registros, puede usar el pseudo-registro definido por el usuario en cualquier expresión, como se muestra en el ejemplo siguiente.
0:000> bp $t3
0:000> bp @$t4
0:000> ?? @$t1 + 4*@$t2
Un pseudo-registro siempre se escribe como un entero, a menos que use el modificador ? junto con el comando r . Si usa este modificador, el pseudo-registro adquiere el tipo de lo que se le asigna. Por ejemplo, el siguiente comando asigna el tipo UNICODE_STRING** y el valor de 0x0012FFBC a $t 15.
0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc
Los pseudo-registros definidos por el usuario usan cero como valor predeterminado cuando se inicia el depurador.
Nota Los alias $u 0, $u 1, ..., $u 9 no son pseudo-registros, a pesar de su apariencia similar. Para obtener más información sobre estos alias, consulte Uso de alias.
Ejemplo
En el ejemplo siguiente se establece un punto de interrupción que se alcanza cada vez que el subproceso actual llama a NtOpenFile. Pero este punto de interrupción no se alcanza cuando otros subprocesos llaman a NtOpenFile.
kd> bp /t @$thread nt!ntopenfile
Ejemplo
En el ejemplo siguiente se ejecuta un comando hasta que el registro contiene un valor especificado. En primer lugar, coloque el código siguiente para la ejecución paso a paso condicional en un archivo de script denominado "eaxstep".
.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }
A continuación, emita el siguiente comando.
t "$<eaxstep"
El depurador realiza un paso y, a continuación, ejecuta el comando . En este caso, el depurador ejecuta el script, que muestra 1234 o repite el proceso.