Share via


Sintaxe Pseudo-Register

O depurador dá suporte a vários pseudo-registros que contêm determinados valores.

O depurador define pseudo-registros automáticos para determinados valores úteis. Pseudo-registros definidos pelo usuário são variáveis de inteiro que você pode gravar ou ler.

Todos os pseudo-registros começam com um cifrão ($). Se você estiver usando a sintaxe MASM, poderá adicionar um sinal de at ( @ ) antes do cifrão. Isso no sinal informa ao depurador que o token a seguir é um registro ou pseudo-registro, não um símbolo. Se você omitir o sinal em , o depurador responderá mais lentamente, pois ele precisará pesquisar a tabela de símbolos inteira.

Por exemplo, os dois comandos a seguir produzem a mesma saída, mas o segundo comando é mais rápido.

0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f

Se existir um símbolo com o mesmo nome que o pseudo-registro, você deverá adicionar o sinal de at.

Se você estiver usando a sintaxe de expressão C++, o sinal de at ( @ ) sempre será necessário.

O comando r (Registers) é uma exceção a essa regra. O depurador sempre interpreta seu primeiro argumento como um registro ou pseudo-registro. (Um sinal de não é necessário ou permitido.) Se houver um segundo argumento para o comando r , ele será interpretado de acordo com a sintaxe de expressão padrão. Se a sintaxe de expressão padrão for C++, você deverá usar o comando a seguir para copiar o pseudo-registro $t 2 para o pseudo-registro $t 1 .

0:000> r $t1 = @$t2

Pseudo-Registers automática

O depurador define automaticamente os pseudo-registros a seguir.

Pseudo-registro Descrição

$ea

O endereço efetivo da última instrução que foi executada. Se esta instrução não tiver um endereço efetivo, o depurador exibirá "Erro de registro inválido". Se essa instrução tiver dois endereços efetivos, o depurador exibirá o primeiro endereço.

$ea 2

O segundo endereço efetivo da última instrução que foi executada. Se essa instrução não tiver dois endereços efetivos, o depurador exibirá "Erro de registro incorreto".

$exp

A última expressão que foi avaliada.

$ra

O endereço de retorno que está atualmente na pilha.

Esse endereço é especialmente útil em comandos de execução. Por exemplo, g @$ra continua até que o endereço de retorno seja encontrado (embora gu (Go Up) seja uma maneira mais precisa e eficaz de "sair" da função atual).

$ip

O registro do ponteiro de instrução.

Processadores baseados em x86: O mesmo que eip. Processadores baseados em Itanium: Relacionado ao iip. (Para obter mais informações, consulte a observação a seguir nesta tabela.) Processadores baseados em x64: O mesmo que rasgar.

$eventip

O ponteiro de instrução no momento do evento atual. Esse ponteiro normalmente corresponde a $ip, a menos que você tenha alternado threads ou alterado manualmente o valor do ponteiro de instrução.

$previp

O ponteiro de instrução no momento do evento anterior. (Invadir o depurador conta como um evento.)

$relip

Um ponteiro de instrução relacionado ao evento atual. Quando você está rastreando branch, esse ponteiro é o ponteiro para a origem do branch.

$scopeip

O ponteiro de instrução para o contexto local atual (também conhecido como escopo).

$exentry

O endereço do ponto de entrada do primeiro executável do processo atual.

$retreg

O registro de valor retornado primário.

Processadores baseados em x86: O mesmo que eax. Processadores baseados em Itanium: O mesmo que ret0. Processadores baseados em x64: O mesmo que rax.

$retreg 64

O registro de valor retornado primário, no formato de 64 bits.

Processador x86: O mesmo que o par edx:eax .

$csp

O ponteiro da pilha de chamadas atual. Esse ponteiro é o registro mais representativo da profundidade da pilha de chamadas.

Processadores baseados em x86: O mesmo que esp. Processadores baseados em Itanium: O mesmo que bsp. Processadores baseados em x64: O mesmo que rsp.

$p

O valor que o último comando d* (Memória de Exibição) imprimiu.

$proc

