WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!

Pages:     || 2 | 3 | 4 | 5 |   ...   | 9 |
-- [ Страница 1 ] --

Assembler^ Зубков С. В.

^^_ \JM\\J О V_. U.

^ш тят »* у дня DOS, Windows ilCTCUMIP УДК 004.438Assembler ББК 32.973.26-018.1 3-91 Зубков С. В.

3-91 Assembler для DOS, Windows и UNIX / Зубков Сергей Владимирович. - 3-е изд., стер. - М. : ДМК Пресс ;

СПб. : Питер, 2004. - 608 с. : ил. (Серия «Для программистов»).

ISBN 5-94074-259-9 В книге освещаются все аспекты современного программирования на ассембле ре для DOS, Windows 95/NT и UNIX (Solaris, Linux и FreeBSD), включая созда ние резидентных программ и драйверов, прямое программирование периферий ных устройств, управление защищенным режимом и многое другое. Детально рассматривается архитектура процессоров Intel вплоть до Pentium III. Все главы иллюстрируются подробными примерами работоспособных программ.

Издание ориентировано как на профессионалов, так и на начинающих без опыта программирования.

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

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

© Зубков С. В., ISBN 5-94074-259-9 © ДМК Пресс, Зубков Сергей Владимирович Assembler для DOS, Windows и UNIX Главный редактор Захаров И. М.

editor-in-chief@dmkpress.ru Научный редактор Шалаев Н. В.

Литературный редактор Космачева Н. А.

Верстка А/щ-Заде В. X.

Дизайн обложки Антонов А. И.

Подписано в печать 12.11.2003. Формат 70хЮО'/16.

Гарнитура «Петербург». Печать офсетная.

Усл. печ. л. 49,4. Тираж 3000 экз. Зак. № Издательство «ДМК Пресс», 105023, Москва, пл. Журавлева, 2/ Web-сайт издательства: www.dmk.ru Internet-магазин: www.abook.ru, www.dmk.ru Ордена Трудового Красного Знамени ГУП Чеховский полиграфический комбинат Министерства Российской Федерации по делам печати, телерадиовещания и средств массовых коммуникаций 142300, г. Чехов Московской области Тел. (272) 71-336, факс (272) 62- Содержание Введение и Глава 1, Предварительные сведения 1.1. Что нужно для работы с ассемблером 1.2. Представление данных в компьютерах 1.2.1. Двоичная система счисления 1.2.2. Биты, байты и слова 1.2.3. Шестнадцатеричная система счисления 1.2.4. Числа со знаком 1.2.5. Логические операции 1.2.6. Коды символов 1.2.7. Организация памяти Глава 2. Процессоры Intel в реальном режиме 2.1. Регистры процессора 2.1.1. Регистры общего назначения 2.1.2. Сегментные регистры 2.1.3. Стек 2.1.4. Регистр флагов 2.2. Способы адресации 2.2.1. Регистровая адресация 2.2.2. Непосредственная адресация 2.2.3. Прямая адресация 2.2.4. Косвенная адресация 2.2.5. Адресация по базе со сдвигом 2.2.6. Косвенная адресация с масштабированием 2.2.7. Адресация по базе с индексированием 2.2.8. Адресация по базе с индексированием и масштабированием 2.3. Основные непривилегированные команды 2.3.1. Пересылка данных 2.3.2. Двоичная арифметика 2.3.3. Десятичная арифметика •Я ВШ Assembler для DOS, Windows и UNIX 2.3.4. Логические операции 2.3.5. Сдвиговые операции 2.3.6. Операции над битами и байтами 2.3.7. Команды передачи управления 2.3.8. Строковые операции 2.3.9. Управление флагами 2.3.10. Загрузка сегментных регистров 2.3.11. Другие команды 2.4. Числа с плавающей запятой 2.4.1. Типы данных FPU 2.4.2. Регистры FPU 2.4.3. Исключения FPU 2.4.4. Команды пересылки данных FPU 2.4.5. Базовая арифметика FPU 2.4.6. Команды сравнения FPU 2.4.7. Трансцендентные операции FPU 2.4.8. Константы FPU 2.4.9. Команды управления FPU 2.5. Расширение IAMMX 2.5.1. Регистры ММХ 2.5.2. Типы данных ММХ 2.5.3. Команды пересылки данных ММХ 2.5.4. Команды преобразования типов ММХ 2.5.5. Арифметические операции ММХ 2.5.6. Команды сравнения ММХ 2.5.7. Логические операции ММХ 2.5.8. Сдвиговые операции ММХ 2.5.9. Команды управления состоянием ММХ.'. 2.5.10. Расширение AMD 3D 2.6. Расширение SSE 2.6.1. Регистры SSE 2.6.2. Типы данных SSE 2.6.3. Команды SSE 2.6.4. Определение поддержки SSE 2.6.5. Исключения Глава 3. Директивы и операторы ассемблера юе 3.1. Структура программы 3.2. Директивы распределения памяти 3.2.1. Псевдокоманды определения переменных 3.2.2. Структуры Содержание.^ 3.3. Организация программы 3.3.1. Сегменты 3.3.2. Модели памяти и упрощенные директивы определения сегментов 3.3.3. Порядок загрузки сегментов 3.3.4. Процедуры 3.3.5. Конец программы 3.3.6. Директивы задания набора допустимых команд 3.3.7. Директивы управления программным счетчиком 3.3.8. Глобальные объявления 3.3.9. Условное ассемблирование 3.4. Выражения 3.5. Макроопределения 3.5.1. Блоки повторений 3.5.2. Макрооператоры 3.5.3. Другие директивы, используемые в макроопределениях 3.6. Другие директивы 3.6.1. Управление файлами 3.6.2. Управление листингом : 3.6.3. Комментарии Глава 4. Основы программирования для MS DOS 4.1. Программа типа COM 4.2. Программа типа EXE 4.3. Вывод на экран в текстовом режиме 4.3.1. Средства DOS 4.3.2. Средства BIOS 4.3.3. Прямая работас видеопамятью 4.4. Ввод с клавиатуры 4.4.1. Средства DOS 4.4.2. Средства BIOS 4.5. Графические видеорежимы 4.5.1. Работа с VGA-режимами 4.5.2. Работа с SVGA-режимами 4.6. Работас мышью 4.7. Другие устройства 4.7.1. Системный таймер 4.7.2. Последовательный порт 4.7.3. Параллельный порт Assembler для DOS, Windows и UNIX 4.8. Работа с файлами 4.8.1. Создание и открытие файлов 4.8.2. Чтение и запись в файл 4.8.3. Закрытие и удаление файла 4.8.4. Поиск файлов 4.8.5. Управление файловой системой 4.9. Управление памятью 4.9.1. Обычная память : 4.9.2. Область памяти UMB 4.9.3. Область памяти НМД 4.9.4. Интерфейс EMS 4.9.5. Интерфейс XMS 4.10. Загрузка и выполнение программ 4.11. Командные параметры и переменные среды Глава 5. Более сложные приемы программирования.. 5.1. Управляющие структуры 5.1.1. Структуры IF...THEN...ELSE 5.1.2. Структуры CASE 5.1.3. Конечные автоматы 5.1.4. Циклы 5.2. Процедуры и функции 5.2.1. Передача параметров 5.2.2. Локальные переменные 5.3. Вложенные процедуры 5.3.1. Вложенные процедуры со статическими ссылками 5.3.2. Вложенные процедуры с дисплеями 5.4. Целочисленная арифметика повышенной точности 5.4.1. Сложение и вычитание 5.4.2. Сравнение 5.4.3. Умножение 5.4.4. Деление 5.5. Вычисления с фиксированной запятой 5.5.1. Сложение и вычитание 5.5.2. Умножение 5.5.3. Деление 5.5.4. Трансцендентные функции 5.6. Вычисления с плавающей запятой Содержание 5.7. Популярные алгоритмы 5.7.1. Генераторы случайных чисел 5.7.2. Сортировки 5.8. Перехват прерываний 5.8.1. Обработчики прерываний 5.8.2. Прерывания от внешних устройств 5.8.3. Повторная входимость 5.9. Резидентные программы 5.9.1. Пассивная резидентная программа 5.9.2. Мультиплексорное прерывание 5.9.3. Выгрузка резидентной программы из памяти 5.9.4. Полурезидентные программы 5.9.5. Взаимодействие между процессами 5.10. Программирование на уровне портов ввода-вывода.... 5.10.1. Клавиатура 5.10.2. Последовательный порт 5.10.3. Параллельный порт 5.10.4. Видеоадаптеры VGA 5.10.5. Таймер 5.10.6. Динамик 5.10.7. Часы реального времени и CMOS-память 5.10.8. Звуковые платы 5.10.9. Контроллер DMA 5.10.10. Контроллер прерываний 5.10.11. Джойстик 5.11. Драйверы устройств в DOS 5.11.1. Символьные устройства 5.11.2. Блочные устройства Глава 6. Программирование в защищенном режиме... 6.1. Адресация в защищенном режиме 6.2. Интерфейс VCPI 6.3. Интерфейс DPMI 6.3.1. Переключение в защищенный режим 6.3.2. Функции DPMI управления дескрипторами 6.3.3. Передача управления между режимами в DPMI 6.3.4. Обработчики прерываний 6.3.5. Пример программы И. Assembler для DOS, Windows и UNIX 6.4. Расширители DOS 6.4.1. Способы объединения программы с расширителем 6.4.2. Управление памятью в DPMI 6.4.3. Вывод на экран через линейный кадровый б^фер Глава 7. Программирование для Windows 95/NT 7.1. Первая программа 7.2. Консольные приложения 7.3. Графические приложения 7.3.1. Окно типа MessageBox 7.3.2. Окна 7.3.3. Меню 7.3.4. Диалоги 7.3.5. Полноценное приложение 7.4. Динамические библиотеки 7.5. Драйверы устройств Глава 8. Ассемблер и языки высокого уровня 8.1. Передача параметров 8.1.1. Конвенция Pascal 8.1.2. Конвенция С 8.1.3. Смешанные конвенции 8.2. Искажение имен 8.3. Встроенный ассемблер 8.3.1. Ассемблер, встроенный в Pascal..... 8.3.2. Ассемблер, встроенный в С Глава 9. Оптимизация 9.1. Высокоуровневая оптимизация 9.2. Оптимизация на среднем уровне 9.2.1. Вычисление констант вне цикла 9.2.2. Перенос проверки условия в конец цикла 9.2.3. Выполнение цикла задом наперед 9.2.4. Разворачивание циклов 9.3. Низкоуровневая оптимизация 9.3.1. Общие принципы низкоуровневой оптимизации 9.3.2. Особенности архитектуры процессоров Pentium и Pentium MMX 9.3.3. Особенности архитектуры процессоров Pentium Pro и Pentium II Содержание Глава 10. Процессоры Intel в защищенном режиме... 10.1. Регистры 10.1.1. Системные флаги 10.1.2. Регистры управления памятью 10.1.3. Регистры управления процессором 10.1.4. Отладочные регистры 10.1.5. Машинно-специфичные регистры 10.2. Системные и привилегированные команды 10.3. Вход и выход из защищенного режима 10.4. Сегментная адресация 10.4.1. Модель памяти в защищенном режиме 10.4.2. Селектор 10.4.3. Дескрипторы 10.4.4. Пример программы 10.4.5. Нереальный режим....: 10.5. Обработка прерываний и исключений 10.6. Страничная адресация 10.7. Механизм защиты 10.7.1. Проверка лимитов 10.7.2. Проверка типа сегмента 10.7.3. Проверка привилегий 10.7.4. Выполнение привилегированных команд 10.7.5. Защита на уровне страниц 10.8. Управление задачами 10.8.1. Сегмент состояния задачи 10.8.2. Переключение задач 10.9. Режим виртуального 8086 10.9.1. Прерывания в V86 10.9.2. Ввод-вывод в V86 Глава 11. Программирование на ассемблере в среде UNIX 11.1. Синтаксис AT&T 11.1.1. Основные правила 11.1.2. Запись команд 11.1.3. Адресация 11.2. Операторы ассемблера 11.2.1. Префиксные, или унарные, операторы 11.2.2. Инфиксные, или бинарные, операторы Assembler для DOS, Windows и UNIX 11.3. Директивы ассемблера 11.3.1. Директивы определения данных 11.3.2. Директивы управления символами 11.3.3. Директивы определения секций 11.3.4. Директивы управления разрядностью 11.3.5. Директивы управления программным указателем г.

11.3.6. Директивы управления листингом 11.3.7. Директивы управления ассемблированием 11.3.8. Блоки повторения 11.3.9. Макроопределения 11.4. Программирование с использованием libc 11.5. Программирование без использования libc 11.6. Переносимая программа для UNIX Заключение Приложение 1. Таблицы символов 1. Символы ASCII 2. Управляющие символы ASCII 3. Кодировки второй половины ASCII 4. Коды символов расширенного ASCII s 5. Скан-коды клавиатуры Приложение 2. Команды Intel 80x86 1. Общая информация о кодах команд 1.1. Общий формат команды процессора Intel 1.2. Значения полей кода команды 1.3. Значения поля ModRM 1.4. Значения поля SIB : 2. Общая информация о скоростях выполнения 3. Префиксы 4. Команды процессоров Intel 8088 - Pentium III Используемые сокращения ГлОССарИЙ Алфавитный указатель Введение Первый вопрос, который задает себе человек, впервые услышавший об ассембле ре, - а зачем он, собственно, нужен? Особенно теперь, когда все пишут на C/C++, Delphi или других языках высокого уровня? Действительно очень многое можно создать на С, но ни один язык, даже такой популярный, не может претендовать на то, чтобы на нем можно было написать абсолютно все.

Итак, на ассемблере пишут:

Q все, что требует максимальной скорости выполнения: основные компоненты компьютерных игр, ядра операционных систем реального времени и просто критические участки программ;

Q все, что взаимодействует с внешними устройствами: драйверы, программы, работающие напрямую с портами, звуковыми и видеоплатами;

Q все, что использует полностью возможности процессора: ядра многозадачных операционных систем, DPMI-серверы и вообще любые программы, перево дящие процессор в защищенный режим;

Q все, что полностью использует возможности операционной системы: виру сы и антивирусы, защиты от несанкционированного доступа, программы, об ходящие эти защиты, и программы, защищающиеся от данных программ;

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

«Как же так? - спросите вы, прочитав последний пункт. - Ведь всем известно, что ассемблер - неудобный язык, и писать на нем долго и сложно!» Попробуем перечислить мотивы, которые обычно выдвигаются в доказательство того, что ассемблер не нужен.

Говорят, что ассемблер трудно выучить. Любой язык программирования трудно выучить. Легко выучить С или Delphi после Pascal, потому что они похожи. А по пробуйте освоить Lisp, Forth или Prolog, и окажется, что ассемблер в действитель ности даже проще, чем любой абсолютно незнакомый язык программирования.

Говорят, что программы на ассемблере трудно понять. Разумеется, на ассембле ре легко написать неудобочитаемую программу... точно так же, как и на любом дру гом языке! Если вы знаете язык и если автор программы не старался ее запутать, то понять программу будет не сложнее, чем если бы она была написана на Basic.

Говорят, что программы на ассемблере трудно отлаживать. Программы на ассемблере легко отлаживать - опять же при условии, что вы знаете язык. Более того, знание ассемблера часто помогает отлаживать программы на других языках, потому что оно дает представление о том, как на самом деле функционирует ком пьютер и что происходит при выполнении команд языка высокого уровня.

Assembler для DOS, Windows и UNIX Говорят, что современные компьютеры такие быстрые, что ассемблер больше не нужен. Каким бы быстрым ни был компьютер, пользователю всегда хочется большей скорости, иначе не наблюдалось бы постоянного спроса на еще более мощные компьютеры. И самой быстрой программой на данном оборудовании все гда будет программа, написанная на ассемблере.

Говорят, что писать на ассемблере сложно. В этом есть доля правды. Очень часто авторы программ на ассемблере «изобретают велосипеды», программируя заново элементарные процедуры типа форматированного вывода на экран или' генератора случайных чисел, в то время как программисты на С просто вызывают стандартные функции. Библиотеки таких функций существуют и для ассемблера, но они не стандартизированы и не распространяются вместе с компиляторами.

Говорят, что программы на ассемблере не переносятся. Действительно, в этом заключается самая сильная и самая слабая сторона ассемблера. Во-первых, благо даря этой особенности программы на ассемблере используют возможности ком пьютера с наибольшей полнотой;

