Поделиться через


Номера и операторы MASM

В этом разделе описывается использование синтаксиса выражения макросов Майкрософт (MASM) с инструментами отладки Windows.

Отладчик принимает два различных типа числовых выражений: выражения C++ и выражения MASM. Каждое из этих выражений соответствует собственным правилам синтаксиса входных и выходных данных.

Дополнительные сведения об использовании каждого типа синтаксиса см. в разделе "Оценка выражений " и ? (Вычислять выражение).

В этом примере используется ? Команда отображает значение регистра указателя инструкции с помощью вычислителя выражений MASM.

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

Установка средства оценки выражений в MASM

Используйте expr (выбор вычислителя выражений), чтобы узнать, что такое средство оценки выражений по умолчанию, и измените его на MASM.

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

Теперь, когда средство оценки выражений по умолчанию было изменено, значение ? (Вычислять выражение) для отображения выражений MASM можно использовать команду. В этом примере в регистр rip добавляется шестнадцатеричное значение 8.

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

Ссылка на @rip регистр описана более подробно в описании синтаксиса регистрации.

Числа в выражениях MASM отладчика

Числа можно поместить в выражения MASM в базовые 16, 10, 8 или 2.

Используйте команду n (Set Number Base), чтобы задать для радикса по умолчанию значение 16, 10 или 8. Затем все нерекомендаемые числа интерпретируются в этой базе. Можно переопределить радикс по умолчанию, указав префикс 0x (шестнадцатеричный), префикс 0n (десятичный ), префикс 0t (восьмерично) или 0y префикс (двоичный).

Вы также можете указать шестнадцатеричные числа, добавив h после числа. В числах можно использовать строчные или строчные буквы. Например, "0x4AB3", "0X4aB3", "4AB3h", "4ab3h" и "4aB3H" имеют то же значение.

Если вы не добавляете число после префикса в выражении, число считывается как 0. Таким образом, можно написать значение 0 как 0, префикс, за которым следует 0, и только префикс. Например, в шестнадцатеричном, "0", "0x0" и "0x" имеют то же значение.

Шестнадцатеричные 64-разрядные значения можно ввести в формате xxxx'xxxx. Вы также можете опустить серьезный акцент ('). Если включить серьезный акцент, автоматическое расширение знака отключено.

В этом примере показано, как добавить десятичное, восьмеричное и двоичное значение для регистрации 10.

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

Символы в выражениях MASM отладчика

В выражениях MASM числовое значение любого символа является его адресом памяти. В зависимости от того, какой символ относится, этот адрес является адресом глобальной переменной, локальной переменной, функции, сегмента, модуля или любой другой распознанной метки.

Чтобы указать, с каким модулем связан адрес, добавьте имя модуля и восклицательный знак (!) перед именем символа. Если символ может быть интерпретирован как шестнадцатеричное число, добавьте имя модуля и восклицательный знак или просто восклицательный знак перед именем символа. Дополнительные сведения о распознавании символов см. в разделе "Синтаксис символов" и "Сопоставление символов".

Используйте две двоеточия (::) или два символа подчеркивания (__), чтобы указать члены класса.

Используйте серьезный акцент (') или апостроф (') в имени символа, только если добавить имя модуля и восклицательный знак перед символом.

Числовые операторы в выражениях MASM

Вы можете изменить любой компонент выражения с помощью унарного оператора. Можно объединить любые два компонента с помощью двоичного оператора. Унарные операторы имеют приоритет над двоичными операторами. При использовании нескольких двоичных операторов операторы следуют фиксированным правилам приоритета, описанным в следующих таблицах.

Для переопределения правил приоритета всегда можно использовать круглые скобки.

Если часть выражения MASM заключена в скобки и два знака (@@) отображаются перед выражением, выражение интерпретируется в соответствии с правилами выражений C++. Нельзя добавить пробел между двумя знаками и открывающей скобкой. Вы также можете указать средство оценки выражений с помощью @@c++( ... ) или @@masm( ... ).

При выполнении арифметических вычислений средство оценки выражений MASM обрабатывает все числа и символы как ULONG64 типы.