O endereço do processo atual (ou seja, o endereço do bloco EPROCESS).

$thread

O endereço do thread atual. Na depuração do modo kernel, esse endereço é o endereço do bloco ETHREAD. Na depuração no modo de usuário, esse endereço é o endereço do TEB (bloco de ambiente de thread).

$peb

O endereço do PEB (bloco de ambiente de processo) do processo atual.

$teb

O endereço do TEB (bloco de ambiente de thread) do thread atual.

$tpid

A ID do processo (PID) para o processo que possui o thread atual.

$tid

A ID do thread atual.

$dtid

$dpid

$dsid

Número do $bp

O endereço do ponto de interrupção correspondente. Por exemplo, $bp 3 (ou $bp 03) refere-se ao ponto de interrupção cuja ID do ponto de interrupção é 3. O número é sempre um número decimal. Se nenhum ponto de interrupção tiver uma ID de Número, $bpNúmero será avaliado como zero. Para obter mais informações sobre pontos de interrupção, consulte Usando pontos de interrupção.

$frame

O índice de quadro atual. Esse índice é o mesmo número de quadro que o comando .frame (Definir Contexto Local) usa.

$dbgtime

A hora atual, de acordo com o computador em que o depurador está sendo executado.

$callret

O valor retornado da última função que .call (Função de Chamada) chamou ou que é usada em um comando .fnret /s . O tipo de dados de $callret é o tipo de dados desse valor retornado.

$extret

$extin

$clrex

$lastclrex

Somente depuração gerenciada: O endereço do objeto de exceção CLR (Common Language Runtime) encontrado pela última vez.

$ptrsize

O tamanho de um ponteiro. No modo kernel, esse tamanho é o tamanho do ponteiro no computador de destino.

$pagesize

O número de bytes em uma página de memória. No modo kernel, esse tamanho é o tamanho da página no computador de destino.

$pcr

$pcrb

$argreg

$exr_chance

A chance do registro de exceção atual.

$exr_code

O código de exceção para o registro de exceção atual.

$exr_numparams

O número de parâmetros no registro de exceção atual.

$exr_param0

O valor do Parâmetro 0 no registro de exceção atual.

$exr_param1

O valor do Parâmetro 1 no registro de exceção atual.

$exr_param2

O valor do Parâmetro 2 no registro de exceção atual.

$exr_param3

O valor do Parâmetro 3 no registro de exceção atual.

$exr_param4

O valor do Parâmetro 4 no registro de exceção atual.

$exr_param5

O valor do Parâmetro 5 no registro de exceção atual.

$exr_param6

O valor do Parâmetro 6 no registro de exceção atual.

$exr_param7

O valor do Parâmetro 7 no registro de exceção atual.

$exr_param8

O valor do Parâmetro 8 no registro de exceção atual.

$exr_param9

O valor do Parâmetro 9 no registro de exceção atual.

$exr_param10

O valor do Parâmetro 10 no registro de exceção atual.

$exr_param11

O valor do Parâmetro 11 no registro de exceção atual.

$exr_param12

O valor do Parâmetro 12 no registro de exceção atual.

$exr_param13

O valor do Parâmetro 13 no registro de exceção atual.

$exr_param14

O valor do Parâmetro 14 no registro de exceção atual.

$bug_code

Se ocorreu um bug marcar, esse é o código de bug. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel.

$bug_param1

Se ocorreu um bug marcar, esse é o valor do Parâmetro 1. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel.

$bug_param2

Se ocorreu um bug marcar, esse é o valor do Parâmetro 2. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel.

$bug_param3

Se ocorreu um bug marcar, esse é o valor do Parâmetro 3. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel.

$bug_param4

Se ocorreu um bug marcar, esse é o valor do Parâmetro 4. Aplica-se à depuração do modo kernel dinâmico e despejos de falha do kernel.

