Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este tópico descreve o uso da sintaxe de expressão do Microsoft Macro Assembler (MASM) com as ferramentas de depuração do Windows.
O depurador aceita dois tipos diferentes de expressões numéricas: expressões C++ e expressões MASM. Cada uma dessas expressões segue suas próprias regras de sintaxe para entrada e saída.
Para obter mais informações sobre quando cada tipo de sintaxe é usado, consulte Avaliando expressões e ? (Avaliar Expressão).
Neste exemplo, o ? exibe o valor do registro do ponteiro de instrução usando o avaliador de expressão MASM.
0:000> ? @rip
Evaluate expression: 140709230544752 = 00007ff9`6bb40770
Definir o Avaliador de Expressão como MASM
Use o .expr (Choose Expression Evaluator) para ver qual é o avaliador de expressão padrão e altere-o para MASM.
0:000> .expr /s masm
Current expression evaluator: MASM - Microsoft Assembler expressions
Agora que o avaliador de expressão padrão foi alterado, o ? (Avaliar Expressão) pode ser usado para exibir expressões MASM. Este exemplo adiciona o valor hexadecimal de 8 ao registro rip.
0:000> ? @rip + 8
Evaluate expression: 140709230544760 = 00007ff9`6bb40778
A referência de registo @rip é descrita em mais detalhes em Sintaxe de Registo.
Números nas expressões MASM do Depurador
Você pode colocar números em expressões MASM na base 16, 10, 8 ou 2.
Use o comando n (set Number Base) para definir o radix padrão como 16, 10 ou 8. Todos os números não prefixados são então interpretados nesta base. Você pode substituir o radix padrão especificando o prefixo 0x (hexadecimal), o prefixo 0n (decimal), o prefixo 0t (octal) ou o prefixo 0y (binário).
Você também pode especificar números hexadecimais adicionando um h após o número. Você pode usar letras maiúsculas ou minúsculas dentro de números. Por exemplo, "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" e "4aB3H" têm o mesmo significado.
Se você não adicionar um número após o prefixo em uma expressão, o número será lido como 0. Portanto, você pode escrever 0 como 0, o prefixo seguido de 0 e apenas o prefixo. Por exemplo, em hexadecimal, "0", "0x0" e "0x" têm o mesmo significado.
Você pode inserir valores hexadecimais de 64 bits no formato xxxxxxxx'xxxxxxxx. Pode também omitir o acento grave ('). Se você incluir o acento grave, a extensão automática do sinal será desativada.
Este exemplo mostra como adicionar um valor decimal, octal e binário para registrar 10.
? @r10 + 0x10 + 0t10 + 0y10
Evaluate expression: 26 = 00000000`0000001a
Símbolos em expressões MASM do depurador
Em expressões MASM, o valor numérico de qualquer símbolo é seu endereço de memória. Dependendo do que o símbolo se refere, esse endereço é o endereço de uma variável global, variável local, função, segmento, módulo ou qualquer outro rótulo reconhecido.
Para especificar a qual módulo o endereço está associado, inclua o nome do módulo e um ponto de exclamação (!) antes do nome do símbolo. Se o símbolo puder ser interpretado como um número hexadecimal, inclua o nome do módulo e um ponto de exclamação, ou apenas um ponto de exclamação, antes do nome do símbolo. Para obter mais informações sobre reconhecimento de símbolos, consulte Sintaxe de símbolos e correspondência de símbolos.
Use dois pontos (::) ou dois sublinhados (__) para indicar os membros de uma classe.
Use um acento grave (') ou um apóstrofo (') em um nome de símbolo somente se você adicionar um nome de módulo e ponto de exclamação antes do símbolo.
Operadores numéricos em expressões MASM
Você pode modificar qualquer componente de uma expressão usando um operador unário. Você pode combinar quaisquer dois componentes usando um operador binário. Os operadores unários têm precedência sobre os operadores binários. Quando você usa vários operadores binários, os operadores seguem as regras de precedência fixa descritas nas tabelas a seguir.
Você sempre pode usar parênteses para substituir regras de precedência.
Se parte de uma expressão MASM estiver entre parênteses e dois sinais (@@) aparecerem antes da expressão, a expressão será interpretada de acordo com as regras de expressão C++. Não é possível adicionar um espaço entre os dois sinais de arroba e o parêntese de abertura. Você também pode especificar o avaliador de expressão usando @@c++( ... ) ou @@masm( ... ).
Quando executa cálculos aritméticos, o avaliador de expressões MASM considera todos os números e símbolos como tipos ULONG64.
Os operadores de endereços unários assumem o DS como o segmento padrão para endereços. As expressões são avaliadas por ordem de precedência do operador. Se os operadores adjacentes tiverem igual precedência, a expressão será avaliada da esquerda para a direita.
Você pode usar os seguintes operadores unários.
| Operador | Significado |
|---|---|
+ |
Unário mais |
- |
Unário menos |
não |
Retorna 1 se o argumento for zero. Retorna zero para qualquer argumento diferente de zero. |
Olá |
16 bits superiores |
baixo |
16 bits menos significativos |
por |
Byte de ordem baixa do endereço especificado. |
$pby |
O mesmo que por, exceto que aceita um endereço físico. Somente a memória física que usa o comportamento de cache padrão pode ser lida. |
wo |
Palavra de ordem baixa do endereço especificado. |
$pwo |
O mesmo que wo exceto que usa um endereço físico. Somente a memória física que usa o comportamento de cache padrão pode ser lida. |
DWO |
Palavra dupla do endereço especificado. |
$pdwo |
O mesmo que dwo, exceto que aceita um endereço físico. Somente a memória física que usa o comportamento de cache padrão pode ser lida. |
QWO |
Quad-word do endereço especificado. |
$pqwo |
O mesmo que qwo exceto que aceita um endereço físico. Somente a memória física que usa o comportamento de cache padrão pode ser lida. |
POI |
Dados em tamanho de ponteiro provenientes do endereço especificado. O tamanho do ponteiro é de 32 bits ou 64 bits. Na depuração do kernel, este tamanho é baseado no processador do computador target. Portanto, poi é o melhor operador para usar se você quiser dados do tamanho de um ponteiro. |
$ppoi |
O mesmo que poi , exceto que leva um endereço físico. Somente a memória física que usa o comportamento de cache padrão pode ser lida. |
Exemplos
O exemplo a seguir mostra como usar poi para desreferenciar um ponteiro para ver o valor armazenado nessa localização de memória.
Primeiro, determine o endereço de memória de interesse. Por exemplo, podemos examinar a estrutura do thread e decidir que queremos ver o valor do CurrentLocale.
0:000> dx @$teb
@$teb : 0x8eed57b000 [Type: _TEB *]
[+0x000] NtTib [Type: _NT_TIB]
[+0x038] EnvironmentPointer : 0x0 [Type: void *]
[+0x040] ClientId [Type: _CLIENT_ID]
[+0x050] ActiveRpcHandle : 0x0 [Type: void *]
[+0x058] ThreadLocalStoragePointer : 0x1f8f9d634a0 [Type: void *]
[+0x060] ProcessEnvironmentBlock : 0x8eed57a000 [Type: _PEB *]
[+0x068] LastErrorValue : 0x0 [Type: unsigned long]
[+0x06c] CountOfOwnedCriticalSections : 0x0 [Type: unsigned long]
[+0x070] CsrClientThread : 0x0 [Type: void *]
[+0x078] Win32ThreadInfo : 0x0 [Type: void *]
[+0x080] User32Reserved [Type: unsigned long [26]]
[+0x0e8] UserReserved [Type: unsigned long [5]]
[+0x100] WOW32Reserved : 0x0 [Type: void *]
[+0x108] CurrentLocale : 0x409 [Type: unsigned long]
CurrentLocale está localizado 0x108 além do início do TEB.
0:000> ? @$teb + 0x108
Evaluate expression: 613867303176 = 0000008e`ed57b108
Use poi para desreferenciar esse endereço.
0:000> ? poi(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
O valor retornado de 409 corresponde ao valor de CurrentLocale na estrutura TEB.
Ou use poi e parênteses para desreferenciar o endereço calculado.
0:000> ? poi(@$teb + 0x108)
Evaluate expression: 1033 = 00000000`00000409
Use os operadores by ou wo unary para retornar um byte ou palavra do endereço de destino.
0:000> ? by(0000008e`ed57b108)
Evaluate expression: 9 = 00000000`00000009
0:000> ? wo(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
Operadores binários
Você pode usar os seguintes operadores binários. Os operadores em cada célula têm precedência sobre aqueles nas células inferiores. Os operadores na mesma célula têm a mesma precedência e são analisados da esquerda para a direita.
| Operador | Significado |
|---|---|
* / mod (ou %) |
Multiplicação Divisão inteira Módulo (restante) |
+ - |
Adição Subtração |
<< >> >>> |
Mudança para a esquerda Desvio lógico para a direita Desvio aritmético para a direita |
= (ou ==) < > <= >= != |
Igual a Menos de Maior que Menor que ou igual a Maior ou igual a Não é igual a |
e (ou &) |
Bitwise E |
xor (ou ^) |
Bitwise XOR (OR exclusivo) |
ou (ou |) |
Bitwise OU |
Os <operadores de comparação , >, =, ==, e != avaliam até 1 se a expressão é verdadeira ou zero se a expressão é falsa. Um único sinal de igual (=) é o mesmo que um sinal de igual duplo (==). Você não pode usar efeitos colaterais ou atribuições dentro de uma expressão MASM.
Uma operação inválida (como divisão por zero) resulta num "Erro de operando", que é retornado na janela de comandos do depurador.
Podemos verificar se o valor retornado corresponde a 0x409 usando o operador == comparação.
0:000> ? poi(@$teb + 0x108)==0x409
Evaluate expression: 1 = 00000000`00000001
Operadores não numéricos em expressões MASM
Você também pode usar os seguintes operadores adicionais em expressões MASM.
| Operador | Significado |
|---|---|
$fnsucc(FnAddress, RetVal, Flag) |
Interpreta o valor RetVal como um valor de retorno para a função que está localizada no endereço FnAddress . Se esse valor de retorno se qualificar como um código de êxito, $fnsucc retornará TRUE. Caso contrário, $fnsucc retorna FALSE. Se o tipo de retorno for BOOL, bool, HANDLE, HRESULT ou NTSTATUS, $fnsucc entende corretamente se o valor de retorno especificado se qualifica como um código de sucesso. Se o tipo de retorno for um ponteiro, todos os valores diferentes de NULL serão qualificados como códigos de êxito. Para qualquer outro tipo, o sucesso é definido pelo valor de Flag. Se Flag for 0, então um valor diferente de zero de RetVal indica sucesso. Se Flag for 1, um valor zero de RetVal indica sucesso. |
$iment (Endereço) |
Retorna o endereço do ponto de entrada da imagem na lista de módulos carregados. Address especifica o endereço base da imagem do executável portátil (PE). A entrada é encontrada procurando o ponto de entrada da imagem no cabeçalho da imagem PE da imagem que o Endereço especifica. Você pode usar essa função para ambos os módulos que já estão na lista de módulos e para definir pontos de interrupção não resolvidos usando o comando bu . |
$scmp("String1", "String2") |
Avalia como -1, 0 ou 1, tal como o strcmp, utilizando a função C strcmp. |
$sicmp("String1", "String2") |
Avalia um valor de -1, 0 ou 1, semelhante à função stricmp do Microsoft Win32. |
$spat("String", "Padrão") |
Avalia como TRUE ou FALSE dependendo se String corresponde ao Pattern. A correspondência não diferencia maiúsculas de minúsculas. O padrão pode conter uma variedade de caracteres curinga e especificadores. Para obter mais informações sobre a sintaxe, consulte Sintaxe curinga de cadeia de caracteres. |
$vvalid(Endereço,Comprimento) |
Determina se o intervalo de memória que começa em Endereço e se estende para bytes de comprimento é válido. Se a memória for válida, $vvalid será avaliada como 1. Se a memória for inválida, $vvalid será avaliada como 0. |
Exemplos
A seguir mostra como investigar o intervalo de memória válida em torno de um módulo carregado:
Primeiro, determine o endereço da área de interesse, por exemplo, usando o comando lm (List Loaded Modules .
0:000> lm
start end module name
00007ff6`0f620000 00007ff6`0f658000 notepad (deferred)
00007ff9`591d0000 00007ff9`5946a000 COMCTL32 (deferred)
...
Use $vvalid para verificar um intervalo de memória.
0:000> ? $vvalid(0x00007ff60f620000, 0xFFFF)
Evaluate expression: 1 = 00000000`00000001
Use $vvalid para confirmar que esse intervalo maior é um intervalo de memória inválido.
0:000> ? $vvalid(0x00007ff60f620000, 0xFFFFF)
Evaluate expression: 0 = 00000000`00000000
Este também é um intervalo inválido.
0:000> ? $vvalid(0x0, 0xF)
Evaluate expression: 0 = 00000000`00000000
Use não para retornar zero quando o intervalo de memória for válido.
0:000> ? not($vvalid(0x00007ff60f620000, 0xFFFF))
Evaluate expression: 0 = 00000000`00000000
Use $imnet para examinar o ponto de entrada do COMCTL32, que determinámos anteriormente usando o comando lm para saber o endereço. Começa em 00007ff9'591d0000.
0:000> ? $iment(00007ff9`591d0000)
Evaluate expression: 140708919287424 = 00007ff9`59269e80
Desmonte o endereço retornado para examinar o código do ponto de entrada.
0:000> u 00007ff9`59269e80
COMCTL32!DllMainCRTStartup:
00007ff9`59269e80 48895c2408 mov qword ptr [rsp+8],rbx
00007ff9`59269e85 4889742410 mov qword ptr [rsp+10h],rsi
00007ff9`59269e8a 57 push rdi
COMCTL32 é exibido na saída confirmando que este é o ponto de entrada para este módulo.
Registros e Pseudo-Registers em expressões MASM
Você pode usar registradores e pseudo-registros dentro de expressões MASM. Pode adicionar um sinal de arroba (@) antes de todos os registos e pseudo-registos. O sinal de arroba faz com que o depurador acesse o valor mais rapidamente. Este sinal @ é desnecessário para os registos baseados em x86 mais comuns. Para outros registos e pseudo-registos, recomendamos que adicione a arroba, mas não é obrigatório. Se você omitir o sinal de arroba para os registros menos comuns, o depurador tentará analisar o texto como um número hexadecimal, depois como um símbolo e, finalmente, como um registro.
Você também pode usar um ponto (.) para indicar o ponteiro de instrução atual. Você não deve adicionar um sinal @ antes desse período e não pode usar um ponto como o primeiro parâmetro do comando r. Este período tem o mesmo significado que o $ip pseudo-registo.
Para obter mais informações sobre registros e pseudo-registros, consulte Sintaxe de registro e sintaxePseudo-Register.
Use o comando r register para ver que o valor do registo @rip é 00007ffb'7ed00770.
0:000> r
rax=0000000000000000 rbx=0000000000000010 rcx=00007ffb7eccd2c4
rdx=0000000000000000 rsi=00007ffb7ed61a80 rdi=00000027eb6a7000
rip=00007ffb7ed00770 rsp=00000027eb87f320 rbp=0000000000000000
r8=00000027eb87f318 r9=0000000000000000 r10=0000000000000000
r11=0000000000000246 r12=0000000000000040 r13=0000000000000000
r14=00007ffb7ed548f0 r15=00000210ea090000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffb`7ed00770 cc int 3
Esse mesmo valor pode ser exibido usando o . atalho de período.
0:000> ? .
Evaluate expression: 140718141081456 = 00007ffb`7ed00770
Podemos confirmar que esses valores são todos equivalentes, e retornar zero se forem, usando esta expressão MASM.
0:000> ? NOT(($ip = .) AND ($ip = @rip) AND (@rip =. ))
Evaluate expression: 0 = 00000000`00000000
Números de linha de origem em expressões MASM
Você pode usar expressões de arquivo de origem e número de linha em expressões MASM. Deve incluir estas expressões utilizando acentos graves ('). Para obter mais informações sobre a sintaxe, consulte Sintaxe da linha de origem.