Читаем Тонкости дизассемблирования полностью

Разумеется, не может быть смещения 'offset 12', (т.к. процессор не оперирует с полуторными словами), а комбинация '11' указывает на регистровую адресацию.

Может возникнуть вопрос, как складывать с 16-битным регистром 8 битное смещение? Конечно, непосредственному сложению мешает несовместимость типов, поэтому процессор сначала расширяет 8 бит до слова с учетом знака. Поэтому, диапазон возможных значений составляет от —127 до 127. (или от —0x7F до 0x7FF).

Все вышесказанное проиллюстрировано в приведенной ниже таблице 3. Обратим внимание на любопытный момент — адресация типа [BР] отсутствует. Ее ближайшим эквивалентом является [BР + 0]. Отсюда следует, что для экономии следует избегать непосредственного использования BР в качестве индексного регистра. BР может быть только базой. И mov ax,[bp] хотя и воспринимается любым ассемблером, но ассемблируется в

mov ax,[bр+0], что на байт длиннее.

Исследовав приведенную ниже таблицу 1, можно прийти к выводу, что адресация в процессоре 8086 была достаточно неудобной. Сильнее всего сказывалось то ограничение, что в качестве индекса могли выступать только три регистра (BX, SI, DI), когда гораздо чаще требовалось использовать для этого CX (например, в цикле) или AX (как возвращаемое функцией значение).

Поэтому, начиная с процессора 80386 (для 32-разрядного режима), концепция адресаций была пересмотрена. Поле R/M стало всегда выражать регистр независимо от способа его использования, чем стало управлять поле 'mod', задающие, кроме регистровой, три вида адресации:



Видно, что поле 'mod' по-прежнему выражает длину следующего поля — смещения, разве что с учетом 32-битного режима, где все слова расширяются до 32 бит.

Напомним, что с помощью префикса 0x67 можно и в 16-битном режиме использовать 32-битный режимы адресации, и наоборот. Однако, при этом мы сталкиваемся с интересным моментом — разрядность индексных регистров остается 32-битной и в 16-битном режиме!

В реальном режиме, где нет понятия границ сегментов, это действительно будет работать так, как выглядит, и мы сможем адресовать первые 4 мегабайта памяти (32 бита), что позволит преодолеть печально известное ограничение размера сегмента 8086 процессоров в 64К. Но такие приложения окажутся нежизнеспособными в защищенном или V86 режиме. Попытка вылезти за границу 64К сегмента вызовет исключение 0Dh, что приведет к автоматическому закрытию приложения, скажем, под управлением Windows. Аналогично поступают и отладчики (в том числе и многие эмуляторы, включая cuр386).

Сегодня актуальность этого приема, конечно, значительно снизилась, поскольку «голый DOS» практически уже не встречается, а режим его эмуляции Windows крайне неудобен для пользователей.



Изучив эту таблицу, можно прийти к заключению, что система адресации 32-битного режима крайне скудная, и ни на что серьезное ее не хватит. Однако, это не так. В 386+ появился новый байт SIB, который расшифровывается 'Scale-Index Base'.

Процессор будет ждать его вслед за R/M всякий раз, когда последний равен 100b. Эти поля отмечены в таблице как '[-]'. SIB хорошо документирован, и назначения его полей показаны на рисунке 6. Нет совершенно никакой необходимости зазубривать таблицу адресаций.




'Base' это базовый регистр, 'Index' — индексный, а два байта 'Scale' — это степень двойки для масштабирования. Поясним введенные термины. Ну, что такое индексный регистр, понятно всем. Например SI. Теперь же в качестве индексного можно использовать любой регистр. За исключением, правда, SР; впрочем, можно выбирать и его, но об этом позже.

Базовый регистр, это тот, который суммируется с индексным, например, [BР+SI]. Аналогично, базовым теперь может быть любой регистр. При этом есть возможность в качестве базового выбрать SР. Заметим, что если мы выберем этот регистр в качестве индексного, то вместо 'SР' получим — «никакой»: в этом случае адресацией будет управлять только базовый регистр.



Ну и, наконец, масштабирование — это уникальная возможность умножать индексный регистр на 1,2,4,8 (т.е. степень двойки, которая задается в поле Scale). Это очень удобно для доступа к различным структурам данных. При этом индексный регистр, являющийся одновременно и счетчиком цикла, будет указывать на следующий элемент структуры даже при единичном шаге цикла (что чаще всего и встречается). В таблице 4 показаны все возможные варианты значений байта 'SIB'.

Если при этом в качестве базового регистра будет выбран EBР, то полученный режим адресации будет зависеть от поля MOD предыдущего байта. Возможны следующие варианты:



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

Перейти на страницу:

Похожие книги

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Эта книга представляет собой перевод третьего издания американского бестселлера Effective C++ и является руководством по грамотному использованию языка C++. Она поможет сделать ваши программы более понятными, простыми в сопровождении и эффективными. Помимо материала, описывающего общую стратегию проектирования, книга включает в себя главы по программированию с применением шаблонов и по управлению ресурсами, а также множество советов, которые позволят усовершенствовать ваши программы и сделать работу более интересной и творческой. Книга также включает новый материал по принципам обработки исключений, паттернам проектирования и библиотечным средствам.Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Скотт Майерс , Скотт Мейерс

Программирование, программы, базы данных / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT