Números y operadores de MASM

En este tema se describe el uso de la sintaxis de expresiones de Microsoft Macro Assembler (MASM) con las herramientas de depuración de Windows.

El depurador acepta dos tipos diferentes de expresiones numéricas: expresiones de C++ y expresiones MASM. Cada una de estas expresiones sigue sus propias reglas de sintaxis para la entrada y salida.

Para obtener más información sobre cuándo se usa cada tipo de sintaxis, vea Evaluación de expresiones y ? (Evaluar expresión).

En este ejemplo, el ? el comando muestra el valor del registro del puntero de instrucción mediante el evaluador de expresiones MASM.

0:000> ? @rip
Evaluate expression: 140709230544752 = 00007ff9`6bb40770

Establecer el evaluador de expresiones en MASM

Use el .expr (Elegir evaluador de expresiones) para ver cuál es el evaluador de expresiones predeterminado y cambiarlo a MASM.

0:000> .expr /s masm
Current expression evaluator: MASM - Microsoft Assembler expressions

Ahora que se ha cambiado el evaluador de expresiones predeterminado, (Evaluar expresión) se puede usar para mostrar expresiones MASM. En este ejemplo se agrega el valor hexadecimal de 8 al registro de rip.

0:000> ? @rip + 8
Evaluate expression: 140709230544760 = 00007ff9`6bb40778

La referencia de registro de @rip se describe con más detalle en La sintaxis de registro.

Números en expresiones MASM del depurador

Puede colocar números en expresiones MASM en base 16, 10, 8 o 2.

Use el comando n (Establecer base de número) para establecer el radix predeterminado en 16, 10 o 8. Todos los números sin fijar se interpretan en esta base. Puede invalidar el radix predeterminado especificando el prefijo 0x (hexadecimal), el prefijo 0n (decimal), el prefijo 0t (octal) o el prefijo 0y (binario).

También puede especificar números hexadecimales agregando un h después del número. Puede usar letras mayúsculas o minúsculas dentro de números. Por ejemplo, "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" y "4aB3H" tienen el mismo significado.

Si no agrega un número después del prefijo en una expresión, el número se lee como 0. Por lo tanto, puede escribir 0 como 0, el prefijo seguido de 0 y solo el prefijo. Por ejemplo, en hexadecimal, "0", "0x0" y "0x" tienen el mismo significado.

Puede escribir valores hexadecimales de 64 bits en el formato xxxxxxxx'xxxxxxxx . También puedes omitir el acento grave ('). Si incluye el acento grave, la extensión de signo automático está deshabilitada.

En este ejemplo se muestra cómo agregar un valor decimal, octal y binario para registrar 10.