Alguns desses pseudo-registros podem não estar disponíveis em determinados cenários de depuração. Por exemplo, você não pode usar $peb, $tid e $tpid ao depurar um minidump no modo de usuário ou determinados arquivos de despejo no modo kernel. Haverá situações em que você poderá aprender informações de thread de ~ (Status do Thread), mas não de $tid. Não é possível usar o pseudo-registro $previp no primeiro evento de depurador. Você não pode usar o pseudo-registro $relip , a menos que esteja rastreando branch. Se você usar um pseudo-registro indisponível, ocorrerá um erro de sintaxe.

Um pseudo-registro que contém o endereço de uma estrutura , como $thread, $proc, $teb, $peb e $lastclrex -- será avaliado de acordo com o tipo de dados adequado no avaliador de expressão C++, mas não no avaliador de expressão MASM. Por exemplo, o comando ? $teb exibe o endereço do TEB, enquanto o comando ?? @$teb exibe toda a estrutura TEB. Para obter mais informações, consulte Avaliando expressões.

Em um processador baseado em Itanium, o registro iip é alinhado a pacotes, o que significa que ele aponta para o slot 0 no pacote que contém a instrução atual, mesmo que um slot diferente esteja sendo executado. Portanto , iip não é o ponteiro de instrução completo. O pseudo-registro $ip é o ponteiro de instrução real, incluindo o pacote e o slot. Os outros pseudo-registros que contêm ponteiros de endereço ($ra, $retreg, $eventip, $previp, $relip e $exentry) têm a mesma estrutura que $ip em todos os processadores.

Você pode usar o comando r para alterar o valor de $ip. Essa alteração também altera automaticamente o registro correspondente. Quando a execução é retomada, ela é retomada no novo endereço do ponteiro de instrução. Esse registro é o único pseudo-registro automático que você pode alterar manualmente.

Nota Na sintaxe MASM, você pode indicar a $ip pseudo-registro com um período ( . ). Você não adiciona um sinal de at (@) antes desse período e não usa o período como o primeiro parâmetro do comando r . Essa sintaxe não é permitida em uma expressão C++.

Os pseudo-registros automáticos são semelhantes aos aliases automáticos. Mas você pode usar aliases automáticos junto com tokens relacionados a alias (como ${ }) e não pode usar pseudo-registros com esses tokens.

Pseudo-Registers definida pelo usuário

Há 20 pseudo-registros definidos pelo usuário ($t 0, $t 1, ..., $t 19). Esses pseudo-registro são variáveis que você pode ler e gravar por meio do depurador. Você pode armazenar qualquer valor inteiro nesses pseudo-registros. Elas podem ser especialmente úteis como variáveis de loop.

Para gravar em um desses pseudo-registros, use o comando r (Registros), como mostra o exemplo a seguir.

0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)

Como todos os pseudo-registros, você pode usar o pseudo-registro definido pelo usuário em qualquer expressão, como mostra o exemplo a seguir.

0:000> bp $t3 
0:000> bp @$t4 
0:000> ?? @$t1 + 4*@$t2 

Um pseudo-registro sempre é digitado como um inteiro, a menos que você use a opção ? junto com o comando r . Se você usar essa opção, o pseudo-registro adquirirá o tipo do que for atribuído a ele. Por exemplo, o comando a seguir atribui o tipo UNICODE_STRING** e o valor 0x0012FFBC a $t 15.

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

Os pseudo-registros definidos pelo usuário usam zero como o valor padrão quando o depurador é iniciado.

Nota Os aliases $u 0, $u 1, ..., $u 9 não são pseudo-registros, apesar de sua aparência semelhante. Para obter mais informações sobre esses aliases, consulte Usando aliases.

Exemplo

O exemplo a seguir define um ponto de interrupção que é atingido sempre que o thread atual chama NtOpenFile. Mas esse ponto de interrupção não é atingido quando outros threads chamam NtOpenFile.

kd> bp /t @$thread nt!ntopenfile

Exemplo

O exemplo a seguir executa um comando até que o registro mantenha um valor especificado. Primeiro, coloque o código a seguir para a etapa condicional em um arquivo de script chamado "eaxstep".

.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }

Em seguida, emita o comando a seguir.

t "$<eaxstep"

O depurador executa uma etapa e executa o comando. Nesse caso, o depurador executa o script, que exibe 1234 ou repete o processo.