во-вторых, эти же программы не будут работать на другом компьютере. Стоит заметить, что и другие языки часто не гарантируют переносимости - та же программа на С, написанная, например, под Windows 95, не скомпилируется ни на Macintosh, ни на SGI.

Далеко не всё, что говорят об ассемблере, является правдой, и далеко не все, кто говорят об ассемблере, на самом деле знают его. Но даже ярые противники согласятся с тем, что программы на ассемблере — самые быстрые, самые малень кие и могут то, что не под силу программам, созданным на любом другом языке программирования.

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

Почти все, что надо знать об ассемблере, где-нибудь да объяснено, а также объяснено многое из того, что не заботит большинство программистов. С одной стороны, чтобы написать простую программу, не нужно знать язык и устройство процессора в совершенстве, но, с другой стороны, по-настоящему серьезная рабо та потребует и основательной подготовки. Уровень сложности в этой книге воз растает от начала к концу, но в первой ее половине отдельные абзацы помечены специальной пиктограммой (*а), которая означает, что данный абзац лучше про пустить при чтении, если вы знакомитесь с ассемблером впервые. Впрочем, если у вас есть время и желание выучить ассемблер с нуля, - читайте все по порядку.

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

Глава 1. Предварительные сведения 1.1. Что нужно для работы с ассемблером Прежде всего вам потребуется ассемблер. Здесь самое время сказать, что язык программирования, которым мы собираемся заниматься, называется «язык ассем блера» (assembly language). Ассемблер - это программа, которая переводит текст с языка, понятного человеку, в язык, понятный процессору, то есть говорят, что она переводит язык ассемблера в машинный код. Однако сначала в повседневной речи, а затем и в литературе слово «ассемблер» стало также и названием самого языка программирования. Понятно, что, когда говорят «программа на ассемблере», имеют в виду язык, а когда говорят «макроассемблер версии 6.13», имеют в виду программу. Вместе с ассемблером обязательно должна быть еще одна программа компоновщик (linker), которая и создает исполнимые файлы из одного или несколь ких объектных модулей, полученных после запуска ассемблера. Помимо этого для разных целей могут потребоваться дополнительные вспомогательные программы компиляторы ресурсов, расширители DOS и тому подобное (см. табл. 1).

Трудно говорить о том, продукция какой из трех компаний (Borland, Microsoft или Watcom) однозначно лучше. С точки зрения удобства компиляции TASM луч ше подходит для создания 16-битных программ для DOS, WASM - для 32-бит ных программ для DOS, MASM - для Windows. С точки зрения удобства про граммирования развитость языковых средств растет в ряду WASM - MASM TASM. Все примеры программ в этой книге построены так, что можно использо вать любой из этих компиляторов.

Таблица 1. Ассемблеры и сопутствующие программы Borland Microsoft Watcom masm или ml, tasm wssm DOS, link (16 бит) tlink wlink 16 бит tasm wasm masm или ml, tlink wlink DOS, link (32 бита) и dosx wdosx dos4gw, pmodew, zrdx или 32 бита link (16 бит) и dos или dos32 wdosx tasm wasm masm386 или ml Windows wlink tlink link (32 бита) EXE wrc brcc re tasm wasm masm386 или ml Windows tlink32 wlink DLL link (32 бита) implib wlib Предварительные сведения Разумеется, существуют и другие компиляторы, например бесплатно распрос траняемый в сети Internet NASM или условно бесплатный А86, но пользоваться ими проще, если вы уже знаете турбо- или макроассемблер. Бесплатно распрост раняемый GNU ассемблер, gas, вообще использует совершенно непохожий син таксис, который будет рассмотрен в главе 11, рассказывающей о программирова нии для UNIX.

Во всех программах встречаются ошибки. Если вы собираетесь не только упражняться на примерах из книги, но и написать что-то свое, то вам рано или поздно обязательно потребуется отладчик. Кроме поиска ошибок отладчики иног да применяют и для того, чтобы исследовать работу существующих программ. Бе зусловно, самый мощный отладчик на сегодняшний день - SoftlCE от NuMega Software. Это фактически единственный отладчик для Windows 95/NT, позволя ющий исследовать все - от ядра Windows до программ на C++, поддерживающий одновременно 16- и 32-битный код и т. п. Другие популярные отладчики, распро страняемые вместе с соответствующими ассемблерами, - Codeview (MS), Turbo Debugger (Borland) и Watcom Debugger (Watcom).

Еще одна особенность ассемблера, отличающая его от всех остальных языков программирования, - возможность дизассемблирования. То есть, имея исполняе мый файл, с помощью специальной программы (дизассемблера) почти всегда мож но получить исходный текст на ассемблере. Например, можно дизассемблировать BIOS вашего компьютера и узнать, как выполняется переключение видеорежимов, или драйвер для DOS, чтобы написать такой же для Windows. Дизассемблер не является необходимой программой, но иногда очень удобно иметь его под рукой.

Лучшие дизассемблеры на сегодняшний день - Sourcer от V Communications и IDA.

И наконец, последняя необязательная, но весьма полезная утилита - шестнад цатеричный редактор. Многие подобные редакторы (hiew, preview, Iview, hexit) имеют встроенный дизассемблер, так что можно, например, открыв в таком ре дакторе свою программу, посмотреть, как скомпилировался тот или иной участок программы, поправить какую-нибудь команду ассемблера или изменить значения констант и тут же, без перекомпиляции, запустить программу, чтобы посмотреть на результат изменений.

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

1.2.1. Двоичная система счисления Практически все существующие сейчас компьютерные системы, включая Intel, используют для вычислений двоичную систему счисления. В их электрических Представление данных в компьютерах цепях напряжение может принимать два значения, и эти значения назвали нулем и единицей. Двоичная система счисления как раз и использует только эти две цифры, а вместо степеней десяти, как в обычной десятичной системе, здесь при меняют степени двойки. Чтобы перевести двоичное число в десятичное, надо сло жить двойки в степенях, соответствующих позициям, где в двоичном стоят еди ницы. Например:

10010111Ь=1Х27+ОХ26+ОХ25+1Х24+ОХ23+1Х22+1Х21+1Х2°=128+16+4+2+1= Для перевода десятичного числа в двоичное мож- ^_™^_^' ПеРевоДчисла системы но, например, разделить его на 2, записывая остаток в двоичную справа налево (см. табл. 2).

Чтобы отличать двоичные числа от десятичных, Остаток в ассемблерных программах в конце каждого двоич- 151/2 =75 ного числа ставят букву Ь. 75/2 =37 37/2 = 18 7.2.2. Биты, байты и слова 18/2 = 9 Минимальная единица информации называется 9/2 = 4 битом. Бит принимает только два значения - обычно 4/2 = 2 О и 1. На самом деле они совершенно необязательны 2/2 = 1 один бит может принимать значения «да» и «нет», по 1/2 = казывать присутствие и отсутствие жесткого диска, Результат: 1 00101 11Ь а также является ли персонаж игры магом или вои ном - важно лишь то, что бит имеет только два значения. Но многие величины принимают большее число значений, следовательно, для их описания нельзя обойтись одним битом.

Единица информации размером 8 бит называется байтом. Байт - это мини мальный объем данных, который реально может использовать компьютерная программа. Даже для изменения значения одного бита в памяти надо сначала считать байт, содержащий его. Биты в байте нумеруют справа налево, от нуля до семи, нулевой бит часто называют младшим битом, а седьмой - старшим (см. рис. 1).

Так как всего в байте восемь бит, он может принимать до 2 = 256 разных зна чений. Байт используют для представления целых чисел от 0 до 255 (тип unsigned char в С), целых чисел со знаком от -128 до +127 (тип signed char в С), набора символов ASCII (тип char в С) или переменных, принимающих менее 256 значе ний, например для представления десятичных чисел от 0 до 99.

Следующий по размеру базовый тип данных - слово. Размер одного слова в про цессорах Intel - два байта (см. рис. 2). Биты с 0 по 7 составляют младший байт слова, а биты с 8 по 15 - старший. В слове содержится 16 бит, а значит, оно может 7 6 5 4 3 2 1 РИС. 1. Байт Предварительные сведения принимать до 216 = 65 536 разных значений. Слова используют для представле ния целых чисел без знака со значениями 0-65 535 (тип unsigned short в С), це лых чисел со знаком от -32 768 до +32 767 (тип short int в С), адресов сегментов и смещений при 16-битной адресации. Два слова подряд образуют двойное слово, состоящее из 32 бит, а два двойных слова - одно учетверенное слово (64 бита).

Байты, слова и двойные слова - основные типы данных, с которыми мы будем работать.

Еще одно важное замечание: в компьютерах с процессорами Intel все дан ные хранятся так, что младший байт находится по младшему адресу, по этому слова записываются задом наперед, то есть сначала (по младшему адресу) - последний (младший) байт, а потом (по старшему адресу) первый (старший) байт. Если из программы всегда обращаться к слову как к слову, а к двойному слову как к двойному слову, это не оказывает ни какого влияния. Но если вы хотите прочитать первый (старший) байт из слова в памяти, то придется увеличить адрес на 1. Двойные и учетверен ные слова записываются так же - от младшего байта к старшему.

\ I J 15 87 О Рис. 2. Слово 1.2.3. Шестнадцатеричная система счисления Главное неудобство двоичной системы счисления - это размеры чисел, с ко торыми приходится обращаться. На практике с двоичными числами работают, только если необходимо следить за значениями отдельных битов, а когда разме ры переменных превышают хотя бы четыре бита, используется шестнадцатерич ная система. Она хороша тем, что компактнее десятичной, и тем, что перевод в двоичную систему и обратно происходит очень легко. В шестнадцатеричной системе используется 16 «цифр» (О, 1, 2, 3, 4, 5, 6, 7, 8, 9, А, В, С, D, E, F), и но мер позиции цифры в числе соответствует степени, в которую надо возвести число 16, следовательно:

96h = 9 X 16 + 6 = Перевод в двоичную систему и обратно осуществляется крайне просто - вме сто каждой шестнадцатеричной цифры подставляют соответствующее четырех значное двоичное число:

9h = 1001b, 6h = 0110Ь, 96h = 1U010110b В ассемблерных программах при записи чисел, начинающихся с А, В, С, D, Е, F, в начале приписывается цифра 0, чтобы не перепутать такое число с названием переменной или другим идентификатором. После шестнадцатеричных чисел ста вится буква h (см. табл. 3).

| Представление данных в компьютерах Таблица 3. Двоичные и шестнадцатеричные числа Двоичное Шестнадцатеричное Десятичное ооооь 0 OOh 1 01h 000 1Ь 2 02h 001 Ob 03h 001 1b оюоь 04h 05h 5 0101b 08h 6 0110b 07h 0111b юооь 08h 9 09h 1001b OAh 10 1010b OBh 11 1011b OCh 12 1100b ODh 13 1101b OEh 14 1110b OFh 15 1111b юоооь 10h 7.2.4. Числа со знаком Легко использовать байты, слова или двойные слова для представления целых положительных чисел - от 0 до 255,65 535 или 4 294 967 295 соответственно. Чтобы применять те же самые байты или слова для представления отрицательных чисел, существует специальная операция, известная как дополнение до двух. Для измене ния знака числа выполняют инверсию, то есть заменяют в двоичном представлении числа все единицы нулями и нули единицами, а затем прибавляют 1.

Например, пусть используются переменные типа слова:

150 = 0096h = 0000 0000 1001 0110Ь инверсия дает: 1111 1111 0110 1001Ь + 1 = 1111 1111 0110 ЮЮЬ = OFF6Ah + 150 должна быть равна Проверим, что число на самом деле -150: сумма нулю:

+150 + (-150) = 0096h + OFF6Ah = 10000h Единица в 16-м разряде не помещается в слово, следовательно, мы действи тельно получили 0. В данном формате старший (7-й, 15-й, 31-й для байта, слова, двойного слова) бит всегда соответствует знаку числа: 0 - для положительных и 1 - для отрицательных. Таким образом, схема с использованием дополнения до двух выделяет для положительных и отрицательных чисел равные диапазоны:

Предварительные сведения -128...+127 - для байта, -32 7 8. + 2 767 - для слов, -2 147 483 6 S. + 147 483 647 6..3 4.. для двойных слов.

7.2.5. Логические операции Самые распространенные варианты значений, которые может принимать один бит, - это значения «правда» и «ложь», используемые в логике, откуда происхо дят так называемые «логические операции» над битами. Так, если объединить «правду» и «правду» — получится «правда», а если объединить «правду» и «ложь» - «правды» не получится. В ассемблере нам встретятся четыре основные опера ции - И (AND), ИЛИ (OR), «исключающее ИЛИ» (XOR) и отрицание (NOT), действие которых приводится в табл. 4.

Таблица 4. Логические операции Исключающее ИЛИ Отрицание И ИЛИ NOT 0 = 0 AND 0 = 0 0 OR 0 = 0 0 XOR 0 = NOT 1 = OAND1 = 0 0 OR 1 = 1 0 XOR 1 = 1 AND 0 = 0 1 OR 0 = 1 1 XOR 0 = 1 OR 1 = 1 AND 1 = 1 1 XOR 1 = Все перечисленные операции являются побитовыми, поэтому для выполнения логического действия над числом надо перевести его в двоичный формат и про извести операцию над каждым битом, например:

96h AND OFh = 10010110b AND 00001111b = 0000011Gb = 06h 1.2.6. Коды символов Для представления всех букв, цифр и знаков, появляющихся на экране ком пьютера, обычно используется всего один байт. Символы, соответствующие зна чениям от 0 до 127, то есть первой половине всех возможных значений байта, были стандартизированы.и названы символами ASCII (хотя часто кодами ASCII именуют всю таблицу из 256 символов). Сюда входят некоторые управляющие коды (символ с кодом ODh - конец строки), знаки препинания, цифры (симво лы с кодами 30h - 39h), большие (41h - 5Ah) и маленькие (61h - 7 Ah) латинс кие буквы. Вторая половина символьных кодов используется для алфавитов дру гих языков и псевдографики, набор и порядок символов в ней отличаются в разных странах и даже в пределах одной страны. Например, для букв одного только русского языка существует пять вариантов размещения во второй поло вине таблицы символов ASCII (см. приложение 1). Существует также стандарт, использующий слова для хранения кодов символов, известный как UNICODE или UCS-2, и даже двойные слова (UCS-4), но мы пока не будем на нем оста навливаться.

Представление данных в компьютерах 12.7. Организация памяти Память с точки зрения процессора представляет собой последовательность байтов, каждому из которых присвоен уникальный адрес со значениями от 0 до 232-1 (4 Гб). Программы же могут работать с памятью как с одним непрерывным массивом (модель памяти flat) или как с несколькими массивами (сегментирован ные модели памяти). Во втором случае для задания адреса любого байта требует ся два числа - адрес начала массива и адрес искомого байта внутри массива. По мимо основной памяти программы могут использовать регистры - специальные ячейки памяти, расположенные физически внутри процессора, доступ к которым осуществляется не по адресам, а по именам. Но здесь мы вплотную подходим к рассмотрению собственно работы процессора, о чем подробно рассказано в сле дующей главе.

Глава 2. Процессоры Intel в реальном режиме Процессор Intel x86 после включения питания оказывается в так называемом ре жиме реальной адресации памяти, или просто реальном режиме. Большинство операционных систем сразу же переводит его в защищенный режим, позволяю щий им обеспечивать многозадачность, распределение памяти и другие функции.

Пользовательские программы в таких операционных системах часто работают еще и в режиме V86, из которого им доступно все то же, что и из реального, кроме команд, относящихся к управлению защищенным режимом. Следовательно, дан ная глава описывает реальный режим и V86, то есть все, что доступно программи сту в подавляющем большинстве случаев, если он не проектирует операционную систему или DPMI-сервер.

2.1. Регистры процессора Начиная с 80386 процессоры Intel предоставляют 16 основных регистров для пользовательских программ плюс еще 11 регистров для работы с мультимедий ными приложениями (ММХ) и числами с плавающей запятой (FPU/NPX). Все команды так или иначе изменяют значения регистров, и всегда быстрее и удобнее обращаться к регистру, чем к памяти.

Из реального (но не из виртуального) режима помимо основных регистров доступны также регистры управления памятью (GDTR, IDTR, TR, LDTR), реги стры управления (CRO, CR1 - CR4), отладочные регистры (DRO - DR7) и ма шинно-специфичные регистры, но они не применяются для решения повседнев ных задач и рассматриваются далее в соответствующих разделах.

2.7.1 Регистры общего назначения 32-битные регистры ЕАХ (аккумулятор), ЕВХ (база), ЕСХ (счетчик), EDX (регистр данных) могут использоваться без ограничений для любых целей - вре менного хранения данных, аргументов или результатов различных операций. На звания регистров происходят от того, что некоторые команды применяют их спе циальным образом: так, аккумулятор часто необходим для хранения результата действий, выполняемых над двумя операндами, регистр данных в этих случаях получает старшую часть результата, если он не умещается в аккумулятор, регистр счетчик работает как счетчик в циклах и строковых операциях, а регистр-база при так называемой адресации по базе. Младшие 16 бит каждого из этих регист ров применяются как самостоятельные регистры с именами АХ, ВХ, СХ, DX. На Регистры процессора :tf самом деле в процессорах 8086-80286 все регистры были 16-битными и называ лись именно так, а 32-битные ЕАХ - EDX появились с введением 32-битной ар хитектуры в 80386. Кроме этого, отдельные байты в 16-битных регистрах АХ DX тоже могут использоваться как 8-битные регистры и иметь свои имена. Стар шие байты этих регистров называются АН, ВН, СН, DH, а младшие - AL, BL, CL, DL (см. рис. 3).

Остальные четыре регистра - ESI (индекс источника), EDI (индекс приемни ка), ЕВР (указатель базы), ESP (указатель стека) - имеют более конкретное на значение и применяются для хранения всевозможных временных переменных.

Регистры ESI tfEDI необходимы в строковых операциях, ЕВР и ESP - при рабо те со стеком (см. раздел 2.1.3). Так же как и в случае с регистрами ЕАХ - EDX, младшие половины этих четырех регистров называются SI, DI, BP и SP соот ветственно, и в процессорах до 80386 только они и присутствовали.

АХ АН ЕАХ AL 31 16 15 ВХ ЕВХ ВН BL сх СН ЕСХ CL DX EDX DH DL ESI SI DI EDI ЕВР ЗР ESP SP Рис. 3. Регистры общего назначения i | Процессоры Intel в реальном режиме 2.1.2. Сегментные регистры При использовании сегментированных моделей памяти для формирования лю бого адреса нужны два числа - адрес начала сегмента и смещение искомого байта относительно этого начала (в бессегментной модели памяти flat адреса начал всех сегментов равны). Операционные системы (кроме DOS) могут размещать сегмен ты, с которыми работает программа пользователя, в разных местах памяти и даже временно записывать их на диск, если памяти не хватает. Так как сегменты способ ны оказаться где угодно, программа обращается к ним, применяя вместо настоя щего адреса начала сегмента 16-битное число, называемое селектором. В процес сорах Intel предусмотрено шесть 16-битных регистров - CS, DS, ES, FS, GS, SS, где хранятся селекторы. (Регистры FS и GS отсутствовали в 8086, но появились уже в 80286.) Это означает, что в любой момент можно изменить параметры, запи санные в этих регистрах.

В реальном режиме селектор каждого сегмента равен адресу его начала, де ленному на 16. Чтобы получить адрес в памяти, 16-битное смещение скла дывают с этим селектором, предварительно сдвинутым влево на 4. Таким образом, оказывается, что максимальный доступный адрес в реальном ре жиме 220 - 1 = 1 048 575. Для сравнения: в защищенном режиме адрес нача ла для каждого сегмента хранится отдельно, так что возможно 246 (64 Тб) различных логических адреса в формате сегментхмещение (программа оп ределяет до 16 383 сегментов, каждый из которых до 4 Тб), хотя реально процессор адресуется только к 4 или 64 (для Pentium Pro) Тб памяти.

В отличие от DS, ES, GS, FS, которые называются регистрами сегментов дан ных, CS и SS отвечают за сегменты двух особенных типов - сегмент кода и сегмент стека. Первый содержит программу, исполняющуюся в данный момент, следова тельно, запись нового селектора в этот регистр приводит к тому, что далее будет исполнена не следующая по тексту программы команда, а команда из кода, нахо дящегося в другом сегменте, с тем же смещением. Смещение очередной выпол няемой команды всегда хранится в специальном регистре EIP (указатель инст рукции, 16-битная форма IP), запись в который также приведет к тому, что далее будет исполнена какая-нибудь другая команда. На самом деле все команды пере дачи управления - перехода, условного перехода, цикла, вызова подпрограммы и т. п. - и осуществляют эту самую запись в CS и EIP.

2.1.3. Стек Стек - организованный специальным образом участок памяти, который ис пользуется для временного хранения переменных, передачи параметров вызыва емым подпрограммам и сохранения адреса возврата при вызове процедур и пре рываний. Легче всего представить стек в виде стопки листов бумаги (это одно из значений слова «stack» в английском языке) — вы можете класть и забирать листы только с вершины стопки. Поэтому, если записать в стек числа 1, 2, 3, то при чте нии они окажутся в обратном порядке - 3, 2, 1. Стек располагается в сегменте па мяти, описываемом регистром SS, и текущее смещение вершины стека отражено Регистры процессора в регистре ESP, причем во время записи значение этого смещения уменьшается, то есть он «растет вниз» от максимально возможного адреса (см. рис. 4). Такое расположение стека «вверх ногами» может быть необходимо, к примеру, в бес сегментной модели памяти, когда все сегменты, включая сегменты стека и кода, занимают одну и ту же область - память целиком. Тогда программа исполняет ся в нижней области памяти, в области малых адресов, и EIP растет, а стек распо лагается в верхней области памяти, и ESP уменьшается.

При вызове подпрограммы параметры в большинстве случаев помещают в стек, а в ЕВР записывают текущее значение ESP. Если подпрограмма использует стек для хранения локальных переменных, ESP изменится, но ЕВР можно будет ис пользовать для того, чтобы считывать Значения параметров напрямую из стека (их смещения запишутся как ЕВР + номер параметра). Более подробно вызовы подпрограмм и все возможные способы передачи параметров рассмотрены в раз деле 5.2. Дно стека FCh F8h Параметры F4h •« EBP=OFFFFFFFOh FOh ECh J Локальные переменные OFFFFFFESh •8h ESP=OFFFFFE4h E4h • Рис. 4. Стек 2.1.4. Регистр флагов Еще один важный регистр, использующийся при выполнении большинства ко манд, - регистр флагов. Как и раньше, его младшие 16 бит, представлявшие собой весь этот регистр до процессора 80386, называются FLAGS. В EFLAGS каждый бит является флагом, то есть устанавливается в 1 при определенных условиях или установка его в 1 изменяет поведение процессора. Все флаги, расположенные в старшем слове регистра, имеют отношение к управлению защищенным режи мом, поэтому здесь рассмотрен только регистр FLAGS (см. рис. 5):

Q CF - флаг переноса. Устанавливается в 1, если результат предыдущей опера ции не уместился в приемнике и произошел перенос из старшего бита или 1 CF ZF 0 AF PF OF DF IF TF SF 0 NT IOPL Рис. 5. Регистр флагов FLAGS Процессоры Intel в реальном режиме если требуется заем (при вычитании), в противном случае - в 0. Например, после сложения слова OFFFFh и 1, если регистр, в который надо поместить результат, - слово, в него будет записано OOOOh и флаг CF = 1.

a PF - флаг четности. Устанавливается в 1, если младший байт результата предыдущей команды содержит четное число битов, равных 1, и в 0, если нечетное. Это не то же самое, что делимость на два. Число делится на два без остатка, если его самый младший бит равен нулю, и не делится, когда он равен 1.

Q AF - флаг полупереноса или вспомогательного переноса. Устанавливается в 1, если в результате предыдущей операции произошел перенос (или заем) из третьего бита в четвертый. Этот флаг используется автоматически коман дами двоично-десятичной коррекции.

Q ZF - флаг нуля. Устанавливается в 1, если результат предыдущей команды ноль.

Q SF - флаг знака. Он всегда равен старшему биту результата.

Q TF - флаг ловушки. Он был предусмотрен для работы отладчиков, не ис пользующих защищенный режим. Установка его в 1 приводит к тому, что после выполнения каждой программной команды управление временно пере дается отладчику (вызывается прерывание 1 - см. описание команды INT).

Q IF - флаг прерываний. Сброс этого флага в 0 приводит к тому, что процессор перестает обрабатывать прерывания от внешних устройств (см. описание ко манды INT). Обычно его сбрасывают на короткое время для выполнения критических участков кода.

QDF — флаг направления. Он контролирует поведение команд обработки строк: когда он установлен в 1, строки обрабатываются в сторону уменьше ния адресов, когда DF = 0 - наоборот.

Q OF - флаг переполнения. Он устанавливается в 1, если результат предыду щей арифметической операции над числами со знаком выходит за допусти мые для них пределы. Например, если при сложении двух положительных чисел получается число со старшим битом, равным единице, то есть отрица тельное, и наоборот.

Флаги IOPL (уровень привилегий ввода-вывода) и NT (вложенная задача) применяются в защищенном режиме.

2.2. Способы адресации Большинство команд процессора вызываются с аргументами, которые в ассем блере принято называть операндами. Например: команда сложения содержимого регистра с числом требует задания двух операндов — содержимого регистра и чис ла. Далее рассмотрены все существующие способы задания адреса хранения опе рандов - способы адресации.

2.2.7. Регистровая адресация Операнды могут располагаться в любых регистрах общего назначения и сегмент ных регистрах. Для этого в тексте программы указывается название соответствующего Способы адресации ViSI регистра, например: команда, копирующая в регистр АХ содержимое регистра ВХ, записывается как mov ax.bx 2.2.2. Непосредственная адресация Некоторые команды (все арифметические, кроме деления) позволяют ука зывать один из операндов непосредственно в тексте программы. Например:

команда mov ax, помещает в регистр АХ число 2.

2.2.3. Прямая адресация Если у операнда, располагающегося в памяти, известен адрес, то его можно использовать. Если операнд - слово, находящееся в сегменте, на который указы вает ES, со смещением от начала сегмента 0001, то команда mov ax.es: поместит это слово в регистр АХ. В реальных программах для задания статичес ких переменных обычно используют директивы определения данных (раздел 3.3), которые позволяют ссылаться на статические переменные не по адресу, а по име ни. Тогда, если в сегменте, указанном в ES, была описана переменная word_var размером в слово, можно записать ту же команду как mov ax,es:word_var В таком случае ассемблер сам заменит слово word_var на соответствующий адрес. Если селектор сегмента данных находится в DS, то имя сегментного реги стра при прямой адресации можно не указывать, DS используется по умолча нию. Прямая адресация иногда называется адресацией по смещению.

Адресация отличается для реального и защищенного режимов. В реальном (так же как и в режиме V86) смещение всегда 16-битное. Это значит, что ни не посредственно указанное смещение, ни результат сложения содержимого разных регистров в более сложных методах адресации не могут превышать границ слова.

При работе в Windows, DOS4G, PMODE и в других ситуациях, когда программа будет запускаться в защищенном режиме» смещение не должно превышать гра ниц двойного слова.

2.2.4. Косвенная адресация По аналогии с регистровыми и непосредственными операндами адрес операн да в памяти также можно не указывать, а хранить в любом регистре. До процессо ра 80386 для этого можно было использовать только ВХ, SI, DI и ВР, но потом ограничения были сняты и адрес операнда разрешили считывать также из ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ЕВР и ESP (но не из АХ, СХ, DX или SP напрямую надо использовать ЕАХ, ЕСХ, EDX, ESP соответственно или предварительно ско пировать смещение в ВХ, SI, DI или ВР). Например, следующая команда помещает Процессоры Intel в реальном режиме в регистр АХ слово из ячейки памяти, селектор сегмента которой находится в DS, а смещение - в ВХ:

mov ax,[bx] ' Как и в случае с прямой адресацией, DS используется по умолчанию, но не всегда: если смещение берут из регистров ESP, EBP или ВР, то в качестве сегмен тного регистра применяется SS. В реальном режиме можно свободно работать со всеми 32-битными регистрами, надо только следить, чтобы их содержимое не пре вышало границ 16-битного слова.

2.2.5. Адресация по базе со сдвигом Теперь скомбинируем два предыдущих метода адресации. Следующая команда mov ax,[bx+2] помещает в регистр АХ слово, которое есть в сегменте, указанном в DS, со смеще нием на два больше, чем число из ВХ. Так как слово занимает ровно 2 байта, эта команда поместила в АХ слово, непосредственно следующее за тем, которое было в предыдущем примере. Такая форма адресации используется в тех случаях, ког да в регистре находится адрес начала структуры данных, а доступ надо осуще ствить к какому-нибудь ее элементу. Еще один вариант применения адресации по базе со сдвигом — доступ из подпрограммы к параметрам, переданным в стеке, ис пользуя регистр ВР (ЕВР) в качестве базы и номер параметра в качестве смеще ния, что детально рассмотрено в разделе 4.3.2. Другие допустимые формы записи этого способа адресации:

mov ax,[bp]+ mov ax,2[bp] До процессора 80386 в качестве базового регистра разрешалось использовать только ВХ, ВР, SI или DI и сдвиг мог быть только байтом или словом (со знаком).

Начиная с 80386 и старше, процессоры Intel позволяют дополнительно использо вать ЕАХ, ЕВХ, ЕСХ, EDX, EBP, ESP, ESI и EDI, так же как и для обычной косвен ной адресации. С помощью этого метода разрешается организовывать доступ к од номерным массивам байтов: смещение соответствует адресу начала массива, а число в регистре - индексу элемента массива, который надо считать. Очевидно, что, если массив состоит не из байтов, а из слов, придется умножать базовый ре гистр на два, а если из двойных слов - на четыре. Для этого предусмотрен специ альный метод - косвенная адресация.

2.2.6. Косвенная адресация с масштабированием Этот метод адресации полностью идентичен предыдущему, однако с его помо щью можно прочитать элемент массива слов, двойных слов или учетверенных слов, просто поместив номер элемента в регистр:

mov ax, [esi*2]+ Множитель, который равен 1, 2,4 или 8, соответствует размеру элемента мас сива — байту, слову, двойному или учетверенному слову. Из регистров в этом Способы адресации варианте адресации можно использовать только ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, EBP, ESP, но не SI, DI, ВР или SP.

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

mov ax,[bx+si+2] mov ax,[bx][si]+ mov ax,[bx+2][si] mov ax,[bx][si+2] mov ax,2[bx][si] В регистр АХ помещается слово из ячейки памяти со смещением, равным сум ме чисел, содержащихся в ВХ, SI, и числа 2. Из 16-битных регистров так можно складывать только ВХ + SI, ВХ + DI, ВР + SI и ВР + DI, а из 32-битных — все восемь регистров общего назначения. Как и для прямой адресации, вместо непос редственного указания числа разрешено использовать имя переменной, заданной одной из директив определения данных. Таким образом можно считать, напри мер, число из двумерного массива: если задана таблица 10x10 байт, 2 - смещение ее начала от начала сегмента данных (на практике будет использоваться имя этой таблицы), ВХ = 20, a SI = 7, приведенные команды прочитают слово, состоящее из седьмого и восьмого байтов третьей строки. Если таблица состоит не из оди ночных байтов, а из слов или двойных слов, удобнее использовать наиболее пол ную форму - адресацию по базе с индексированием и масштабированием.

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

Смещение может быть байтом или двойным словом. Если ESP или ЕВР ис пользуются в роли базового регистра, Селектор сегмента операнда берется по умолчанию из регистра SS, во всех остальных случаях - из DS.

EAX EAX CS: EBX EBX SS: ECX ECX DS: EDX+ смещение EDX * ES: EBP EBP FS: ESP ESI OS: EDI EDI ESI Рис. 6. Полная форма адресации Процессоры Intel в реальном режиме 2.3. Основные непривилегированные команды В этом разделе описаны все непривилегированные команды процессоров Intel серии х86, включая команды расширений IA NPX (чаще называемое FPU - рас ширение для работы с числами с плавающей запятой) и IA MMX (мультимедий ное расширение). Для каждой команды указана форма записи, название и модель процессоров Intel, начиная с которой она поддерживается: 8086, 80186, 80286, 80386, 80486, Р5 (Pentium), MMX, P6 (Pentium Pro и Pentium II).

2.3.1. Пересылка данных Команда Назначение Процессор MOV приемник, источник Пересылка данных Базовая команда пересылки данных. Копирует содержимое источника в при емник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда mov ax.bx эквивалентна выражению ах:=Ьх;

языка Pascal или ах=Ьх;

языка С, за исключением того, что команда ассемблера позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора.

В качестве источника для MOV могут использоваться: число (непосредствен ный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти);

в качестве приемника: регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда дол жны быть одного и того же размера - байт, слово или двойное слово.

Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой и нельзя помещать в сегмент ный регистр непосредственный операнд - эти операции выполняют двумя коман дами MOV (из сегментного регистра в обычный и уже из него в другой сегмент ный) или парой команд PUSH/POP.

Загрузка регистра SS командой MOV автоматически запрещает прерывания до окончания следующей за ней команды MOV, поэтому можно не опасаться, что в этот момент произойдет прерывание, обработчик которого получит неправильный стек. В любом случае для загрузки значения в регистр SS пред почтительнее команда LSS.

Команда Назначение Процессор CMOVcc приемник.источник Условная пересылка данных Р Непривилегированные команды | Это набор команд, которые копируют содержимое источника в приемник, если удовлетворяется то или иное условие (см. табл. 5). Источником может быть ре гистр общего назначения или переменная, а приемником - только регистр. Тре бование, которое должно выполниться, - просто равенство нулю или единице тех или иных флагов из регистра FLAGS, но, если использовать команды CMOVcc сразу после СМР (сравнение) с теми же операндами, условия приобретают осо бый смысл, например:

ах, Ьх сглр Сравнить ах и Ьх.

ах, Ьх cmovl Если ах < Ьх, скопировать Ьх в ах.

Слова «выше» и «ниже» в табл. 5 относятся к сравнению чисел без знака, сло ва «больше» и «меньше» учитывают знак.

Таблица 5. Разновидности команды CMOVcc Код команды Реальное условие Условие для СМР CMOVA Если выше CF = 0 и ZF = CMOVNBE Если не ниже и не равно CMOVAE Если выше или равно CF = CMOVNB Если не ниже CMOVNC Если нет переноса CMOVB Если ниже CF= CMOVNAE Если не выше и не равно CMOVC Если перенос CMOVBE Если ниже или равно CF= 1 umZF= CMOVNA Если не выше CMOVE Если равно ZF= CMOVZ Если ноль CMOVG Если больше ZF = 0 и SF = OF CMOVNLE Если не меньше и не равно CMOVGE Если больше или равно SF = OF CMOVNL Если не меньше CMOVL Если меньше SFO OF CMOVNGE Если не больше и не равно CMOVLE Если меньше или равно ZF = 1 или SF 0 OF Если не больше CMOVNG Если не равно CMOVNE ZF = CMOVNZ Если не ноль OF = 0 Если нет переполнения CMOVNO OF=1 Если есть переполнение CMOVO Если нет четности CMOVNP PF = Если нечетное CMOVPO Если есть четность CMOVP PF= Если четное CMOVPE SF = 0 Если нет знака CMOVNS SF=1 Если есть знак CMOVS Процессоры Intel в реальном режиме Команда Назначение Процессор ХСНСоперанд1,операнд2 Обмен операндов между собой Содержимое операнда 2 копируется в операнд 1, а старое содержимое операн да 1 - в операнд 2. XCHG можно выполнять над двумя регистрами или над реги стром и переменной.

To же, что три команды на языке С:

еах, ebx xchg temp = еах еах = ebx;

ebx = temp А эта команда ничего не делает.

xchg al, al Команда Назначение Процессор BSWAP регистрЗЗ Обмен байтов внутри регистра Обращает порядок байтов в 32-битном регистре. Биты 0-7 (младший байт младшего слова) меняются местами с битами 24-31 (старший байт старшего слова), а биты 8-15 (старший байт младшего слова) - с битами 16-23 (младший байт старшего слова).

mov - eax,12345678h bswap еах ;

Теперь в еах находится 78563412h.

Чтобы обратить порядок байтов в 16-битном регистре, следует использовать команду XCHG:

xchg al.ah ;

Обратить порядок байтов в АХ.

В процессорах Intel команду BSWAP можно использовать и для обращения порядка байтов в 16-битных регистрах, но в некоторых совместимых процессорах других фирм этот вариант не реализован.

Команда Назначение Процессор PUSH источник Поместить данные в стек Помещает содержимое источника в стек. Источником может быть регистр, сег ментный регистр, непосредственный операнд или переменная. Фактически эта ко манда уменьшает ESP на размер источника в байтах (2 или 4) и копирует содер жимое источника в память по адресу SS:[ESP]. Команда PUSH почти всегда используется в паре с POP (считать данные из стека). Поэтому, чтобы скопиро вать содержимое одного сегментного регистра в другой (что нельзя выполнить од ной командой MOV), можно использовать такую последовательность команд:

push cs pop ds.;

Теперь DS указывает на тот же сегмент, что и CS.

Другой вариант применения команд PUSH/POP - временное хранение пере менных, например:

push еах ;

Сохраняет текущее значение ЕАХ.

;

Здесь располагаются какие-нибудь команды, ;

которые используют ЕАХ, например CMPXCHG.

pop еах ;

Восстанавливает старое значение ЕАХ.

Непривилегированные команды. У| Начиная с процессора 80286 команда PUSH ESP (или SP) помещает в стек значение ESP до того, как она же его уменьшит, а на 8086 регистр SP располагал ся в стеке уже уменьшенным на два.

Команда Назначение Процессор POP приемник Считать данные из стека - Помещает в приемник слово или двойное слово, находящееся в вершине сте ка, увеличивая ESP на 2 или 4 соответственно. POP выполняет действие, полно стью обратное PUSH. Приемником может быть регистр общего назначения, сег ментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменная. Если в роли приемника выступает операнд, ис пользующий ESP для косвенной адресации, команда POP вычисляет адрес опе ранда уже после того, как она увеличивает ESP.

Команда Назначение Процессор Поместить в стек PUSHA все регистры общего назначения PUSHAD PUSHA располагает в стеке регистры в следующем порядке: АХ, СХ, DX, ВХ, SP, ВР, SI и DI. PUSHAD помещает в стек EAX, ECX, EDX, EBX, ESP, EBP, ESI и EDI. (В случае с SP и ESP используется значение, которое находилось в регист ре до начала работы команды.) В паре с командами POPA/POPAD, считывающи ми эти же регистры из стека в обратном порядке, это позволяет писать подпро граммы (обычно обработчики прерываний), которые не должны изменять значения регистров по окончании своей работы. В начале такой подпрограммы вызывают команду PUSHA, а в конце - РОРА.

На самом деле PUSHA и PUSHAD - одна и та же команда с кодом 60h.

Ее поведение определяется тем, выполняется ли она в 16- или в 32-битном режиме. Если программист использует команду PUSHAD в 16-битном сегмен те или PUSHA в 32-битном, ассемблер просто записывает перед ней префикс изменения размерности операнда (66h). Это же будет распространяться на некоторые другие пары команд: POPA/POPAD, POPF/POPFD, PUSHF/ PUSHFDJCXZ/JECXZ, CMPSW/CMPSD, INSW/INSD, LODSW/LODSD, MOVSW/MOVSD, OUTSW/OUTSD, SCASW/SCASD и STOSW/STOSD.

Команда Назначение Процессор Загрузить из стека РОРА все регистры общего назначения POPAD Команды выполняют действия, полностью обратные действиям PUSHA и PUSHAD, но помещенное в стек значение SP или ESP игнорируется. РОРА загру жает из стека DI, SI, ВР, увеличивает SP на два, загружает ВХ, DX, СХ, АХ, a POPAD загружает EDI, ESI, ЕВР, увеличивает ESP на 4 и загружает EBX, EDX, ECX, EAX.

Процессоры Intel в реальном режиме Команда Назначение Процессор IN приемник.источник Считать данные из порта Копирует число из порта ввода-вывода, номер которого указан в источнике, в приемник. Приемником может быть только AL, АХ или ЕАХ. Источник - или непосредственный операнд, или DX, причем во время использования непосред ственного операнда можно указывать лишь номера портов не больше 255.

Команда Назначение Процессор OUT приемник.источник Записать данные в порт Копирует число из источника (AL, АХ или ЕАХ) в порт ввода-вывода, номер которого указан в приемнике. Приемник может быть либо непосредственным номером порта (не больше 255), либо регистром DX. На командах IN и OUT стро ится все общение процессора с устройствами ввода-вывода - клавиатурой, жест кими дисками, различными контроллерами, и используются они, в первую оче редь, в драйверах устройств. Например, чтобы включить динамик PC, достаточно выполнить команды:

in al,61h or al, out 61h,al Программирование портов ввода-вывода рассмотрено подробно в разделе 5.10.

Команда Назначение Процессор CWD Конвертирование слова в двойное слово Конвертирование двойного слова CDQ в учетверенное Команда CWD превращает слово в АХ в двойное слово, младшая половина которого (биты 0-15) остается в АХ, а старшая (биты 16-31) располагается в DX.

Команда CDQ выполняет аналогичное действие по отношению к двойному слову в ЕАХ, расширяя его до учетверенного слова в EDX:EAX.

Эти команды лишь устанавливают все биты регистра DX или EDX в значение, равное величине старшего бита регистра АХ или ЕАХ, сохраняя таким образом его знак.

Команда Назначение Процессор CBW Конвертирование байта в слово Конвертирование слова в двойное слово CWDE CBW расширяет байт, находящийся в регистре AL, до слова в АХ;

CWDE рас ширяет слово в АХ до двойного слова в ЕАХ. Команды CWDE и CWD отличают ся тем, что CWDE размещает свой результат в ЕАХ, в то время как CWD, выпол няющая точно такое же действие, располагает результат в паре регистров DX:AX.

Так же как и в командах CWD/CDQ, расширение выполняется путем установки Непривилегированные команды :18НЯД8ИННЕЯ каждого бита старшей половины результата равным старшему биту исходного байта или слова, то есть:

mov al,OF5h ;

AL = OF5h = 245 = -11.

Cbw ;

Теперь АХ = OFFFSh = 65 525 = -11.

Как и в случае с командами PUSHA/PUSHAD, пара CWD/CDQ - это одна команда с кодом 99h, и пара CBW/CWDE - одна команда с кодом 98h. Интер претация этих команд зависит от того, в каком (16-битном или в 32-бит ном) сегменте они исполняются. Если указать CDQ или CWDE в 16-битном сегменте, ассемблер поставит префикс изменения разрядности операнда.

Команда Назначение Процессор MOVSX приемник.источник Пересылка с расширением знака Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет знак аналогич но командам CBW/CWDE.

Команда Назначение Процессор MOVZX приемник.источник Пересылка с расширением нулями Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет нулями, то есть команда movzx ax, Ы эквивалентна паре команд mov al.bl mov ah, Команда Назначение Процессор XLAT адрес Трансляция в соответствии с таблицей XLATB Помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX) со смещением относительно начала таблицы равным AL. В качестве аргумента для XLAT в ассемблере можно указать имя таблицы, но эта информация никак не используется процессором и служит только в качестве комментария. Если он не нужен, можно применить форму записи XLATB. Например, можно написать сле дующий вариант преобразования шестнадцатеричного числа в ASCII-код соответ ствующего ему символа:

mov al.OCh mov bx, offset htable xlatb если в сегменте данных, на который указывает регистр ES, было записано htable db "0123456789ABCDEF" 2 Assembler для DOS - Процессоры Intel в реальном режиме то теперь AL содержит не число ОСЬ, а ASCII-код буквы С. Разумеется, это пре образование разрешается выполнить посредством более компактного кода всего из трех арифметических команд, который будет рассмотрен в описании команды DAS, но с XLAT можно осущертвить любые преобразования такого рода.

Команда ' Назначение Процессор LEA приемник,источник Вычисление эффективного адреса Вычисляет эффективный адрес источника (переменная) и помещает его в при емник (регистр). С помощью LEA можно вычислить адрес переменной, которая описана сложным методом адресации, например по базе с индексированием. Если адрес - 32-битный, а регистр-приемник - 16-битный, старшая половина вычис ленного адреса теряется, если наоборот, приемник - 32-битный, а адресация 16-битная, то вычисленное смещение дополняется нулями.

Команду LEA часто используют для быстрых арифметических вычисле ний, например умножения:

bx,[ebx+ebx*4] ;

ВХ = ЕВХ х lea или сложения:

lea ebx,[eax+12] ;

ЕВХ = ЕАХ+ (эти команды меньше, чем соответствующие MOVu ADD, и не изменяют флаги) 23.2. Двоичная арифметика Все команды этого раздела, кроме команд деления и умножения, изменяют флаги OF, SF, ZF, AF, CF, PF в соответствии с назначением каждого из них (см.

раздел 2.1.4).

Команда Назначение Процессор ADD приемник.источник Сложение Команда выполняет арифметическое сложение приемника и источника, поме щает сумму в приемник, не изменяя содержимое источника. Приемник может быть регистром или переменной, источник - числом, регистром или переменной, но нельзя использовать переменную одновременно и для источника, и для при емника. Команда ADD никак не различает числа со знаком и без знака, но, упот ребляя значения флагов CF (перенос при сложении чисел без знака), OF (пере нос при сложении чисел со знаком) и SF (знак результата), разрешается применять ее и для тех, и для других.

Команда Назначение Процессор ADC приемник.источник Сложение с переносом Эта команда аналогична ADD, но при этом выполняет арифметическое сложе ние приемника, источника и флага CF. Пара команд ADD/ADC используется для Непривилегированные команды | !

сложения чисел повышенной точности. Сложим, например, два 64-битных целых числа. Пусть одно из них находится в паре регистров ЕрХ:ЕАХ (младшее двой ное слово (биты 0-31) - в ЕАХ и старшее (биты 32-63) - в EDX), а другое - в паре регистров ЕВХ:ЕСХ:

add еах.есх adc edx.ebx Если при сложении младших двойных слов произошел перенос из старшего разряда (флаг CF = 1), то он будет учтен следующей командой ADC.

Команда Назначение Процессор XADD приемник,источник Обменять между собой и сложить Выполняет сложение, помещает содержимое приемйика в источник, а сумму операндов - в приемник. Источник - всегда регистр, приемник может быть регист ром и переменной.

Назначение Команда Процессор SUB приемник,источник Вычитание Вычитает источник из приемника и помещает разнс >сть в приемник. Прием ник может быть регистром или переменной, источник - числом, регистром или переменной, но нельзя использовать переменную одновременно и для источника, и для приемника. Точно так же, как и команда ADD, ! 5UB не делает различий между числами со знаком и без знака, но флаги позволяет использовать ее и для тех, и для других.

Назначение Процессор Команда SBB приемник, источник Вычитание с займом Эта команда аналогична SUB, но она вычитает из приемника значение источ пика и дополнительно вычитает значение флага СЕ Ее можно использовать для вычитания 64-битных чисел в EDX:EAX и ЕВХ:ЕСХ аналогично ADD/ADC:

еах.есх sub edx.ebx sbb Если при вычитании младших двойных слов произошел заем, то он будет уч тен при вычитании старших слов.

Процессор Назначение Команда Умножение чисел со знаком IMUL источник IMUL приемник,источник IMUL приемник.источник!,источник ЩЩЦ;

Процессоры Intel з реальном режиме Эта команда имеет три формы, различающиеся числом операндов:

1. IMUL источник: источник (регистр или переменная) умножается на AL, АХ или ЕАХ (в зависимости от размера операнда), и результат располагается в АХ, DX:AX или EDX:EAX соответственно.

2. IMUL приемник.источник: источник (число, регистр или переменная) ум ножается на приемник (регистр), и результат заносится в приемник.

3. IMUL приемник,источник!,источник2: источник 1 (регистр или переменная) умножается на источник 2 (число), и результат заносится в приемник (регистр).

Во всех трех вариантах считается, что результат может занимать в два раза больше места, чем размер источника. В первом случае приемник автоматически оказывается очень большим, но во втором и третьем случаях существует вероят ность переполнения и потери старших битов результата. Флаги OF и CF будут равны единице, если это произошло, и нулю, если результат умножения помес тился целиком в приемник (во втором и третьем случаях) или в младшую поло вину приемника (в первом случае).

Значения флагов SF, ZF, AF и PF после команды IMUL не определены.

Команда Назначение Процессор MUL источник Умножение чисел без знака ' Выполняет умножение содержимого источника (регистр или переменная) и ре гистра AL, АХ, ЕАХ (в зависимости от размера источника) и помещает результат в АХ, DX:AX, EDX.-EAX соответственно. Если старшая половина результата (АН, DX, EDX) содержит только нули (результат целиком поместился в младшую половину), флаги CF и OF устанавливаются в 0, иначе - в 1. Значение остальных флагов (SF, ZF, AF и PF) не определено.