? @r10 + 0x10 + 0t10 + 0y10
Evaluate expression: 26 = 00000000`0000001a

Símbolos en expresiones MASM del depurador

En las expresiones MASM, el valor numérico de cualquier símbolo es su dirección de memoria. Dependiendo de lo que hace referencia el símbolo, esta dirección es la dirección de una variable global, variable local, función, segmento, módulo o cualquier otra etiqueta reconocida.

Para especificar a qué módulo está asociado la dirección, incluya el nombre del módulo y un signo de exclamación (!) antes del nombre del símbolo. Si el símbolo se puede interpretar como un número hexadecimal, incluya el nombre del módulo y un signo de exclamación, o simplemente un signo de exclamación, antes del nombre del símbolo. Para obtener más información sobre el reconocimiento de símbolos, vea Sintaxis de símbolos y Coincidencia de símbolos.

Use dos puntos (::) o dos caracteres de subrayado (__) para indicar los miembros de una clase.

Use un énfasis grave (') o un apóstrofo (') en un nombre de símbolo solo si agrega un nombre de módulo y un signo de exclamación antes del símbolo.

Operadores numéricos en expresiones MASM

Puede modificar cualquier componente de una expresión mediante un operador unario. Puede combinar dos componentes mediante un operador binario. Los operadores unarios tienen prioridad sobre los operadores binarios. Cuando se usan varios operadores binarios, los operadores siguen las reglas de precedencia fijas que se describen en las tablas siguientes.

Siempre puede usar paréntesis para invalidar las reglas de precedencia.

Si parte de una expresión MASM se incluye entre paréntesis y dos signos (@@) aparecen antes de la expresión, la expresión se interpreta según las reglas de expresión de C++. No se puede agregar un espacio entre los dos signos y el paréntesis de apertura. También puede especificar el evaluador de expresiones mediante @@c++( ... ) o @@masm( ... )).

Al realizar cálculos aritméticos, el evaluador de expresiones MASM trata todos los números y símbolos como tipos de ULONG64.

Los operadores de direcciones unarias asumen DS como el segmento predeterminado para las direcciones. Las expresiones se evalúan en orden de precedencia del operador. Si los operadores adyacentes tienen la misma precedencia, la expresión se evalúa de izquierda a derecha.

Puede usar los siguientes operadores unarios.

Operator Significado

+

Suma unaria

-

Resta unaria

not

Devuelve 1 si el argumento es cero. Devuelve cero para cualquier argumento distinto de cero.

Hi (Hola)

16 bits altos

low

16 bits bajos

by

Byte de orden bajo de la dirección especificada.

$pby

Igual que con la excepción de que toma una dirección física. Solo se puede leer la memoria física que usa el comportamiento de almacenamiento en caché predeterminado.

wo

Palabra de orden bajo de la dirección especificada.

$pwo

Igual que wo , excepto que toma una dirección física. Solo se puede leer la memoria física que usa el comportamiento de almacenamiento en caché predeterminado.

dwo

Palabra doble de la dirección especificada.

$pdwo

Igual que dwo excepto que toma una dirección física. Solo se puede leer la memoria física que usa el comportamiento de almacenamiento en caché predeterminado.

qwo

Palabra cuádruple de la dirección especificada.

$pqwo

Igual que qwo , excepto que toma una dirección física. Solo se puede leer la memoria física que usa el comportamiento de almacenamiento en caché predeterminado.

Poi

Datos de tamaño de puntero de la dirección especificada. El tamaño del puntero es de 32 bits o 64 bits. En la depuración del kernel, este tamaño se basa en el procesador del equipo de destino . Por lo tanto, poi es el mejor operador para usar si desea datos de tamaño de puntero.

$ppoi

Igual que poi , excepto que toma una dirección física. Solo se puede leer la memoria física que usa el comportamiento de almacenamiento en caché predeterminado.

Ejemplos

En el ejemplo siguiente se muestra cómo usar poi para desreferenciar un puntero para ver el valor almacenado en esa ubicación de memoria.

En primer lugar, determine la dirección de memoria de interés. Por ejemplo, podemos examinar la estructura del subproceso y decidir que queremos ver el valor de 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 se encuentra 0x108 más allá del inicio del TEB.

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

Use poi para desreferenciar esa dirección.

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

El valor devuelto de 409 coincide con el valor de CurrentLocale en la estructura TEB.

O bien, use poi y paréntesis para desreferenciar la dirección calculada.

0:000> ? poi(@$teb + 0x108)
Evaluate expression: 1033 = 00000000`00000409

Use los operadores by o wo unario para devolver un byte o una palabra de la dirección de destino.

