Регистры
Именно через регистры передается приложению каждый бит данных, который оно обрабатывает, и знание роли каждого регистра поможет вам распознать неудачный участок кода. CPU x86 имеют восемь регистров общего назначения (ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ESP и ЕВР), шесть сегментных регистров (CS, DS, ES, SS, FS и GS), указатель инструкций (команд) EIP и регистр флагов (EFLAGS). Есть и другие регистры, такие как регистры отладки и управляющие машинные регистры, но это регистры специального назначения, и вы не встретитесь с ними при нормальной отладке в режиме пользователя. Все регистры общего назначения, перечисленные в табл. 6.1, являются 32-разрядными. Заметьте, что некоторые из них допускают мнемонические обозначения для доступа к различным частям полного 32-разрядного регистра. Единственный сегментный регистр, представляющий интерес для данной главы, — это регистр FS, который содержит блок информации потока (TIB), содержащий описание текущего выполняемого потока. Используются и другие сегментные регистры, но операционная система конфигурирует их таким образом, что они оказываются прозрачными по отношению к нормальной операции. Указатель инструкции содержит адрес текущей выполняющийся инструкции.
Таблица 6.1. Регистры общего назначения
32-разрядный регистр |
|
Доступ к младшему байту (биты 0-7) |
Доступ к старшему байту (биты 8-1 5) |
Специфика использования |
ЕАХ |
АХ |
AL |
АН |
Здесь хранятся возвращаемые значения целых функций |
ЕВХ |
ВХ |
BL |
ВН |
Здесь хранится базовый адрес объекта в памяти |
ЕСХ |
СХ |
CL |
СН |
Эти регистры используются счетчиками инструкций циклов |
EDX |
DX |
DL |
DH |
Здесь хранятся 32 старших бита 64-битных значений |
ESI |
SI |
|
|
Здесь хранится исходный адрес инструкций перемещения или сравнения в памяти |
EDI |
DI |
|
|
Здесь хранится целевой адрес инструкций перемещения или сравнения в памяти |
ESP |
SP |
|
|
Указатель стека. Этот регистр изменяется неявно при вызове функции, возврате из функции, отведении места в стеке для локальных переменных и очистке стека |
EBP |
ВР |
|
|
Указатель база/кадр. Этот регистр содержит адрес стекового кадра для процедуры |
В табл. 6.2 описаны флажки, показанные в окне Registers. К сожалению, документация Visual C++ не раскрывает значения этих флажков, а мнемоника, применяемая для них в системе Visual C++, не соответствует мнемонике Intel, так что при ссылках на документацию Intel нужна соответствующая трансляция.
Рис. 6.1. Окно Registers из Visual C++
С окном Registers связана одна незначительная особенность: при обновлении флажков цвет значения регистра EFL не изменяется (в отличие от обычных регистров, значения которых при обновлениях выделяются другим цветом). Но необходимость просматривать индивидуальные значения флажков возникает довольно редко. Для облегчения разметки изменяющихся флажков можно сделать следующее: нажать кнопку New Text File (в панели Standard) и открыть новый временный файл. Затем скопировать (в буфер обмена) существующие флажки из окна Registers и вставить их в окно временного текста, чтобы сравнить их значения до и после изменения.
Таблица 6.2. Значения флажков окна Registers
Флажок окна Registers
|
Значение
|
Мнемоника в руководстве Intel
|
Примечания
|
OV |
Overflow Flag (флажок переполнения) |
OF |
Устанавливается в 1, если операция закончилось целым переполнением или потерей значимости |
UP |
Direction Flag (флажок направления) |
DF |
Устанавливается в 1, если строчная инструкция выполняет обработку в направлении от самого высокого до самого низкого адреса (автодекремент). 0 означает, что строчная инструкция выполняет обработку в противоположном направлении: от самого низкого до самого высокого адреса (автоприращение) |
El |
Interrupt Enable Flag (флажок разрешения прерываний) |
IF |
Устанавливается в 1, если прерывания разрешены. Этот флажок будет всегда включен (1) в пользовательском режиме отладчика |
PL |
Sign Flag (флажок знака) |
SF |
Отображает самый старший (знаковый) бит результата инструкции. Устанавливается в 0 для положительных значений или в 1 — для отрицательных |
ZR |
Zero Flag (нулевой флажок) |
ZF |
Устанавливается в 1, если результатом инструкции является 0 (нуль). Этот флажок важен для инструкций сравнения |
AC |
Auxiliary Carry Flag (вспомогательный флажок переноса) |
AF |
Устанавливается в 1, если двоично-десятичная (BCD) операция генерирует служебный перенос или заем старшего разряда |
PE |
Parity Flag ' (флажок четности) |
PF |
Устанавливается в 1, если наименее значимый (младший) байт результата содержит четное число бит, установленных в 1 |
CY |
Carry Flag (флажок переноса) |
CF |
Устанавливается в 1, если арифметическая операция генерирует перенос или заем из наиболее значащего (знакового) бита результата. Устанавливается в 1 также при переполнении в операциях целочисленной арифметики без знака |