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


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

В этой статье описывается использование синтаксиса выражений C++ с средствами отладки Windows.

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

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

Средство синтаксического анализа выражений C++ поддерживает все формы синтаксиса выражений C++. Синтаксис включает все типы данных, включая указатели, числа с плавающей запятой и массивы, а также все унарные и двоичные операторы C++.

Окна "Контрольные " и "Локальные" в отладчике всегда используют средство оценки выражений C++.

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

0:000> ?? @eip
unsigned int 0x771e1a02

Для определения размера структур можно использовать функцию C++ sizeof .

0:000> ?? (sizeof(_TEB))
unsigned int 0x1000

Задайте для вычислителя выражений значение C++

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

0:000> .expr
Current expression evaluator: MASM - Microsoft Assembler expressions
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions

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

0:000> ? @eip
Evaluate expression: 1998461442 = 771e1a02

Дополнительные сведения о ссылке @eip на регистрацию см. в разделе "Регистрация синтаксиса".

В этом примере шестнадцатеричное значение 0xD добавляется в регистр eip.

0:000> ? @eip + 0xD
Evaluate expression: 1998461455 = 771e1a0f

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

В выражениях C++ можно использовать регистры и псевдорегистры. Перед регистрацией или псевдорегистром необходимо добавить знак @.

Средство оценки выражений автоматически выполняет правильный приведение. Фактические регистры и псевдорегистры целочисленного значения приведение ULONG64к . Все адреса приведениеPUCHARETHREAD*$thread, приведение к, приведение к, $proc приведение к, приведение EPROCESS*к, $teb и $peb приведение TEB*к.PEB*

В этом примере отображается TEB.

0:000>  ?? @$teb
struct _TEB * 0x004ec000
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x004ec02c Void
   +0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
   +0x034 LastErrorValue   : 0xbb
   +0x038 CountOfOwnedCriticalSections : 0

Невозможно изменить регистр или псевдорегистрированную оператором назначения или побочных эффектов. Для изменения этих значений необходимо использовать команду r registers .

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

0:000> r $t0 = 5

0:000> ?? @$t0
unsigned int64 5

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

Числа в выражениях C++

Числа в выражениях C++ интерпретируются как десятичные числа, если они не указаны другим способом. Чтобы указать шестнадцатеричное целое число, добавьте 0x перед числом. Чтобы указать восьмеричное целое число, добавьте 0 (ноль) перед числом.

Радикс отладчика по умолчанию не влияет на способ ввода выражений C++. Вы не можете напрямую ввести двоичное число, за исключением вложенного выражения MASM в выражение C++.

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

Можно использовать Lсуффиксы и UI64 суффиксы со целыми значениями. Фактический размер создаваемого числа зависит от суффикса и введенного числа. Дополнительные сведения об этой интерпретации см. в справочнике по языку C++.

Выходные данные вычислителя выражений C++ сохраняют тип данных, указанный правилами выражений C++. Однако при использовании этого выражения в качестве аргумента для команды всегда выполняется приведение. Например, вам не нужно приведение целых значений к указателям, когда они используются в качестве адресов в аргументах команд. Если значение выражения не может быть допустимо приведение к целочислению или указателю, возникает синтаксическая ошибка.

Префикс (десятичный) можно использовать 0n для некоторых выходных данных, но его нельзя использовать для ввода выражений C++.

Символы и строки в выражениях C++