Унарные операторы адресов предполагают ds в качестве сегмента по умолчанию для адресов. Выражения оцениваются в порядке приоритета оператора. Если смежные операторы имеют равный приоритет, выражение вычисляется слева направо.

Вы можете использовать следующие унарные операторы.

Оператор Значение

+

Унарный плюс

-

Унарный минус

not

Возвращает значение 1, если аргумент равен нулю. Возвращает ноль для любого ненулевого аргумента.

Привет

Высокий 16 бит

low

Низкий 16 бит

by

Байт низкого порядка из указанного адреса.

$pby

То же самое, что и за исключением того, что он принимает физический адрес. Можно считывать только физическую память, использующую поведение кэширования по умолчанию.

wo

Слово с низким порядком из указанного адреса.

$pwo

То же самое, что wo , за исключением того, что он принимает физический адрес. Можно считывать только физическую память, использующую поведение кэширования по умолчанию.

dwo

Двойное слово из указанного адреса.

$pdwo

То же самое, что dwo , за исключением того, что он принимает физический адрес. Можно считывать только физическую память, использующую поведение кэширования по умолчанию.

qwo

Четыре слова из указанного адреса.

$pqwo

То же, что и qwo , за исключением того, что он принимает физический адрес. Можно считывать только физическую память, использующую поведение кэширования по умолчанию.

пои

Данные размера указателя из указанного адреса. Размер указателя составляет 32 бита или 64 бита. В отладке ядра этот размер основан на процессоре целевого компьютера. Таким образом, poi является лучшим оператором для использования, если требуется размер данных указателя.

$ppoi

То же, что и poi , за исключением того, что он принимает физический адрес. Можно считывать только физическую память, использующую поведение кэширования по умолчанию.

Примеры

В следующем примере показано, как использовать poi для расшифровки указателя, чтобы увидеть значение, хранящееся в этом расположении памяти.

Сначала определите адрес памяти, интересующий вас. Например, можно просмотреть структуру потока и решить, что нужно увидеть значение 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 находится 0x108 за пределами начала TEB.

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

Используйте poi для расшифровки этого адреса.

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

Возвращаемое значение 409 соответствует значению CurrentLocale в структуре TEB.

Или используйте poi и круглые скобки для расшифровки вычисляемого адреса.

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

Используйте унарные операторы, чтобы вернуть байт или слово из целевого адреса.

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

Бинарные операторы

Вы можете использовать следующие двоичные операторы. Операторы в каждой ячейке имеют приоритет над операторами в нижних ячейках. Операторы в одной ячейке имеют одинаковый приоритет и анализируются слева направо.

Оператор Значение

*

/

mod (или %)

Умножение

Деление целых чисел

Модуль (оставшаяся часть)

+

-

Дополнение

Вычитание

<<

>>

>>>

Сдвиг влево

Логическая смена вправо

Арифметический сдвиг вправо

= (или ==)

<

>

<=

>=

!=

Равно

Меньше

Больше

Меньше или равно

Больше или равно

Не равно

и (или &)

Побитовое И

xor (или ^)

Побитовое XOR (эксклюзивное ИЛИ)

или (или |)

Побитовое ИЛИ

Операторы <сравнения , >=, ==, и != оцениваются в 1, если выражение имеет значение true или ноль, если выражение равно false. Единый знак равенства (=) совпадает с двойным знаком равенства (==). Побочные эффекты или назначения нельзя использовать в выражении MASM.

Недопустимая операция (например, деление по нулю) приводит к возврату ошибки Operand в окно команды отладчика.

Мы можем проверить, соответствует ли возвращаемое значение 0x409 с помощью оператора сравнения == .

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

Нечисловые операторы в выражениях MASM

Кроме того, в выражениях MASM можно использовать следующие дополнительные операторы.

Оператор Значение

$fnsucc(FnAddress, RetVal, Flag)

Интерпретирует значение RetVal как возвращаемое значение для функции, расположенной по адресу FnAddress . Если это возвращаемое значение является кодом успешного выполнения, $fnsucc возвращает значение TRUE. В противном случае $fnsucc возвращает значение FALSE.

Если возвращаемый тип — BOOL, bool, HANDLE, HRESULT или NTSTATUS, $fnsucc правильно понимает, соответствует ли указанное возвращаемое значение как код успешного выполнения. Если возвращаемый тип является указателем, все значения, отличные от NULL , соответствуют кодам успешности. Для любого другого типа успех определяется значением Flag. Если флаг равен 0, значение RetVal ненулевое значение успешно. Если флаг равен 1, значение RetVal равно нулю.

$iment (адрес)

Возвращает адрес точки входа изображения в загруженном списке модулей. Адрес указывает базовый адрес переносимого исполняемого файла (PE). Запись найдена путем поиска точки входа изображения в заголовке изображения PE, указанного адресом .

Эту функцию можно использовать для обоих модулей, которые уже находятся в списке модулей, и для установки неразрешенных точек останова с помощью команды bu.

$scmp("String1", "String2")

Вычисляется значение -1, 0 или 1, например strcmp с помощью функции strcmp C.

$sicmp("String1", "String2")

Оценивается как -1, 0 или 1, например функция Microsoft Win32.

$spat("String", "Pattern")

Вычисляется значение TRUE или FALSE в зависимости от того, соответствует ли строка шаблону. Сопоставление не учитывает регистр. Шаблон может содержать различные подстановочные знаки и описатели. Дополнительные сведения о синтаксисе см. в разделе "Синтаксис подстановочных знаков строки".

$vvalid(адрес, длина)

Определяет, является ли диапазон памяти, начинающийся с адреса и расширяющийся для байтов длины . Если память допустима, $vvalid оценивается как 1. Если память недопустимая, $vvalid оценивается в 0.

Примеры

Ниже показано, как использовать диапазон допустимой памяти вокруг загруженного модуля.

Сначала определите адрес интересующей области, например с помощью команды lm (команда List Loaded Modules ).


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

Используйте $vvalid для проверки диапазона памяти.

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

Используйте $vvalid для подтверждения того, что этот большой диапазон является недопустимым диапазоном памяти.

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

Это также недопустимый диапазон.

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

Используйте не для возврата нуля, если диапазон памяти действителен.

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

Используйте $imnet для просмотра точки входа COMCTL32, которую мы ранее использовали команду lm для определения адреса. Она начинается с 0007ff9'591d00000.

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

Дизассемблируйте возвращенный адрес для проверки кода точки входа.

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 отображается в выходных данных, подтверждающих, что это точка входа для этого модуля.

Регистры и псевдорегистрации в выражениях MASM

В выражениях MASM можно использовать регистры и псевдорегистрации. Вы можете добавить по знаку (@) перед всеми регистрами и псевдорегистрами. При входе отладчик быстрее обращается к значению. Этот знак @не требуется для наиболее распространенных регистров на основе x86. Для других регистров и псевдорегистрирующих регистров рекомендуется добавить знак при входе, но на самом деле это не обязательно. Если вы опустите знак для менее распространенных регистров, отладчик пытается проанализировать текст как шестнадцатеричное число, а затем в качестве символа и, наконец, как регистр.

Можно также использовать точку (.) для указания текущего указателя инструкции. Не следует добавлять знак @до этого периода, и вы не можете использовать период в качестве первого параметра команды r. Этот период имеет то же значение, что и $ip псевдорегистрировать.

Дополнительные сведения о регистрах и псевдорегистрирующих регистрах см. в разделе "Регистр синтаксис " и "Псевдорегистрирующий синтаксис".

Используйте команду r register, чтобы узнать, что значение регистра @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

Это же значение можно отобразить с помощью . ярлык периода.

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

Мы можем подтвердить, что эти значения эквивалентны и возвращают ноль, если они есть, используя это выражение MASM.

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

Исходные номера строк в выражениях MASM

Исходные и числовые выражения можно использовать в выражениях MASM. Эти выражения необходимо заключить с помощью серьезных акцентов ('). Дополнительные сведения о синтаксисе см. в разделе "Синтаксис исходной строки".

См. также

Выражения MASM и выражения C++

Примеры смешанных выражений

Номера и операторы C++

Расширение знака

? (Вычислять выражение)