Команда Назначение Процессор IDIV источник Целочисленное деление со знаком Выполняет целочисленное деление со знаком AL, АХ или ЕАХ (в зависимос ти от размера источника) на источник (регистр или переменная) и помещает ре зультат в AL, АХ или ЕАХ,.а остаток - в АН, DX или EDX соответственно. Ре зультат всегда округляется в сторону нуля, знак остатка совпадает со знаком делимого, абсолютное значение остатка меньше абсолютного значения делителя.

Флаги CF, OF, SF, ZF, AF и PF после этой команды не определены, а переполне ние или деление на ноль вызывает исключение #DE (ошибка при делении) в за щищенном режиме и прерывание О - в реальном.

Команда Назначение Процессор DIV источник Целочисленное деление без знака Выполняет целочисленное деление без знака AL, АХ или ЕАХ (в зависимости от размера источника) на источник (регистр или переменная) и помещает результат в AL, АХ или ЕАХ, а остаток - в АН, DX или EDX соответственно. Результат всегда r Непривилегированные команды f*| округляется в сторону нуля, абсолютное значение остатка меньше абсолютного значения делителя. Флаги CF, OF, SF, ZF, AF и PF после этой команды не опреде лены, а переполнение или деление на ноль вызывает исключение #DE (ошибка при делении) в защищенном режиме и прерывание О - в реальном.

Команда Назначение Процессор INC приемник Инкремент Увеличивает приемник (регистр или переменная) на 1. Единственное отличие этой команды от ADD приемник,! состоит в том, что флаг CF не затрагивается.

Остальные арифметические флаги (OF, SF, ZF, AF, PF) устанавливаются в соот ветствии с результатом сложения.

Команда Назначение Процессор DEC приемник Декремент Уменьшает приемник (регистр или переменная) на 1. Единственное отличие этой команды от SUB приемник,! заключается в том, что флаг CF не затрагивает ся. Остальные арифметические флаги (OF, SF, ZF, AF, PF) устанавливаются в со ответствии с результатом вычитания.

Команда Назначение Процессор NEG приемник Изменение знака Выполняет над числом, содержащимся в приемнике (регистр или переменная), операцию дополнения до двух. Эта операция эквивалентна обращению знака опе ранда, если рассматривать его как число со знаком. Если приемник равен нулю, флаг CF устанавливается в 0, иначе - в 1. Остальные флаги (OF, SF, ZF, AF, PF) назначаются в соответствии с результатом операции.

Красивый пример использования команды NEG - получение абсолютного значения числа, применяя всего две команды - изменение знака и переход на первую команду еще раз, если знак отрицательный:

labelO: neg eax js labelO Команда Назначение Процессор СМР приемник,источник Сравнение Сравнивает приемник и источник и устанавливает флаги. Действие осуществ ляется путем вычитания источника (число, регистр или переменная) из прием ника (регистр или переменная;

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

Единственным следствием работы этой команды оказывается изменение флагов CF, OF, SF, ZF, AF и PF. Обычно команду СМР используют вместе с командами условного перехода (Jcc), условной пересылки данных (CMOVcc) или условной ИН „ Процессоры Intel в реальном режиме установки байтов (SETcc), которые позволяют применить результат сравнения, не обращая внимания на детальное значение каждого флага. Так, команды CMOVE, JE и SETE выполнят соответствующие действия, если значения операндов пред шествующей команды СМР были равны.

Несмотря на то что условные команды почти всегда вызываются сразу после СМР, не надо забывать, что их можно использовать после любой ко манды, модифицирующей флаги, например: проверить равенство АХ нулю более короткой командой test ax,ax а равенство единице - однобайтной командой dec ax Команда Назначение Процессор CMPXCHG приемник, источник Сравнить и обменять между собой Сравнивает значения, содержащиеся в AL, АХ, ЕАХ (в зависимости от разме ра операндов), с приемником (регистром). Если они равны, информация из ис точника копируется в приемник и флаг ZF устанавливается в 1, в противном слу чае содержимое приемника копируется в AL, АХ, ЕАХ и флаг ZF устанавливается в 0. Остальные флаги определяются по результату операции сравнения, как после СМР. Источник - всегда регистр, приемник может быть регистром и переменной.

Команда Назначение Процессор CMPXCHG8B приемник Сравнить и обменять 8 байт Р Выполняет сравнение содержимого регистров EDX:EAX как 64-битного чис ла (младшее двойное слово - в ЕАХ, старшее - в EDX) с приемником (8-байтная переменная в памяти). Если они равны, содержимое регистров ЕСХ:ЕВХ как 64-битное число (младшее двойное слово в ЕВХ, старшее - в ЕСХ) помещается в приемник. В противном случае содержимое приемника копируется в EDX:EAX.

2.3.3. Десятичная арифметика Процессоры Intel поддерживают операции с двумя форматами десятичных чисел:

неупакованное двоично-десятичное число - байт, принимающий значения от до 09h, и упакованное двоично-десятичное число - байт, принимающий значения от 00 до 99h. Все обычные арифметические операции над такими числами приво дят к неправильным результатам. Например, если увеличить 19h на 1, то полу чится число lAh, а не 20h. Для коррекции результатов арифметических действий над двоично-десятичными числами используются приведенные ниже команды.

Команда Назначение Процессор DAA BCD-коррекция после сложения Если эта команда выполняется сразу после ADD (ADC, INC или XADD) и в ре гистре AL находится сумма двух упакованных двоично-десятичных чисел, то в AL Непривилегированные команды записывается упакованное двоично-десятичное число, которое должно было стать результатом сложения. Например, если AL содержит число 19h, последова тельность команд inc al daa приведет к тому, что в AL окажется 20h (а не 1 Ah, как было бы после INC).

DAA выполняет следующие действия:

1. Если младшие четыре бита AL больше 9 или флаг AF = 1, то AL увеличивается на 6, CFустанавливается, если при этом сложении произошел перенос, и AF устанавливается в 1.

2. Иначе AF = 0.

3. Если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL увеличивается на 60h и CF устанавливается в 1.

4. Иначе CF = 0.

Флаги AF и CF устанавливаются, если в ходе коррекции происходил перенос из первой или второй цифры. SF, ZF и PF устанавливаются в соответствии с ре зультатом, флаг OF не определен.

Команда Назначение Процессор DAS BCD-коррекция после вычитания Если эта команда выполняется сразу после SUB (SBB или DEC) и в регистре AL находится разность двух упакованных двоично-десятичных чисел, то в AL записыва ется упакованное двоично-десятичное число, которое должно было быть результатом вычитания. Например, если AL содержит число 20h, последовательность команд dec al das приведет к тому, что в регистре окажется 19h (а не IFh, как было бы после DEC).

DAS выполняет следующие действия:

1. Если младшие четыре бита AL больше 9 или флаг AF = 1, то AL уменьшается на 6, CFустанавливается, если при этом вычита нии произошел заем, и AF устанавливается в 1.

2.ИначаАР = 0.

3. Если теперь старшие четыре бита AL больше 9 или флаг CF — 1, то AL уменьшается на 60h и CF устанавливается в 1.

4. Иначе CF = 0.

Известный пример необычного использования этой команды ~ самый ком пактный вариант преобразования шестнадцатеричной цифры в ASCII-код соответствующего символа (более длинный и очевидный вариант этого преобразования рассматривался в описании команды XLAT):

стр al, sbb al,69h das Процессоры Intel в реальном режиме После SBB числа 0-9 превращаются в 96h - 9Fh, а числа OAh - OFh в OA1h - OA6h. Затем DAS вычитает 66h из первой группы чисел, переводя их в 30h - 39h, и 60h из второй группы чисел, переводя их в 41 h — 46h.

Флаги AF и CF устанавливаются, если в ходе коррекции происходил заем из первой или второй цифры. SF, ZF и PF устанавливаются в соответствии с резуль татом, флаг OF не определен.

Команда Назначение Процессор ASCII-коррекция после сложения АДА Корректирует сумму двух неупакованных двоично-десятичных чисел в AL.

Если коррекция приводит к десятичному переносу, АН увеличивается на 1. Эту команду лучше использовать сразу после команды сложения двух таких чисел.

Например, если при сложении 05 и 06 в АХ окажется число OOOBh, то команда ААА скорректирует его в OlOlh (неупакованное десятичное 11). Флаги CF и OF устанавливаются в 1, если произошел перенос из AL в АН, в противном случае они равны нулю. Значения флагов OF, SF, ZF и PF не определены.

Команда Назначение Процессор ASCII-коррекция после вычитания AAS Корректирует разность двух неупакованных двоично-десятичных чисел в AL сразу после команды SUB или SBB. Если операция приводит к займу, АН уменьша ется на 1. Флаги CF и OF устанавливаются в 1, если произошел заем из AL в АН, и в ноль - в противном случае. Значения флагов OF, SF, ZF и PF не определены.

Команда Назначение Процессор ASCII-коррекция после умножения ДАМ Корректирует результат умножения неупакованных двоично-десятичных чисел, который находится в АХ после выполнения команды MUL, преобразовывая полу ченное в пару неупакованных двоично-десятичных чисел (в АН и AL). Например:

mov al, mov bl,5 ;

Умножить 5 на 5.

mul Ы ;

Результат в АХ - 0019h.

aam ;

Теперь АХ содержит 0205h.

ААМ устанавливает флаги SF, ZF и PF в соответствии с результатом и остав ляет OF, AF и CF неопределенными.

Код команды ААМ - D4h OAh, где OAh - основание системы счисления, по отношению к которой выполняется коррекция. Этот байт можно заме нить на любое другое число (кроме нуля), и ААМ преобразует АХ к двум не упакованным цифрам любой системы счисления. Такая обобщенная форма ААМ работает на всех процессорах (начиная с 8086), но появляется в доку ментации Intel только с процессоров Pentium. Фактически действие, кото рое выполняет ААМ, - целочисленное деление AL на OAh (или любое другое Непривилегированные команды число в общем случае), частное помещается в АН, и остаток - в AL, поэто му команду часто используют для быстрого деления в высокооптимизиро ванных алгоритмах.

Команда Назначение Процессор ASCII-коррекция перед делением AAD Выполняет коррекцию неупакованного двоично-десятичного числа, находяще гося в регистре АХ, так, чтобы последующее деление привело к десятичному ре зультату. Например, разделим десятичное 25 на 5:

mov ax,0205h ;

25 в неупакованном формате, mov Ы, aad ;

Теперь в АХ находится I9h.

div Ы ;

АХ = 0005.

Флаги SF, ZF и PF устанавливаются в соответствии с результатом, OF, AF и CF не определены.

Команда AAD, как и ААМ, используется с любой системой счисления: ее код D5h 0Ah, и второй байт можно заменить на любое другое число. Действие AAD заключается в том, что содержимое регистра АН умножается на второй байт команды (0Ah no умолчанию) и складывается с AL, после чего АН обнуляется, так что AAD можно использовать для быстрого умноже ния на любое число.

2.3А. Логические операции Команда Назначение Процессор AND приеК/шик.источник Логическое И Команда выполняет побитовое «логическое И» над приемником (регистр или переменная) и источником (число, регистр или переменная;

источник и прием ник не могут быть переменными одновременно) и помещает результат в прием ник. Любой бит результата равен 1, только если соответствующие биты обоих операндов были равны 1, и равен 0 в остальных случаях. Наиболее часто AND применяют для выборочного обнуления отдельных битов. Например, команда and а1,00001111Ь обнулит старшие четыре бита регистра AL, сохранив неизменными четыре младших.

Флаги OF и CF обнуляются, SF, ZF и PF устанавливаются в соответствии с ре зультатом, AF не определен.

Команда Назначение Процессор OR приемник.источник Логическое ИЛИ Выполняет побитовое «логическое ИЛИ» над приемником (регистр или пере менная) и источником (число, регистр или переменная;

источник и приемник не •i Процессоры Intel в реальном режиме могут быть переменными одновременно) и помещает результат в приемник. Любой бит результата равен 0, только если соответствующие биты обоих операндов были равны 0, и равен 1 в остальных случаях. Команду OR чаще всего используют для выборочной установки отдельных битов. Например, команда or al,00001111b приведет к тому, что младшие четыре бита регистра AL будут установлены в 1.

При выполнении команды OR флаги OF и CF обнуляются, SF, ZF и PF уста навливаются в соответствии с результатом, AF не определен.

Команда Назначение Процессор XOR приемник.источник Логическое исключающее ИЛИ Выполняет побитовое «логическое исключающее ИЛИ» над приемником (ре гистр или переменная) и источником (число, регистр или переменная;

источник и приемник не могут быть переменными одновременно) и помещает результат в приемник. Любой бит результата равен 1, если соответствующие биты операн дов различны, и нулю - в противном случае. XOR используется для самых раз ных операций, например:

хог ах,ах ;

Обнуление регистра АХ.

или хог ах.Ьх хог Ьх.ах хог ах.Ьх ;

Меняет местами содержимое АХ и ВХ.

Оба примера могут выполняться быстрее, чем соответствующие очевидные команды mov ax,О или xchg ax, их Команда Назначение Процессор NOT приемник Инверсия Каждый бит приемника (регистр или переменная), равный нулю, устанавли вается в 1, и каждый бит, равный 1, сбрасывается в 0. Флаги не затрагиваются.

Команда Назначение Процессор TEST приемник, источник Логическое сравнение Вычисляет результат действия побитового «логического И» над приемником (регистр или переменная) и источником (число, регистр или переменная;

источник и приемник не могут быть переменными одновременно) и устанавливает флаги SF, ZF и PF в соответствии с полученным показателем, не сохраняя результата (фла ги OF и CF обнуляются, значение AF не определено). TEST, так же как и СМР, используется в основном в сочетании с командами условного перехода (Jcc), условной пересылки данных (CMOVcc) и условной установки байтов (SETcc).

Непривилегированные команды 2.3.5. Сдвиговые операции Команда Назначение Процессор SAR приемник.счетчик Арифметический сдвиг вправо SAL приемник.счетчик Арифметический сдвиг влево SHR приемник.счетчик Логический сдвиг вправо SHL приемник.счетчик Логический сдвиг влево Эти четыре команды выполняют двоичный сдвиг приемника (регистр или пере менная) вправо (в сторону младшего бита) или влево (в сторону старшего бита) на значение счетчика (число или регистр CL, из которого учитываются только младшие 5 бит, принимающие значения от 0 до 31). Операция сдвига на 1 экви валентна умножению (сдвиг влево) или делению (сдвиг вправо) на 2. Так, число ООЮЬ (2) после сдвига на 1 влево превращается в ОЮОЬ (4). Команды SAL и SHL выполняют одну и ту же операцию (на самом деле это одна и та же коман да) - на каждый шаг сдвига старший бит заносится в CF, все биты сдвигаются влево на одну позицию, и младший бит обнуляется. Команда SHR осуществляет прямо противоположную операцию: младший бит заносится в CF, все биты сдви гаются на 1 вправо, старший бит обнуляется. Эта команда эквивалентна беззнако вому целочисленному делению на 2. Команда SAR действует по аналогии с SHR, только старший бит не обнуляется, а сохраняет предыдущее значение, вот почему, например, число H l l l l O O b (-4) перейдет в H l l l l l O b (-2). SAR, таким обра зом, эквивалентна знаковому делению на 2, но, в отличие от IDIV, округление происходит не в сторону нуля, а в сторону отрицательной бесконечности. Так, если разделить —9 на 4 с помощью IDIV, получится -2 (и остаток -1), а если вы полнить арифметический сдвиг вправо числа -9 на 2, результатом будет -3. Сдви ги больше 1 эквивалентны соответствующим сдвигам на 1, выполненным после довательно. Схема всех сдвиговых операций приведена на рис. 7.

Сдвиги на 1 изменяют значение флага OF: SAL/SHL устанавливают его в 1, если после сдвига старший бит изменился (то есть старшие два бита исходного числа не были одинаковыми), и в 0, если старший бит остался тем же. SAR уста навливает OF в 0, a SHR -- с значение старшего бита исходного числа. Для сдви гов на несколько битов значение OF не определено. Флаги SF, ZF, PF назначаются SHR 7,15, SAR 7,15, SAL/SHL • CF 7,15, Рис. 7. Сдвиговые операции ;

•. Процессоры Intel в реальном всеми сдвигами в соответствии с результатом, параметр AF не определен (кроме случая, когда счетчик сдвига равен нулю: ничего не происходит и флаги не изме няются).

В процессорах 8086 в качестве второго операнда можно было задавать лишь число 1 и при использовании CL учитывать все биты, а не только младшие 5, но уже начиная с 80186 эти команды приняли свой окончательный вид.

Команда Назначение Процессор SHRD приемник,источник,счетчик Сдвиг повышенной точности вправо SHLD приемник,источник,счетчик Сдвиг повышенной точности влево Приемник (регистр или переменная) сдвигается влево (в случае SHLD) или впра во (в случае SHRD) на число битов, указанное в счетчике (число или регистр CL, откуда используются только младшие 5 бит, принимающие значения от 0 до 31).

Старший (для SHLD) или младший (в случае SHRD) бит не обнуляется, а счи тывается из источника (регистр), значение которого не изменяется. Например, если приемник содержит OOlOlOOlb, источник - 1010Ь, то счетчик равен 3, SHRD даст в результате OlOOOlOlb, a SHLD - 01001 lOlb (см. рис. 8).

источник SHRD приемник 15,31 0 15, SHLD *+ CF -* приемник 15,31 0 15,31 О Рис. 8. Сдвиги двойной точности Флаг OF устанавливается при сдвигах на 1 бит, если изменился знак прием ника, и сбрасывается в противном случае;

при сдвигах на несколько битов флаг OF не определен. Во всех случаях SF, ZF и PF устанавливаются в соответствии с результатом и AF не определен, кроме варианта со сдвигом на 0 бит, в котором значения флагов не изменяются. Если счетчик больше, чем разрядность прием ника, - результат и все флаги не определены.

Команда Назначение Процессор ROR приемник.счетчик Циклический сдвиг вправо ROL приемник.счетчик Циклический сдвиг влево RCR приемник.счетчик Циклический сдвиг вправо через флаг переноса RCL приемник.счетчик Циклический сдвиг влево через флаг переноса Эти команды осуществляют циклический сдвиг приемника (регистр или пе ременная) на число битов, указанное в счетчике (число или регистр CL, из кото рого учитываются только младшие 5 бит, принимающие значения от 0 до 31). При выполнении циклического сдвига на 1 команды ROR (ROL) перемещают каждый бит приемника вправо (влево) на одну позицию, за исключением самого младшего (старшего), который записывается в позицию самого старшего (младшего) бита.

Непривилегированные команд!:

ROR 7,15,31 CF, ROL 7,15, RCR ъ. PF ^ 7,15, с RCL 7,15,31 О Рис. 9. Циклические сдвиги Команды,RCR и RCL выполняют аналогичное действие, но включают флаг CF в цикл, как если бы он был дополнительным битом в приемнике (см. рис. 9).

После выполнения команд циклического сдвига флаг CF всегда равен последне му вышедшему за пределы приемника биту, флаг OF определен только для сдвигов на 1 - он устанавливается, если изменилось значение самого старшего бита, и сбра сывается в противном случае. Флаги SF, ZF, AF и PF не изменяются.

2.3.6. Операции над битами и байтами Назначение Процессор Команда ВТ база,смещение Проверка бита Команда ВТ считывает в флаг CF значение бита из битовой строки, определен ной первым операндом - битовой базой (регистр или переменная), со смещением, указанным во втором операнде - битовом смещении (число или регистр). Когда первый операнд - регистр, то битовой базой считается бит 0 п названном регистре и смещение не может превышать 15 или 31 (в зависимости от размера регистра);

если оно превышает эти границы, в качестве смещения будет использоваться оста ток от деления на 16 или 32 соответственно. Если первый операнд - переменная, то в качестве битовой базы нужен бит 0 указанного байта в памяти, а смещение может принимать значения от 0 до 31, если оно установлено непосредственно (старшие биты процессором игнорируются), и от -231 до 231—1, если оно указано в регистре.

Несмотря на то что эта команда считывает единственный бит из памя ти, а процессор - целое двойное слово по адресу База + (4 х (Смещение/ 32)) или слово по адресу База + (2 х (Смещение/16)), в зависимости от разрядности адреса, все равно не ся*дует пользоваться ВТ вблизи от недо ступных для чтения областей памяти.

Процессоры Intel в реальном режиме После выполнения команды ВТ флаг CF равен значению считанного бита, флаги OF, SF, ZF, AF и PF не определены..

Команда Назначение Процессор BTS база.смещение Проверка и установка бита BTR база,смещение Проверка и сброс бита ВТС база,смещение Проверка и инверсия бита Эти три команды соответственно устанавливают в 1 (BTS), сбрасывают в О (ВТК) и инвертируют (ВТС) значение бита, который находится в битовой строке с началом, определенным в базе (регистр или переменная), и смещением, указан ным во втором операнде (число от 0 до 31 или регистр). Если битовая база - ре гистр, то смещение не может превышать 15 или 31 в зависимости от разрядности этого регистра. Если битовая база - переменная в памяти, то смещение может принимать значения от —231 до 231—1 (при условии, что оно указано в регистре).

После выполнения команд BTS, BTR и ВТС флаг CF равен значению считан ного бита до его изменения в результате действия команды, флаги OF, SF, ZF, AF и PF не определены.

Команда Назначение Процессор BSF приемник,источник Прямой поиск бита BSR приемник,источник Обратный поиск бита BSF сканирует источник (регистр или переменная), начиная с самого младшего бита, и записывает в приемник (регистр) номер первого встретившегося бита, рав ного 1. Команда BSR сканирует источник, начиная с самого старшего бита, и воз вращает номер первого встретившегося ненулевого бита, считая от нуля. То есть, если источник равен 0000 0000 0000 ООЮЬ, то BSF возвратит 1, a BSR - 14.

Если весь источник равен нулю, значение приемника не определено и флаг ZF устанавливается в 1, иначе ZF всегда сбрасывается. Флаги CF, OF, SF, AF и PF не определены.

Команда Назначение Процессор SETcc приемник Установка байта по условию Это набор команд, устанавливающих приемник (8-битный регистр или пере менная размером в 1 байт) в 1 или 0, если удовлетворяется или не удовлетворяется определенное условие. Фактически в каждом случае проверяется состояние тех или иных флагов, но, когда команда из набора SETcc используется сразу после СМР, условия приобретают формулировки, соответствующие отношениям меж ду операндами СМР (см. табл. 6). Скажем, если операнды СМР были неравны, то команда SETNE, выполненная сразу после СМР, установит значение своего опе ранда в 1.

Слова «выше» и «ниже» в таблице относятся к сравнению чисел без знака, слова «больше» и «меньше» учитывают знак.

Непривилегированные команды a Таблица 6. Команды SETcc Реальное условие Условие для CMP Код команды Если выше SETA CF = 0 и ZF = Если не ниже и не равно SETNBE Если выше или равно SETAE CF = 0 Если не ниже SETNB Если нет переноса SETNC Если ниже SETB Если не выше и не равно CF= SETNAE Если перенос SETC Если ниже или равно SETBE CF = 1 или ZF = Если не выше SETNA Если равно SETE ZF= Если ноль SETZ Если больше SETG ZF = 0 и SF = OF Если не меньше и не равно SETNLE Если больше или равно SETGE SF = OF Если не меньше SETNL Если меньше SETL SF 0 OF Если не больше и не равно SETNGE Если меньше или равно SETLE ZF = 1 или SF <> OF Если не больше SETNG Если не равно SETNE ZF = Если не ноль SETNZ Если нет переполнения OF = SETNO OF=1 Если есть переполнение SETO Если нет четности SETNP PF = Если нечетное SETPO Если есть четность SETP PF= Если четное SETPE Если нет знака SF = SETNS Если есть знак SF= SETS 2.3.7. Команды передачи управления Назначение Процессор Команда Безусловный переход JMP операнд SOB JMP передает управление в другую точку программы, не сохраняя какой-либо информации для возврата. Операндом может быть непосредственный адрес для пе рехода (в программах используют имя метки, установленной перед командой, на которую выполняется переход), а также регистр или переменная, содержащая адрес, В зависимости от типа перехода различают:

а переход типа short (короткий переход) - если адрес перехода находится в пре делах -128...+ 127 байт от команды JMP;

Процессоры Intel в реальном режиме I а переход типа near (ближний переход) - если адрес перехода находится в том же сегменте памяти, что и команда JMP;

Q переход типа far (дальний переход) - если адрес перехода находится в дру гом сегменте. Дальний переход может выполняться и в тот же самый сегмент при условии, что в сегментной части операнда указано число, совпадающее с текущим значением CS;

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

При выполнении переходов типа short и'near команда JMP фактически преоб разовывает значение регистра EIP (или IP), изменяя тем самым смещение следу ющей исполняемой команды относительно начала сегмента кода. Если операнд регистр или переменная в памяти, то его показатель просто копируется в EIP, как если бы это была команда MOV. Если операнд для JMP - непосредственно ука занное число, то его значение суммируется с содержимым EIP, приводя к относи тельному переходу. В ассемблерных программах в качестве операнда обычно указывают имена меток, но на уровне исполняемого кода ассемблер вычисляет и записывает именно относительные смещения.

Выполняя дальний переход в реальном, виртуальном и защищенном режимах (при переходе в сегмент с теми же привилегиями), команда JMP просто загружа ет новое значение в EIP и новый селектор сегмента кода в CS, используя старшие 16 бит операнда как новое значение для CS и младшие 16 или 32 бит в качестве значений IP или EIP.

Команда Назначение Процессор Jcc метка Условный переход Это набор команд, выполняющих переход (типа short или near), если удовлет воряется соответствующее условие, которым в каждом случае реально является состояние тех или иных флагов. Но, когда команда из набора Jcc используется сразу после СМР, условия приобретают формулировки, соответствующие отно шениям между операндами СМР (см. табл. 7). Например, если операнды СМР были равны, то команда JE, выполненная сразу после СМР, осуществит переход.

Операнд для всех команд из набора Jcc - 8-битное или 32-битное смещение отно сительно текущей команды.

Слова «выше» и «ниже» в таблице относятся к сравнению чисел без знака;

сло ва «больше» и «меньше» учитывают знак.

Команды Jcc не поддерживают дальних переходов, поэтому, если требуется вы полнить условный переход на дальнюю метку, необходимо использовать команду из набора Jcc с обратным условием и дальний JMP, как, например:

стр ах,О jne local_ jmp far_label ;

Переход, если АХ = 0.

local 1:

Непривилегированные команды Таблица 7. Варианты команды Jcc Код команды Реальное условие Условие для CMP JA Если выше CF = 0 и ZF = JBE Если не ниже и не равно JAE Если выше или равно JNB Если не ниже CF = Если нет переноса JNC JB Если ниже JNAE CF=1 Если не выше и но равно JC Если перенос Если ниже или равно JBE CF = 1 или ZF = Если не выше JNA JE Если равно ZF= Если ноль JZ Если больше JG ZF = 0 и SF = OF JNLE Если не меньше и не равно JGE Если больше или равно SF = OF JNL Если не меньше JL Если меньше SF 0 OF JNGE Если не больше и не равно Если меньше или равно JLE ZF = 1 или SF 0 OF Если не больше JNG Если не равно JNE ZF = Если не ноль JNZ Если нет переполнения OF = JNO OF=1 Если есть переполнение JO Если нет четности JNP PF = Если нечетное JPO Если есть четность JP PF= Если четное JPE Если нет знака SF = JNS Если есть знак SF= JS Назначение Процессор Команда Переход, если СХ - 0 JCXZ метка Переход, если ЕСХ = JECXZ метка Выполняет ближний переход на указанную метку, если регистр СХ или ЕСХ (для JCXZ и JECXZ соответственно) равен нулю. Так же как и команды из серии Jcc, JCXZ и JECXZ не могут выполнять дальних переходов. Проверка равенства СХ нулю, например, может потребоваться в начале цикла, организованного ко мандой LOOPNE, - если в него войти с СХ = 0, то он будет выполнен 65 535 раз.

Команда Назначение Процессор Цикл LOOP метка Процессоры Intel в реальном режиме Уменьшает регистр ЕСХ на 1 и выполняет переход типа short на метку (кото рая не может быть дальше расстояния -128...+ 127 байт от команды ЮОР), если ЕСХ не равен нулю. Эта команда используется для организации циклов, в кото рых регистр ЕСХ (или СХ при 16-битной адресации) играет роль счетчика. Так, в следующем фрагменте команда ADD выполнится 10 раз:

mov cx.OAh loop_start:

add ax.cx loop loop_start Команда LOOP полностью эквивалентна паре команд dec ecx jnz метка Но LOOP короче этих двух команд на один байт и не изменяет значения флагов.

Команда Назначение Процессор LOOPE метка ' Цикл, пока равно LOOPZ метка • Цикл, пока ноль LOOPNE метка Цикл, пока не равно LOOPNZ метка Цикл, пока не ноль Все перечисленные команды уменьшают регистр ЕСХ на один, после чего вы полняют переход типа short, если ЕСХ не равен нулю и если выполняется условие.

Для команд ШОРЕ и LOOPZ условием является равенство единице флага ZF, для команд LOOPNE и LOOPNZ - равенство флага ZF нулю. Сами команды LOOPcc не изменяют значений флагов, так что ZF должен быть установлен (или сброшен) предшествующей командой. Например, следующий фрагмент копирует строку из DS:SI в строку в ES:DI (см. описание команд работы со строками), пока не кончится строка (СХ = 0) или пока не встретится символ с ASCII-кодом 13 (конец строки):

mov cx,str_length move_loop:

lodsb stosb cmp al, loopnz move_loop Команда Назначение Процессор CALL операнд Вызов процедуры Сохраняет текущий адрес в стеке и передает управление по адресу, указанно му в операнде. Операндом может быть непосредственное значение адреса (метка в ассемблерных программах), регистр или переменная, содержащие адрес пере хода. Если в качестве* адреса перехода указано только смещение, считается, что адрес расположен в том же сегменте, что и команда CALL. При этом, так же как и в случае с JMP, выполняется ближний вызов процедуры. Процессор помещает значение регистра EIP (IP при 16-битной адресации), соответствующее следую щей за CALL команде, в стек и загружает ь EIP новое значение, осуществляя тем Непривилегированные команды,/;

самым передачу управления. Если операнд CALL - регистр или переменная, то его значение рассматривается как абсолютное смещение, если операнд - ближ няя метка в программе, то ассемблер указывает ее относительное смещение. Что бы выполнить дальний CALL в реальном режиме, режиме V86 или в защищен ном режиме при переходе в сегмент с теми же привилегиями, процессор помещает в стек значения регистров CS и EIP (IP при 16-битной адресации) и осуществляет дальний переход аналогично команде JMP.

Команда Назначение Процессор RET число Возврат из процедуры RETN число RETF число RETN считывает из стека слово (или двойное слово, в зависимости от режима адресации) и загружает его в IP (или EIP), выполняя тем самым действия, обрат ные ближнему вызову процедуры командой CALL. Команда RETF загружает из стека IP (EIP) и CS, возвращаясь из дальней процедуры. Если в программе указа на команда RET, ассемблер заменит ее на RETN или RETF в зависимости от того, как была описана процедура, которую эта команда завершает. Операнд для RET необязателен, но, если он присутствует, после считывания адреса возврата из сте ка будет удалено указанное количество байтов - это нужно, если при вызове про цедуры ей передавались параметры через стек.

Команда Назначение Процессор INT число Вызов прерывания INT аналогично команде CALL помещает в стек содержимое регистров EFLAGS, CS и EIP, после чего передает управление программе, называемой обработчиком прерываний с указанным в качестве операнда номером (число от 0 до OFFh). В ре альном режиме адреса обработчиков прерываний считываются из таблицы, начи нающейся в памяти по адресу 0000h:0000h. Адрес каждого обработчика занимает 4 байта, вот почему, например, обработчик прерывания 10h находится в памяти по адресу 0000h:0040h. В защищенном режиме адреса обработчиков прерываний находятся в таблице IDT и обычно недоступны для прямого чтения или записи, так что для установки собственного обработчика программа должна обращаться к операционной системе. В DOS вызовы прерываний используются для выполне ния большинства системных функций - работы с файлами, вводом/выводом и т. д. Например, следующий фрагмент кода завершает выполнение программы и возвращает управление DOS:

mov ax,4C01h int 21h Команда Назначение Процессор Возврат из обработчика прерывания IRET IRETD i;

Процессоры intel в реальном режиме Возврат управления из обработчика прерывания или исключения. IRET за гружает из стека значения IP, CS и FLAGS, a IRETD - EIP, CS и EFLAGS соот ветственно. Единственное отличие IRET от RETF состоит в том, что значение ре гистра флагов восстанавливается, из-за чего многим обработчикам прерываний приходится изменять величину EFLAGS, находящегося в стеке, чтобы, например, вернуть флаг CF, установленный в случае ошибки.

Команда Назначение Процессор Вызов прерывания 3 INT Размер этой команды - один байт (код OCCh), что делает ее удобной для до водки программ отладчиками, работающими в реальном режиме. Они записыва ют этот байт вместо первого байта команды, перед которой требуется точка оста нова, и переопределяют адрес обработчика прерывания 3 на соответствующую процедуру внутри отладчика.

Команда Назначение. Процессор Вызов прерывания 4 при переполнении INTO INTO - еще одна специальная форма команды INT. Она вызывает обработчик прерывания 4, если флаг OF установлен в 1.

Команда Назначение Процессор BOUND индекс,границы Проверка выхода за границы массива BOUND проверяет, не выходит ли значение первого операнда (регистр), взя тое как число со знаком, за границы, указанные во втором операнде (переменная).

Границы - два слова или двойных слова (в Зависимости от разрядности операн дов), рассматриваемые как целые со знаком и расположенные в памяти подряд.

Первая граница считается нижней, вторая - верхней. Если индекс меньше ниж ней границы или больше верхней, вызывается прерывание 5 (или исключение #BR), причем адрес возврата указывает не на следующую команду, а на BOUND, так что обработчик должен исправить значение индекса или границ, прежде чем выполнять команду IRET.

Команда Назначение Процессор ENTER размер.уровень Вход в процедуру Команда ENTER создает стековый кадр заданного размера и уровня вложен ности (оба операнда - числа;

уровень вложенности может принимать значения только от 0 до 31) с целью вызова процедуры, использующей динамическое рас пределение памяти в стеке для своих локальных переменных. Так, команда enter 2048, помещает в стек указатели на стековый кадр текущей процедуры и той, из кото рой вызывалась текущая, создает стековый кадр размером 2 Кб для вызыве.~мой Непривилегированные команды процедуры и помещает в ЕВР адрес начала кадра. Пусть процедура MAIN имеет уровень старый ЕВР • ЕВР вложенности 0, процедура PROCA запускает ЕВР для MAIN ся из MAIN и имеет уровень вложенности 1, и PROCB запускается из PROCA с уровнем локальные вложенности 2. Тогда стек при входе в проце- переменные дуру МАШ имеет вид, показанный на рис. 10. для MAIN •ESP Теперь процедура МАШ может определять свои локальные переменные в памяти, исполь Рис. 10. Стековый кадр зуя текущее значение ЕВР.

процедуры нулевого уровня На первом уровне вложенности процедура (MAIN) PROCA, как показано на рис. 11, может созда вать свои локальные переменные, применяя текущее значение ЕВР, и получит до ступ к локальным переменным процедуры МАШ, используя значение ЕВР для МАШ, помещенное в стек командой ENTER.

Процедура PROCB на втором уровне вложен ности (см. рис. 12) получает доступ как к локаль ным переменным процедуры PROCA, применяя значение ЕВР для PROCA, так и к локальным переменным процедуры МАШ, используя зна чение ЕВР для МАШ.

старый ЕВР ЕВР для MAIN локальные переменные для MAIN ЕВР ЕВР ЕВР для MAIN ЕВР для MAIN ЕВР для PROCA локальные переменные ESP для PROCA ESP Рис. 12. Стековый кадр процедуры Рис. 11. Стековый кадр процедуры первого уровня (PROCA) второго уровня (PROCB) Назначение Команда Процессор Выход из процедуры LEAVE Команда выполняет действия, противоположные команде ENTER. Фактически LEAVE только копирует содержимое ЕВР в ESP, тем самым выбрасывая из стека I Процессоры Intel в реальном режиме весь кадр, созданный последней выполненной командой ENTER, и считывает из стека ЕВР для предыдущей процедуры, что одновременно восстанавливает и зна чение, которое имел ESP до вызова последней команды ENTER.

2.3.8. Строковые операции Все команды для работы со строками считают, что строка-источник находится по адресу DS:SI (или DS:ESI), то есть в сегменте памяти, указанном в DS Со сме щением в SI, а строка-приемник - соответственно в ES:DI (или ES:EDI). Кроме того, все строковые команды работают только с одним элементом строки (байтом, словом или двойным словом) за один раз. Для того чтобы команда выполнялась над всей строкой, необходим один из префиксов повторения операций.

Команда Назначение Процессор REP Повторять Повторять, пока равно REPE Повторять, пока не равно REPNE Повторять, пока ноль REPZ Повторять, пока не ноль REPNZ Все перечисленные команды являются префиксами для операций над строка ми. Любой из префиксов выполняет следующую за ним команду строковой обра ботки столько раз, сколько указано в регистре ЕСХ (или СХ, в зависимости от разрядности адреса), уменьшая его при каждом выполнении команды на 1. Кроме того, REPZ и REPE прекращают повторения команды, если флаг ZF сброшен в О, a REPNZ и REPNE прекращают повторения, если флаг ZF установлен в 1. Пре фикс REP обычно используется с командами INS, OUTS, MOVS, LODS, STOS, а префиксы REPE, REPNE, REPZ и REPNZ - с командами CMPS и SCAS. Пове дение префиксов в других случаях не определено.

Команда Назначение Процессор MOVS приемник.источник Копирование строки Копирование строки байтов MOVSB Копирование строки слов MOVSW Копирование строки двойных слов MOVSO Копирует один байт (MOVSB), слово (MOVSW) или двойное слово (MOVSD) из памяти по адресу DS:ESI (или DS:SI, в зависимости от разрядности адреса) в па мять по адресу ES:EDI (или ES:DI). При использовании формы записи MOVS ассемблер сам определяет по типу указанных операндов (принято указывать имена копируемых строк, но можно применять любые два операнда подходящего типа), ка кую из трех форм этой команды (MOVSB, MOVSW или MOVSD) выбрать. Исполь зуя MOVS с операндами, разрешается заменить регистр DS другим с помощью пре фикса замены сегмента (ES:, GS:, FS:, CS:, SS:), регистр ES заменить нельзя. После выполнения команды регистры ESI (или SI) и EDI (или DI) увеличиваются на 1, или 4 (если копируются байты, слова или двойные слова), когда флаг DF = О, Непривилегированные команды и уменьшаются, когда DF = 1. Команда MOVS с префиксом REP выполняет копи рование строки длиной в ЕСХ (или СХ) байтов, слов или двойных слов.

Команда Назначение Процессор CMPS приемник,источник Сравнение строк Сравнение строк байтов CMPSB Сравнение строк слов CMPSW Сравнение строк двойных слов CMPSD Сравнивает один байт (CMPSB), слово (CMPSW) или двойное слово (CMPSD) из памяти по адресу DS:ESI (или DS:SI, в зависимости от разрядности адреса) с бай том, словом или двойным словом по адресу ES:EDI (или ES:DI) и устанавливает флаги аналогично команде СМР. При использовании формы записи CMPS ассемб лер сам определяет по типу указанных операндов (принято указывать имена срав ниваемых строк, но можно использовать любые два операнда подходящего типа), какую из трех форм этой команды (CMPSB, CMPSW или CMPSD) выбрать.

Применяя CMPS с операндами, можно заменить регистр DS другим, воспользо вавшись префиксом замены сегмента (ES:, GS:, FS:, CS:, SS:), регистр ES заменить нельзя. После выполнения команды регистры ESI (или SI) и EDI (или DI) уве личиваются на 1, 2 или 4 (если сравниваются байты, слова или двойные слова), когда флаг DF = 0, и уменьшаются, когда DF = 1. Команда CMPS с префиксами REPNE/REPNZ или REPE/REPZ выполняет сравнение строки длиной в ЕСХ (или СХ) байтов, слов или двойных слов. В первом случае сравнение продолжает ся до первого совпадения в строках, а во втором — до первого несовпадения.

Команда Назначение Процессор SCAS приемник Сканирование строки Сканирование строки байтов SCASB Сканирование строки слов SCASW Сканирование строки двойных слов SCASD Сравнивает содержимое регистра AL (SCASB), AX (SCASW) или ЕАХ (SCASD) с байтом, словом или двойным словом из памяти по адресу ES:EDI (или ES:DI, в за висимости от разрядности адреса) и устанавливает флаги аналогично команде СМР.

При использовании формы записи SCAS ассемблер сам определяет по типу указан ного операнда (принято указывать имя сканируемой строки, но можно использовать любой операнд подходящего типа), какую из трех форм этой команды (SCASE, SCASW или SCASD) выбрать. После выполнения команды регистр EDI (или DI) увеличивается на 1, 2 или 4 (если сканируются байты, слова или двойные слова), когда флаг DF = 0, и уменьшается, когда DF = 1. Команда SCAS с префиксами REPNE/REPNZ или REPE/REPZ выполняет сканирование строки длиной в ЕСХ (или СХ) байтов, слов или двойных слов. В первом случае сканирование продолжа ется до первого элемента строки, совпадающего с содержимым аккумулятора, а во втором - до первого отличного.

Процессоры Intel в реальном режиме Команда Назначение Процессор LODS источник Чтение из строки Чтение байта из строки LODSB Чтение слова из строки LODSW Чтение двойного слова из строки LODSD Копирует один байт (LODSB), слово (LODSW) или двойное слово (LODSD) из памяти по адресу DS:ESI (или DS:SI, в зависимости от разрядности адреса) в регистр AL, АХ или ЕАХ соответственно. При использовании формы записи LODS ассемблер сам определяет по типу указанного операнда (принято указы вать имя строки, но можно использовать любой операнд подходящего типа), ка кую из трех форм этой команды (LODSB, LODSW или LODSD) выбрать. Приме^ няя LODS с операндом, можно заменить регистр DS на другой с помощью префикса замены сегмента (ES:, GS:, FS:, CS:, SS:). После выполнения команды регистр ESI (или SI) увеличивается на 1, 2 или 4 (если считывается байт, слово или двойное слово), когда флаг DF = 0, и уменьшается, когда DF = 1. Команда LODS с префиксом REP выполнит копирование строки длиной в ЕСХ (или СХ), и в аккумуляторе окажется последний элемент строки. На самом деле LODS ис пользуют без префиксов, часто внутри цикла в паре с командой STOS, так что LODS считывает число, другие команды выполняют над ним какие-нибудь дей ствия, а затем STOS записывает измененное число на прежнее место в памяти.

Команда Назначение Процессор STOS приемник Запись в строку Запись байта в строку STOSB Запись слова в строку STOSW Запись двойного слова в строку STOSD Копирует регистр AL (STOSB), AX (STOSW) или ЕАХ (STOSD) в память по адресу ES:EDI (или ES:DI, в зависимости от разрядности адреса). При использо вании формы записи STOS ассемблер сам определяет по типу указанного операн да (принято указывать имя строки, но можно использовать любой операнд под ходящего типа), какую из трех форм этой команды (STOSB, STOSW или STQSD) выбрать. После выполнения команды регистр EDI (или DI) увеличивается на 1, 2 или 4 (если копируется байт, слово или двойное слово), когда флаг DF = О, и уменьшается, когда DF = 1. Команда STOS с префиксом REP заполнит строку длиной в ЕСХ (или СХ) числом, находящимся в аккумуляторе.

Команда Назначение Процессор INS источник, DX Чтение строки из порта Чтение строки байт из порта. INSB INSW Чтение строки слов из порта Чтение строки двойных слов из порта INSD Непривилегированные команды ' tiS Считывает из порта ввода-вывода, номер которого указан в регистре DX, байт (INSB), слово (INSW) или двойное слово (INSD) в память по адресу ES:EDI (или ES:DI, в зависимости от разрядности адреса). При использовании формы записи INS ассемблер определяет по типу указанного операнда, какую из трех форм этой команды (INSB, INSW или INSD) употребить. После выполнения команды ре гистр EDI (или DI) увеличивается на 1, 2 или 4 (если считывается байт, слово или двойное слово), когда флаг DF = 0, и уменьшается, когда DF = 1. Команда INS с префиксом REP считывает блок данных из порта длиной в ЕСХ (или СХ) байтов, слов или двойных слов.

Команда Назначение Процессор Запись строки в порт OUTS DX, приемник OUTSB Запись строки байтов в порт Запись строки слов в порт OUTSW OUTSD Запись строки двойных слов в порт Записывает в порт ввода-вывода, номер которого указан в регистре DX, байт (OUTSB), слово (OUTSW) или двойное слово (OUTSD) из памяти по адресу DS:ESI (или DS:SI, в зависимости от разрядности адреса). При использовании формы записи OUTS ассемблер определяет по типу указанного операнда, какую из трех форм этой команды (OUTSB, OUTSW или OUTSD) употребить. Приме няя OUTS с операндами, также можно заменить регистр DS другим с помощью префикса замены сегмента (ES:, GS:, FS:, CS:, SS:). После выполнения команды регистр ESI (или SI) увеличивается на 1, 2 или 4 (если считывается байт, слово или двойное слово), когда флаг DF = 0, и уменьшается, когда DF = 1. Команда OUTS с префиксом REP записывает блок данных размером в ЕСХ (или СХ) бай тов, слов или двойных слов в указанный порт. Все процессоры до Pentium не про веряли готовность порта принять новые данные в ходе выполнения команды REP OUTS, так что, если порт не успевал обрабатывать информацию с той скорос тью, с которой ее поставляла эта команда, часть данных терялась.

2.3.9. Управление флагами Команда Назначение Процессор Установить флаг переноса STC Устанавливает флаг CF в 1.

Команда Назначение Процессор Сбросить флаг переноса CLC Сбрасывает флаг CF в 0.

Команда Назначение Процессор CMC Инвертировать флаг переноса Процессоры Intel в реальном режиме ЕЭ1Н1Н1Н1Н Инвертирует флаг СЕ Команда Назначение Процессор Установить флаг направления STD Устанавливает флаг DF в 1, так что при последующих строковых операциях регистры DI и SI будут уменьшаться.

Команда Назначение Процессор CLD Сбросить флаг направления Сбрасывает флаг DF в 0, так что при последующих строковых операциях ре гистры DI и SI будут увеличиваться.

Команда Назначение Процессор Загрузить флаги состояния в АН LAHF Копирует младший байт регистра FLAGS в АН, включая флаги SF (бит 7), ZF (бит 6), AF (бит 4), PF (бит 2) и CF (бит 0). Бит 1 устанавливается в 1, биты и 5 - в 0.

Команда Назначение Процессор Загрузить флаги состояния из АН SAHF Загружает флаги SF, ZF, AF, PF и CF из регистра АН значениями битов 7,6,4, и 0 соответственно. Зарезервированные биты 1,3 и 5 регистра флагов не изменяются.

Команда Назначение Процессор Поместить FLAGS в стек PUSHF Поместить EFLAGS в стек PUSHFD Эти команды копируют содержимое регистра FLAGS или EFLAGS в стек (уменьшая SP или ESP на 2 или 4 соответственно). При копировании регистра EFLAGS флаги VM и RF (биты 16 и 17) не копируются, а соответствующие биты в двойном слове, помещенном в стек, обнуляются.

Команда Назначение Процессор Загрузить FLAGS из стека POPF • Загрузить EFLAGS из стека POPFD Считывает из вершины стека слово (POPF) или двойное слово (POPFD) и по мещает в регистр FLAGS или EFLAGS. Эффект этих команд зависит от режима, в котором выполняется программа: в реальном и защищенном режимах с уров нем привилегий 0 модифицируются все незарезервированные флаги в EFLAGS, кроме VIP, VIF и VM. VIP и VIF обнуляются, и VM не изменяется. В защищен ном режиме с уровнем привилегий, большим нуля, но меньшим или ±. >пным Непривилегированные команды IOPL, модифицируются все флаги, кроме VIP, VIF, VM и IOPL. В режиме V86 не модифицируются флаги VIF, VIP, VM, IOPL и RF.

Команда Назначение Процессор CLI Запретить прерывания Сбрасывает флаг IF в 0. После выполнения этой команды процессор игнори рует все прерывания от внешних устройств (кроме NMI). В защищенном режиме эта команда, так же как и все другие команды, модифицирующие флаг IF (POPF или IRET), выполняется, только если программе даны соответствующие приви легии (CPL < IOPL).

Команда Назначение Процессор STI Разрешить прерывания Устанавливает флаг IF в 1, отменяя тем самым действие команды CLI.

Команда Назначение Процессор Установить AL в соответствии с CF SALC Устанавливает AL в OFFh, если флаг CF = 1, и сбрасывает в ООН, если CF = 0. Это недокументированная команда с кодом OD6h, присутствующая во всех процессо рах Intel и совместимых с ними (начиная с 8086). В документации на Pentium Pro команда SALC упоминается в общем списке команд, но ее действие не описывается (оно аналогично SBB AL,AL, однако значения флагов не изменяются).

2.3.10. Загрузка сегментных регистров Команда Назначение Процессор LOS приемник.источник Загрузить адрес, используя DS LES приемник.источник Загрузить адрес, используя ES LFS приемник.источник Загрузить адрес, используя FS LGS приемник.источник Загрузить адрес, используя GS LSS приемник.источник Загрузить адрес, используя SS Второй операнд (источник) для всех этих команд - переменная в памяти раз мером в 32 или 48 бит (в зависимости от разрядности операндов). Первые 16 или 32 бита из этой переменной загружаются в регистр общего назначения, указанный в качестве первого операнда, а следующие 16 бит - в соответствующий сегмент ный регистр (DS для LDS, ES для LES и т. д.). В защищенном режиме значение, загружаемое в сегментный регистр, всегда должно быть правильным селектором сегмента (в реальном режиме любое число может использоваться как селектор).

2.3.11. Другие команды Команда Назначение Процессор NOP Отсутствие операции Процессоры Intel в реальном режиме NOP - однобайтная команда (код 90h), которая не выполняет ничего, только занимает место и время. Код этой команды фактически соответствует XCHG AL,AL. Многие команды разрешается записать так, что они не будут приводить ни к каким действиям, например:

ax, ax байта.

mov Г) 2 байта.

ax, ax xchg 3 байта (8Dh, 5Fh, OOh но многие ассемблеры, bx, [bx+0] lea встретив такую команду, реально используют более короткую lea bx,[bx] с кодом 8Dh 1FH).

4 байта.

shl eax, 5 байт.

eax, eax, shrd Команда Назначение Процессор Префикс блокировки шины данных LOCK На все время выполнения команды, снабженной таким префиксом, будет заб локирована шина данных, и если в системе присутствует другой процессор, он не сможет обращаться к памяти, пока не закончится выполнение команды с префик сом LOCK. Команда XCHG всегда выполняется автоматически с блокировкой до ступа к памяти, даже если префикс LOCK не указан. Этот префикс можно исполь зовать только с командами ADD, ADC, AND, ВТС, ВТК, BTS, CMPXCHG, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD и XCHG.

Команда Назначение Процессор UD2 Неопределенная операция Р Эта команда всегда вызывает ошибку «неопределенная операция» (исключе ние #UD). Впервые она описана как таковая для Pentium Pro, но во всех предыду щих процессорах UD2 (код OFh OBh) не была определена и, естественно, приво дила к такой же ошибке. Команда предназначена для тестирования программного обеспечения, в частности операционных систем, которые должны уметь коррект но обрабатывать такую ошибку. Название команды происходит от команды UD (код OFh OFFh), которая была определена AMD для процессоров AMD K5.

Команда Назначение Процессор Идентификация процессора CPUID CPUID сообщает информацию о производителе, типе и модификации процес сора и о наличии различных расширений. Команда CPUID поддерживается Intel, начиная с процессоров Intel 80486DX/SX/DX2 SL, UMC U5S, Cyrix Ml, AMD 80486DX4. Попробуйте установить флаг ID в 1 (бит 21 в регистре EFLAGS) - если это получается, значит, команда CPUID поддерживается.

Результат работы CPUID зависит от значения регистра ЕАХ. Если ЕАХ = О, CPUID возвращает в ЕАХ максимальное значение, с которым ее можно вызывать (2 для Р6,1 для Р5), а регистры EBX:ECX:EDX содержат 12-байтную строку - иден тификатор производителя (см. табл. 8).

Непривилегированные команды ' Таблица 8. Строки производителей в CPUID Строка в EBX:ECX:EDX Производитель Intel Genuinelntel UMC UMC UMC UMC Cyrix Cyrixlnstead AuthenticAMD AMD NexGen NexGenDriven Centaur Technology CentaurHalls Например, для процессоров Intel регистр ЕВХ содержит Genu (756E654/h), ЕСХ - inel (49656E69h), a EDX - ntel (6C65746Eh).

Если EAX = 1, CPUID возвращает в ЕАХ информацию о версии процессора, а в EDX - сведения о поддерживаемых расширениях. Многие понятия в этом опи сании относятся к работе процессора в защищенном режиме и рассмотрены ниже.

Информация о версии процессора:

Биты 3-0 - модификация.

Биты 7-4 - модель.

Биты 11-8 - семейство (3 для 386,4 для 486,5 для Pentium, 6 для Pentium Pro).

Биты 13-12 - тип (0 - OEM, 1 - Overdrive, 2 - Dual).

Биты 31-14 — зарезервированы и равны нулю.

Поддерживаемые расширения (регистр EDX):

Бит 0: FPU - процессор содержит FPU и может выполнять весь набор команд 80387.

Бит 1: УМЕ - процессор поддерживает усовершенствованный режим V (флаги VIE и VIP в EFLAGS, биты VME и PVI в CRO).

Бит 2: DE - процессор поддерживает точки останова по вводу/выводу, бит DE в CRO.

Бит 3: PSE - процессор поддерживает страницы до 4 Мб, бит PSE в CR4, мо дифицированные биты в элементах списков страниц (РОЕ) и таблиц стра ниц (РТЕ).

Бит 4: TSC - процессор поддерживает команду RDTSC и бит TSC в CR4.

Бит 5: MSR - процессор поддерживает команды RDMSR и WRMSR и машин но-специфичные регистры, совместимые с Pentium.

Бит 6: РАЕ - процессор поддерживает физические адреса больше 32 бит, до полнительный уровень в таблицах трансляции страниц, страницы по 2 Мб и бит РАЕ в CR4. Число битов для физических адресов зависит от модели процессора. Так, Pentium Pro поддерживает 36 бит.

Бит 6: РТЕ (только для Cyrix).

Бит 7: МСЕ - процессор поддерживает бит МСЕ в CR4.

Бит 8: СХ8 - процессор поддерживает команду CMPXCHG8B.

Бит 9: APIC - процессор содержит встроенный контроллер прерываний (APIC), который активизирован и доступен.

Бит 9: PGE (только для AMD).

Процессоры Intei в реальном режиме Бит 10: зарезервирован.

Бит 11: SEP - процессор поддерживает быстрые системные вызовы, команды SYSENTER и SYSEXIT (Pentium II).

Бит 12: MTRR - процессор поддерживает машинно-специфичные реестры MTRR.

Бит 13: PGE - процессор поддерживает бит PGE в CR4 и глобальные флаги в PTDE и РТЕ, указывающие элементы TLB, которые принадлежат сразу нескольким задачам.

Бит 14: МСА - процессор поддерживает машинно-специфичный регистр MCG_CAP.

Бит 15: CMOV - процессор поддерживает команды CMOVcc и (если бит О EDX установлен) FCMOVcc (Pentium Pro).

Бит 16: PAT - процессор поддерживает таблицу атрибутов страниц.

Биты 17-22: зарезервированы.

Бит 23: ММХ - процессор поддерживает набор команд ММХ.

Бит 24: FXSR - процессор поддерживает команды быстрого чтения/записи (ММХ2).

Бит 25: SSE - процессор поддерживает расширения SSE (Pentium III).

Биты 31-26: зарезервированы.

Если ЕАХ = 2, CPUID на процессорах семейства Р6 возвращает в регистрах ЕАХ, ЕВХ, ЕСХ и EDX информацию о кэшах и TLB. Самый младший байт ЕАХ (регистр AL) определяет, сколько раз надо вызвать CPUID с ЕАХ = 2, чтобы полу чить информацию обо всех кэшах (1 для Pentium Pro и Pentium II). Самый старший бит (бит 31) каждого регистра указывает, содержит ли этот регистр правильную ин формацию (бит 31 = 0) или он зарезервирован (бит 31 = 1). В первом случае регистр содержит информацию в 1-байтных дескрипторах со следующими значениями:

OOh - пустой дескриптор;

Olh - TLB команд, 4-килобайтные страницы, 4-сторонняя ассоциативность, 32 элемента;

02h - TLB команд, 4-мегабайтные страницы, 4-сторонняя ассоциативность, 4 элемента;

03h - TLB данных, 4-килобайтные страницы, 4-сторонняя ассоциативность, 64 элемента;

04h - TLB данных, 4-мегабайтные страницы, 4-сторонняя ассоциативность, 8 элементов;

06h - кэш команд, 8 Кб, 4-сторонняя ассоциативность, 32 байта в строке;

08h - кэш команд, 16 Кб, 4-сторонняя ассоциативность, 32 байта в строке;

OAh - кэш данных, 8 Кб, 2-сторонняя ассоциативность, 32 байта в строке;

ОСЬ— кэш данных, 16 Кб, 2-сторонняя ассоциативность, 32 байта в строке;

41h -унифицированный кэш, 128 Кб, 4-сторонняя ассоциативность, 32 байта в строке;

42h - унифицированный кэш, 256 Кб, 4-сторонняя ассоциативность, 32 байта в строке;

43h - унифицированный кэш, 512 Кб, 4-сторонняя ассоциативность, 32 байта в строке;

Числа с плавающей запятой, •:,*« 44h - унифицированный кэш, 1 Мб, 4-сторонняя ассоциативность, 32 байта в строке.

Совместимые с Intel процессоры AMD и Cyrix поддерживают вызов «расши ренных функций» CPUID со значениями ЕАХ, в которых самый старший бит всегда установлен в 1.

ЕАХ = SOOOOOOOh: возвращает в ЕАХ максимальный номер расширенной фун кции CPUID, поддерживаемой данным процессором.

ЕАХ = SOOOOOOlh: возвращает в ЕАХ 051Xh для AMD K5 (X - номер модифи кации) или 061ХН для AMD Кб. В EDX эта функция возвращает информацию о поддерживаемых расширениях (указаны только флаги, отличающиеся от CPUID с ЕАХ = 1).

Бит 5: MSR — процессор поддерживает машинно-специфичные регистры, со вместимые с К5.

Бит 10: процессор поддерживает команды SYSCALL и SYSRET.

Бит 16: процессор поддерживает команды FCMOVcc.

Бит 24: процессор поддерживает ММХ с расширениями от Cyrix.

Бит 25: процессор поддерживает набор команд AMD 3D.

ЕАХ - 80000002h, 80000003h и 80000004h - последовательный вызов CPUID с этими значениями в ЕАХ возвращает в EAX:EBX:ECX:EDX последовательно четыре 16-байтные части строки - имени процессора. Например: AMD-K5(tm) Processor.

ЕАХ = 80000005h - команда возвращает информацию о TLB в регистре ЕВХ (старшее слово — TLB данных, младшее слово — TLB команд, старший байт — ас социативность, младший байт - число элементов), о кэше данных в регистре ЕСХ и о кэше команд в регистре EDX (биты 31-24 - размер в килобайтах, биты 23-16 ассоциативность, биты 15-8 - число линий на тэг, биты 7-0 - число байтов на линию).

2.4. Числа с плавающей запятой В процессорах Intel все операции с плавающей запятой выполняет специаль ное устройство - FPU (Floating Point Unit) - с собственными регистрами и набо ром команд, поставлявшееся сначала в виде сопроцессора (8087, 80287, 80387, 80487), а начиная с 80486DX - встраивающееся в основной процессор. FPU пол ностью соответствует стандартам IEEE 754 и IEEE 854 (с 80486).

2.4.1. Типы данных FPU Числовой процессор может выполнять операции с семью разными типами дан ных, представленными в табл. 9: три целых двоичных, один целый десятичный и три с плавающей запятой.

Вещественные числа хранятся, как и все данные, в форме двоичных чисел.

Двоичная запись числа с плавающей запятой аналогична десятичной, только по зиции справа от запятой соответствуют не делению на 10 в соответствующей сте пени, а делению на 2. Переведем для примера в двоичный вид число 0,625:

Процессоры Intel в реальном режиме Таблица 9. Типы данных FPU Количество Бит значащих Пределы Тип данных цифр 16 4 -32768... Целое слово 9 -2Х109... 2х Короткое целое 64 -ЭхЮ18... 9Х Длинное слово 80 18 -99..99...+99..99(18цифр) Упакованное десятичное 32 1.18Х10-38... 3,40хЮ Короткое вещественное 64 2,23X1 0"308... 1,79x1 15- Длинное вещественное Расширенное 80 19 3,37хЮ-4932... 1,18хЮ49зг вещественное 0,625 - 1/2 - 0, 1/4 больше, чем 0, 0,125 -1/8 = Итак, 0,625 = 0,101Ь. При записи вещественных чисел всегда выполняют нор мализацию - умножают число на такую степень двойки, чтобы перед десятичной точкой стояла единица, в нашем случае 0,625 = 0,101Ь - 1,01Ь х 2-'.

Говорят, что число имеет мантиссу 1,01 и экспоненту —1. Как можно заметить, при использовании этого алгоритма первая цифра мантиссы всегда равна 1, по этому ее можно не писать, увеличивая тем самым точность представления числа дополнительно на 1 бит. Кроме того, значение экспоненты хранят не в виде цело го со знаком, а в виде суммы с некоторым числом так, чтобы всегда было только положительное число и чтобы вещественные числа легко сопоставлялись в большинстве случаев достаточно сравнить экспоненту. Теперь мы можем рас смотреть вещественные форматы IEEE, применяемые в процессорах Intel:

О короткое вещественное: бит 31 - знак мантиссы, биты 30-23 - 8-битная эк спонента +127, биты 22-0 - 23-битная мантисса без первой цифры;

Q длинное вещественное: бит 63 - знак мантиссы, биты 62-52 - 11-битная эк спонента +1024, биты 51-0 - 52-битная мантисса без первой цифры;

Q расширенное вещественное: бит 79 - знак мантиссы, биты 78-64 - 15-бит ная экспонента +16 383, биты 63-0 - 64-битная мантисса с первой цифрой (то есть бит 63 равен 1).

FPU выполняет все вычисления в 80-битном расширенном формате, а 32 и 64-битные числа используются для обмена данными с основным процессором и памятью.

Кроме обычных чисел формат IEEE предусматривает несколько специаль ных случаев, которые могут получаться в результате математических операций и над которыми также можно выполнять отдельные операции:

Q положительный ноль: все биты числа сброшены в ноль;

а отрицательный ноль: знаковый бит - 1, все остальные биты - нули;

Числа с плавающей запятой Q положительная бесконечность: знаковый бит - 0, все биты мантиссы — О, все биты экспоненты - 1;

О отрицательная бесконечность: знаковый бит — 1, все биты мантиссы — О, все биты экспоненты - 1;

а Ненормализованные числа: все биты экспоненты - 0 (используются для ра боты с очень маленькими числами -до Ю~16445 для расширенной точности);

а неопределенность: знаковый бит - 1, первый бит мантиссы (первые два для 80-битных чисел) - 1, а остальные - 0, все биты экспоненты - 1;

О не-число типа SNAN (сигнальное): все биты экспоненты - 1, первый бит мантиссы - 0 (для 80-битных чисел первые два бита мантиссы - 10), а среди остальных битов есть единицы;

О не-число типа QNAN (тихое): все биты экспоненты - 1, первый бит ман тиссы (первые два для 80-битных чисел) - 1, среди остальных битов есть единицы. Неопределенность - один из вариантов QNAN;

а неподдерживаемое число: все остальные ситуации.

Остальные форматы данных FPU также допускают неопределенность — единица в старшем бите и нули в остальных для целых чисел, и старшие 16 бит - единицы для упакованных десятичных чисел.

2.4.2. Регистры FPU FPU предоставляет восемь регистров для хранения данных и пять вспомога тельных регистров.

Регистры данных (RO - R7) не адресуются по именам, как рещстры основного процессора, а рассматриваются в качестве стека, вершина которого называется ST;

более глубокие элементы - ST(1), ST(2) и так далее до ST(7). Если, например, в какой-то момент времени регистр R5 называется ST (см. рис. 13), то после запи си в этот стек числа оно будет записано в регистр R4, который станет называться ST, R5 станет называться ST(1) и т. д.

Pages:     || 2 | 3 | 4 | 5 |   ...   | 9 |



© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.