0:000> ? by(0000008e`ed57b108)
Evaluate expression: 9 = 00000000`00000009
0:000> ? wo(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409

Operadores binarios

Puede usar los siguientes operadores binarios. Los operadores de cada celda tienen prioridad sobre los de las celdas inferiores. Los operadores de la misma celda tienen la misma prioridad y se analizan de izquierda a derecha.

Operator Significado

*

/

mod (o %)

Multiplicación

División de enteros

Módulo (resto)

+

-

Suma

Resta

<<

>>

>>>

Desplazamiento a la izquierda

Desplazamiento lógico a la derecha

Desplazamiento aritmético a la derecha

= (o ==)

<

>

<=

>=

!=

Igual a

Menor que

Mayor que

Menor o igual que

Mayor o igual que

No es igual a

y (o &)

AND bit a bit

xor (o ^)

XOR bit a bit (OR exclusivo)

o (o |)

OR bit a bit

Los <operadores de comparación , , >= = = y != se evalúan en 1 si la expresión es true o cero si la expresión es false. Un único signo igual (=) es el mismo que un signo igual doble (==). No se pueden usar efectos secundarios ni asignaciones dentro de una expresión MASM.

Una operación no válida (como la división por cero) da como resultado un "error de operando" a la ventana Comando del depurador.

Podemos comprobar que el valor devuelto coincide con 0x409 mediante el operador de comparación == .

0:000> ? poi(@$teb + 0x108)==0x409
Evaluate expression: 1 = 00000000`00000001

Operadores no numéricos en expresiones MASM

También puede usar los siguientes operadores adicionales en expresiones MASM.

Operator Significado

$fnsucc(FnAddress, RetVal, Flag)

Interpreta el valor RetVal como un valor devuelto para la función que se encuentra en la dirección de FnAddress . Si este valor devuelto se califica como código correcto, $fnsucc devuelve TRUE. De lo contrario, $fnsucc devuelve FALSE.

Si el tipo de valor devuelto es BOOL, bool, HANDLE, HRESULT o NTSTATUS, $fnsucc entiende correctamente si el valor devuelto especificado se califica como código correcto. Si el tipo de valor devuelto es un puntero, todos los valores distintos de NULL califican como códigos de operación correcta. Para cualquier otro tipo, success se define mediante el valor de Flag. Si Flag es 0, se realiza correctamente un valor distinto de cero de RetVal . Si Flag es 1, se realiza correctamente un valor cero de RetVal .

$iment (dirección)

Devuelve la dirección del punto de entrada de la imagen en la lista de módulos cargados. Address especifica la dirección base de la imagen portable ejecutable (PE). La entrada se encuentra buscando el punto de entrada de imagen en el encabezado de imagen PE de la imagen que address especifica.

Puede usar esta función para ambos módulos que ya están en la lista de módulos y para establecer puntos de interrupción sin resolver mediante el comando bu .

$scmp("String1", "String2")

Se evalúa como -1, 0 o 1, como strcmp mediante la función strcmp C.

$sicmp("String1", "String2")

Se evalúa como -1, 0 o 1, como la función stricmp Microsoft Win32 .

$spat("String", "Pattern")

Se evalúa como TRUE o FALSE en función de si String coincide con Pattern. La coincidencia distingue mayúsculas y minúsculas. El patrón puede contener una variedad de caracteres comodín y especificadores. Para obtener más información sobre la sintaxis, vea Sintaxis de caracteres comodín de cadena.

$vvalid(Address,Length)

Determina si el intervalo de memoria que comienza en Address y se extiende para Bytes de longitud es válido. Si la memoria es válida, $vvalid se evalúa como 1. Si la memoria no es válida, $vvalid se evalúa como 0.

Ejemplos

A continuación se muestra cómo usar el intervalo de investigación de la memoria válida en torno a un módulo cargado.

En primer lugar, determine la dirección del área de interés, por ejemplo mediante el comando lm (Enumerar módulos cargados ).


0:000> lm
start             end                 module name
00007ff6`0f620000 00007ff6`0f658000   notepad    (deferred)
00007ff9`591d0000 00007ff9`5946a000   COMCTL32   (deferred)        
...

Use $vvalid para comprobar un intervalo de memoria.

0:000> ? $vvalid(0x00007ff60f620000, 0xFFFF)
Evaluate expression: 1 = 00000000`00000001

Use $vvalid para confirmar que este intervalo mayor es un intervalo de memoria no válido.

0:000> ? $vvalid(0x00007ff60f620000, 0xFFFFF)
Evaluate expression: 0 = 00000000`00000000

Esto también es un intervalo no válido.

0:000> ? $vvalid(0x0, 0xF)
Evaluate expression: 0 = 00000000`00000000

Use no para devolver cero cuando el intervalo de memoria sea válido.

0:000> ? not($vvalid(0x00007ff60f620000, 0xFFFF))
Evaluate expression: 0 = 00000000`00000000

Use $imnet para ver el punto de entrada de COMCTL32 que usamos anteriormente el comando lm para determinar la dirección. Comienza en 00007ff9'591d0000.

0:000> ? $iment(00007ff9`591d0000)
Evaluate expression: 140708919287424 = 00007ff9`59269e80

Desensamblar la dirección devuelta para examinar el código de punto 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 se muestra en la salida que confirma que este es el punto de entrada de este módulo.

Registros y Pseudo-Registers en expresiones MASM

Puede usar registros y pseudo-registros en expresiones MASM. Puede agregar un signo (@) antes de todos los registros y pseudo-registros. El signo en el signo hace que el depurador tenga acceso al valor más rápidamente. Este signo @ no es necesario para los registros basados en x86 más comunes. En el caso de otros registros y pseudo-registros, se recomienda agregar el at sign, pero en realidad no es necesario. Si omite el signo de los registros menos comunes, el depurador intenta analizar el texto como un número hexadecimal, como símbolo y, por último, como registro.

También puede usar un punto (.) para indicar el puntero de instrucción actual. No debe agregar un signo @ antes de este período y no puede usar un punto como primer parámetro del comando r. Este período tiene el mismo significado que el $ip pseudo-registro.

Para obtener más información sobre los registros y los pseudo-registros, vea Register Syntax y Pseudo-Register Syntax.

Use el comando r register para ver que el valor del @rip registro es 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

Este mismo valor se puede mostrar mediante . método abreviado de punto.

0:000> ? .
Evaluate expression: 140718141081456 = 00007ffb`7ed00770

Podemos confirmar que esos valores son equivalentes y devolver cero si son, mediante esta expresión MASM.

0:000>  ? NOT(($ip = .) AND ($ip = @rip) AND (@rip =. ))
Evaluate expression: 0 = 00000000`00000000

Números de línea de origen en expresiones MASM

Puede usar expresiones de número de línea y archivo de origen en expresiones MASM. Debe incluir estas expresiones mediante acentos graves ('). Para obtener más información sobre la sintaxis, vea Sintaxis de línea de origen.

Consulte también

Expresiones masm frente a expresiones de C++

Ejemplos de expresiones mixtas

Números y operadores de C++

Extensión de firma

? (Evaluar expresión)