Вы можете ввести символ, окружив его одними кавычками ('). Разрешены стандартные escape-символы C++.

Строковые литералы можно вводить, окружая их двойными кавычками ("). Вы можете использовать \" в качестве escape-последовательности в такой строке. Однако строки не имеют значения для вычислителя выражений.

Символы в выражениях C++

В выражении C++ каждый символ интерпретируется в соответствии с типом. В зависимости от того, к чему относится символ, он может интерпретироваться как целое число, структура данных, указатель функции или любой другой тип данных. Синтаксическая ошибка возникает, если используется символ, который не соответствует типу данных C++ ( например, немодифицированному имени модуля) в выражении C++ .

Вы можете использовать серьезный акцент (') или апостроф (') в имени символа, только если добавить имя модуля и восклицательный знак перед именем символа. При добавлении < разделителей > после имени шаблона можно добавлять пробелы между этими разделителями.

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

Структуры в выражениях C++

Средство оценки выражений C++ приводит псевдорегистры к соответствующим типам. Например, $teb выполняется приведение в виде TEB*.

0:000> ??  @$teb
struct _TEB * 0x004ec000
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x004ec02c Void
   +0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
   +0x034 LastErrorValue   : 0xbb
   +0x038 CountOfOwnedCriticalSections : 0

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

0:000> ??  @$teb->ClientId.UniqueProcess
void * 0x0000059c

Операторы в выражениях C++

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

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

Типы данных указываются как обычные на языке C++. Символы, указывающие массивы ([ ]), элементы указателя (->), элементы UDT (.) и члены классов (::) распознаются. Поддерживаются все арифметические операторы, включая операторы назначения и побочных эффектов. Однако вы не можете использовать newоператоры и deletethrow операторы, и вы не можете на самом деле вызвать функцию.

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

Как и в C++, при использовании операторов с недопустимыми типами данных возникает синтаксическая ошибка. Средство синтаксического анализа выражений C++ отладчика использует немного более расслабленные правила, чем большинство компиляторов C++, но все основные правила применяются. Например, нельзя изменить целочисленное значение.

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

Как и в C++, оценка выражений заканчивается, когда его значение известно. Это окончание позволяет эффективно использовать такие выражения, как ?? myPtr && *myPtr.

Приведение ссылок и типов

Оператор Значение
Комментарий выражения // Игнорировать весь последующий текст
Класс :: Член Член класса
Класс ::~Member Член класса (деструктор)
:: Имя Глобальный
Структура. Поле Поле в структуре
Указатель ->Поле Поле в указанной структуре
Имя [целое число] Индекс массива
LValue ++ Добавочный (после оценки)
LValue -- Декремент (после оценки)
<dynamic_cast type>(Value) Typecast (всегда выполняется)
<тип> static_cast(Значение) Typecast (всегда выполняется)
<reinterpret_cast type>(Value) Typecast (всегда выполняется)
<тип> const_cast(значение) Typecast (всегда выполняется)

Операции со значением

Оператор Значение
(тип) Значение Typecast (всегда выполняется)
значение sizeof Размер выражения
sizeof( тип ) Размер типа данных
++ LValue Добавочный (перед оценкой)
-- LValue Декремент (перед оценкой)
~ Value Битовое дополнение
! Value Not (Boolean)
Value Унарный минус
+ Value Унарный плюс
& LValue Адрес типа данных
Value Dereference
Структура. Указатель Указатель на элемент структуры
Указатель -> * Указатель Указатель на элемент ссылочной структуры

Арифметический

Оператор Значение
Значение Умножение
Значение / Подразделение
Значение % Модуль
Значение + Дополнение
Значение - Вычитание
Значение<< Побитовая смена влево
Значение>> Побитовая смена вправо
Значение< Меньше (сравнение)
Значение= значение< Меньше или равно (сравнение)
Значение> Больше (сравнение)
Значение= значение> Больше или равно (сравнение)
Значение == Равно (сравнение)
Значение != значение Не равно (сравнение)
Значение и значение Побитовое И
Значение ^ Побитовое XOR (эксклюзивное ИЛИ)
Значение | Побитовое ИЛИ
Значение &&&Значение Логическое И
Значение || Логическое ИЛИ

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

0:000> r $t0 = 0
0:000> r $t1 = 1
0:000> r $t2 = 2
0:000> ?? @$t1 + @$t2
unsigned int64 3
0:000> ?? @$t2/@$t1
unsigned int64 2
0:000> ?? @$t2|@$t1
unsigned int64 3

Передача прав и обязанностей

Оператор Значение
Значение LValue = Назначить
Значение LValue *= Умножение и назначение
Значение LValue /= Деление и присваивание
Значение LValue %= Остаток от деления и присваивание
Значение LValue += Сложение и присваивание
Значение LValue -= Вычитание и присваивание
LValue<<= Значение Смена влево и назначение
LValue>>= Значение Смена вправо и назначение
LValue &= Value И и назначение
Значение LValue |= ИЛИ и назначение
Значение LValue ^= XOR и назначение

Оценка

Оператор Значение
Значение ? Значение: значение Условная оценка:
Значение, значение Оценка всех значений, а затем отмена всех, кроме самого правого значения

Макросы в выражениях C++

Макросы можно использовать в выражениях C++. Перед макросами необходимо добавить знак номера (#).

Можно использовать следующие макросы. Эти макросы имеют те же определения, что и макросы Microsoft Windows с тем же именем. Макросы Windows определены в Winnt.h.

Макрос Возвращаемое значение
#CONTAINING_RECORD(адрес, тип, поле) Возвращает базовый адрес экземпляра структуры, учитывая тип структуры и адрес поля в структуре.
#FIELD_OFFSET(Тип, поле) Возвращает смещение байтов именованного поля в известном типе структуры.
#RTL_CONTAINS_FIELD(Структура, размер, поле) Указывает, включает ли заданный размер байтов требуемое поле.
#RTL_FIELD_SIZE(Тип, поле) Возвращает размер поля в структуре известного типа, не требуя типа поля.
#RTL_NUMBER_OF(Массив) Возвращает количество элементов в массиве статического размера.
#RTL_SIZEOF_THROUGH_FIELD(Тип, поле) Возвращает размер структуры известного типа, вплоть до указанного поля.

В этом примере показано использование #FIELD_OFFSET макроса для вычисления смещения байтов в поле в структуре.

0:000> ?? #FIELD_OFFSET(_PEB, BeingDebugged)
long 0n2

См. также

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

?? оценка выражения C++

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

.expr выберите средство оценки выражений

Расширение для подписи

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