/
Текст
THE INTEL MICROPROCESSORS 8086/8088, 80186/80188, 80286, 80386, 80486, Pentium, Pentium Pro Processor, Pentium II, Pentium III, and Pentium 4 Architecture, Programming, and Interfacing Sixth Edition BARRY B. BREY DeVry Institute of Technology Prentice Hall Upper Saddle River, New Jersey Columbus, Ohio Барри Брэй МИКРОПРОЦЕССОРЫ INTEL 8086/8088. 80186/80188. 80286 80386, 80486, PENTIUM, PENTIUM PRO PROCESSOR, PENTIUM II, PENTIUM III, PENTIUM 4 АРХИТЕКТУРА, ПРОГРАММИРОВАНИЕ И ИНТЕРФЕЙСЫ ШЕСТОЕ ИЗДАНИЕ Санкт-Петербург «БХВ-Петербург» 2005 Брэй Б. Б87 Микропроцессоры Intel: 8086/8088, 80186/80188, 80286, 80386, 80486, Pentium, Pentium Pro Processor, Pentium II, Pentium III, Pentium 4. Архитектура, программирование и интерфейсы. Шестое издание: Пер. с англ. — СПб.: БХВ-Петербург, 2005. — 1328 с.: ил. ISBN 5-94157-422-3 Приведено подробное описание микропроцессоров семейства i80x86, вариантов организации памяти, систем ввода-вывода, устройств аналого-цифрового и цифроаналогового преобразования, последовательного канала связи на базе микросхемы 16550, периферийных интерфейсных адаптеров, таймеров, контроллеров дисплея и клавиатуры, арифметического сопроцессора, интерфейсов и системных шин персонального компьютера на примере стандартов AGP, ISA, PCI, VESA и USB. Для студентов и преподавателей вузов, специалистов в области информационных технологий УДК 681.3.06 ББК 32.973.26-018 Группа подготовки издания: Главный редактор Зам. главного редактора Зав. редакцией Перевод с английского Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством Екатерина Кондукова Татьяна Лапина Григорий Добин Андрея Жукова, Виталия Козуба Юрий Рожко Ольги Сергиенко Зинаида Дмитриева Игоря Цырульникова Николай Тверских Authorized translation from the English language edition, entitled The Intel microprocessors : 8086/8088, 80186/80188, 80286, 80386, 80486, Pentium, Pentium Pro processor, Pentium II, Pentium 111, and Pentium 4 : architecture, programming, and interfacing, 6th Edition, ISBN 0-13-060714-2, by Brey, Barry B., published by Pearson Education, Inc., publishing as Prentice Hall, Copyright © 2003 by Pcaison Education, Inc. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Peaison Education, Inc. RUSSIAN language edition published by BHV—St. Peteisbutg, Copyright © 2005. Авторизованный перевод английской редакции, выпущенной Prentice Hall, Pearson Education, Inc., © 2003. Bee права защищены. Никакая часть настоящей книги не может быть воспроизведена или передана в какой бы то ни было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на то нет разрешения Peaison Education, Inc. Перевод на русский язык "БХВ-Петербург". © 2005. Лицензия ИД No 02429 от 24.07.00. Подписано в печать 29.09.05. Формат 70хЮ01/1в. Печать офсетная. Усл. печ. л. 107,1. Тираж 3000 экз. Заказ No 384 "БХВ-Петербург", 194354, Санкт-Петербург, ул. Есенина, 5Б. Санитарно-эпидемиологическое заключение на продукцию No 77.99.02.953.Д.006421.11.04 от 11.11.2004 г. выдано Федеральной службой по надзору в сфере защиты прав потребителей и благополучия человека. Отпечатано с готовых диапозитивов в ОАО "Техническая книга" 190005, Санкт-Петербург, Измайловский пр., 29 ISBN 0-13-060714-2 (англ.) ISBN 5-94157-422-3 (рус.) С 2003, Pearson Education, Inc. © Перевод на русский язык “БХВ-Петербург', 2005 ОГЛАВЛЕНИЕ Введение..............................................................21 Содержание книги и ее особенности.....................................27 Порядок изложения.....................................................2$ Структура изложения...................................................2$ Благодарности....................................................... ЗС Адрес для связи.......................................................ЗС Глава 1. Введение в микропроцессоры и компьютеры......................31 Введение..............................................................31 Темы главы............................................................31 1.1. Исторический обзор...............................................32 Эпоха механики.....................................................32 Эпоха электричества................................................33 Развитие инструментов программирования.............................34 Эпоха микропроцессоров.............................................36 Особенности микропроцессора 18080..............................37 Микропроцессор i8O85...........................................37 Современные микропроцессоры........................................38 Микропроцессор i80286..........................................38 Микропроцессор i80386..........................................39 Микропроцессор i80486..........................................40 Микропроцессор Pentium.........................................42 Pentium Pro....................................................45 Pentium II и Pentium Xeon......................................45 Pentium III....................................................46 Pentium 4......................................................46 Будущее микропроцессоров.......................................46 1.2. Персональные вычислительные системы на базе микропроцессоров.....48 Память и система ввода-вывода......................................49 ТРА............................................................50 Системная область..............................................53 Пространство адресов системы ввода-вывода......................55 Операционная система DOS...........................................56 Микропроцессор.....................................................59 Шины...........................................................61 13. Системы счисления.................................................64 Цифры..............................................................64 Позиционные системы счисления......................................65 Преобразование в десятичный формат.................................66 6 Оглавление Преобразование из десятичного формата...............................67 Преобразование целой части десятичного числа....................67 Преобразование дробной части десятичного числа..................68 Шестнадцатеричные числа.............................................69 Дополнительный код..................................................70 1.4. Форматы данных....................................................71 ASCII-данные........................................................72 Двоично-десятичные данные...........................................74 Байты...............................................................75 Слова...............................................................76 Двойные слова.......................................................78 Действительные числа................................................79 Итоги..................................................................81 Контрольные вопросы и задания..........................................84 Глава 2. Микропроцессор и его архитектура..............................90 Введение...............................................................90 Темы главы.............................................................90 2.1. Внутренняя архитектура микропроцессора............................90 Программная модель микропроцессора..................................90 Регистры общего назначения......................................92 Специализированные регистры.....................................93 Сегментные регистры.............................................96 2.2. Адресация памяти в реальном режиме................................97 Сегменты и смещения.................................................97 Сочетания сегментов и смещений, действующие по умолчанию............99 Возможность перемещения программы в памяти.........................101 2.3. Введение в защищенный режим......................................103 Селекторы и дескрипторы............................................103 Программно-недоступные регистры....................................108 2.4. Страничная организация памяти....................................109 Регистры страничной организации памяти.............................109 Каталог страниц и таблицы страниц...................................111 Итоги.................................................................113 Контрольные вопросы...................................................114 Глава 3. Методы адресации.............................................117 Введение..............................................................117 Темы главы............................................................117 3.1. Методы адресации данных...........................................117 Регистровая адресация..............................................121 Непосредственная адресация.........................................122 Прямая адресация данных............................................125 Прямая адресация при обмене данными с аккумулятором............125 Общий случай прямой адресации..................................126 Регистровая косвенная адресация....................................128 Базово-индексная адресация.........................................131 Регистровая косвенная адресация со смещением.......................134 Оглавление 7 Базово-индексная адресация со смещением...........................136 Базово-индексная адресация с масштабированием.....................139 3.2. Структуры данных.................................................140 3.3. Методы адресации инструкций......................................143 Прямая адресация..................................................143 Относительная адресация...........................................144 Косвенная адресация...............................................144 3.4. Адресация стека..................................................146 Итоги.................................................................148 Контрольные вопросы...................................................153 Глава 4. Инструкции передачи данных...................................156 Введение..............................................................156 Темы главы............................................................156 4.1. Инструкция МОУ...................................................157 Машинный язык.....................................................157 Код операции...................................................158 Поле MOD.......................................................159 Коды регистров.................................................160 Коды поля R/M при адресации памяти.............................161 Кодирование прямой адресации...................................162 32-битная адресация............................................163 Непосредственный операнд.......................................164 Коды сегментных регистров......................................165 4.2. Инструкции для работы со стеком — PUSH и POP.....................166 Инструкция PUSH...................................................166 Инструкция POP....................................................168 Инициализация стека...............................................170 4.3. Загрузка адреса................................................. 171 Инструкция LEA......................:.............................172 Инструкции LDS, LES, LFS, LGS и LSS...............................173 4.4. Строковые команды................................................175 Флаг направления..................................................175 Регистры DI и SI..................................................176 Инструкция LODS...................................................176 Инструкция STOS...................................................177 Команда STOS с префиксом повторения REP........................178 Инструкция МОУЕ...................................................179 Инструкция INS....................................................180 Инст рукция OUTS.................................................181 4.5. Дополнительные инструкции передачи данных........................182 Инструкция XCHG...................................................182 Инструкции LAHFn SAHF.............................................183 Инструкция XLAT...................................................183 Инструкции IN и OUT...............................................184 Инструкции МОУЕХ и М0У7Х..........................................186 Инструкция BSWAP..................................................187 Группа команд СМОУ................................................187 4.6. Префиксы переназначения сегмента................................189 4.7. Введение в язык ассемблера......................................189 Директивы.........................................................190 Дире ктивы определения данных................................191 Директивы ASSUME, EQU и ORG...................................193 Директивы PROC и ENDP.........................................194 Организация памяти................................................196 Модели памяти.................................................196 Полное определение сегментов..................................197 Пример программы..................................................200 Итоги................................................................202 Контрольные вопросы..................................................205 Глава 5. Арифметические и логические инструкции......................208 Введение.............................................................208 Темы главы...........................................................208 5.1. Сложение, вычитание и сравнение.................................208 Сложение..........................................................209 Сложение при регистровой адресации............................210 Сложение при непосредственной адресации.......................210 Сложение данных в памяти и в регистре.........................211 Сложение элементов массива....................................211 Инкремент.....................................................212 Сложение с переносом..........................................214 Команда обмена и сложения в процессорах 80486—Pentium 4.......215 Вычитание.........................................................215 Вычитание при регистровой адресации...........................216 Вычитание непосредственного значения..........................216 Декремент.....................................................217 Вычитание с заемом............................................218 Сравнение....................................................... 219 Инструкция сравнения и обмена в процессорах 80486—Pentium 4...220 5.2. Умножение и деление.............................................220 Умножение.........................................................221 Восьмибитное умножение........................................221 Умножение 16-битных слов......................................222 Инструкция 16-битного умножения с непосредственным операндом..222 Умножение 32-битных данных....................................223 Деление...........................................................223 Восьмибитное деление..........................................224 Деление с 16-битным делителем.................................225 Деление с 32-битным делителем.................................226 Использование остатка.........................................226 5.3. Арифметика BCD- и ASCII-данных..................................227 BCD-арифметика....................................................228 Инструкция DAA................................................228 Инструкция DAS................................................229 Оглавлен^______________________________________________________________* ASCII-арифметика..................................................229 Инструкция ААА...............................................229 Инструкция AAD...............................................230 Инструкция ААМ...............................................230 Инструкция AAS...............................................232 5 4. Логические команды..............................................232 Инструкция AND...................................................232 Инструкция OR....................................................234 Инструкция XOR...................................................236 Инструкции проверки бит..........................................238 Инструкции NOT и NEG.............................................239 5.5. Сдвиги, в том числе и циклические...............................240 Сдвиги............................................................240 Сдвиги с удвоенной точностью (80386—Pentium 4)................242 Циклические сдвиги................................................243 Инструкции сканирования бит.......................................244 5.6. Сравнение строк.................................................245 Инструкция SCAS...................................................245 Инструкция CMPS...................................................246 Итоги................................................................247 Контрольные вопросы..................................................249 Глава 6. Инструкции передачи управления..............................253 Введение.............................................................253 Темы главы...........................................................253 6.1. Инструкции перехода.............................................253 Безусловный переход...............................................254 Короткий переход..............................................255 Ближний переход...............................................256 Дальний переход...............................................257 Переход по адресу, заданному содержимым регистра..............258 Косвенный переход при индексной адресации.....................260 Команды условного перехода и условной установки...................261 Инструкции условной установки.................................264 Инструкция LOOP...................................................264 Условные циклы................................................266 6.2. Логические блоки в языке ассемблера.............................266 Циклы DO-WHILE....................................................269 Циклы REPEAT-UNTIL................................................272 6.3. Процедуры.......................................................274 Инструкция CALL...................................................275 Ближний вызов.................................................275 Дальний вызов.................................................276 Вызов по значению регистра....................................277 Вызов с косвенной адресацией данных...........................277 Инструкция RET....................................................279 6.4. Введение в прерывания...........................................281 Векторы прерываний................................................281 10 Оглавление Инструкции вызова прерываний.....................................282 Инструкция INT...............................................282 Инструкция IRET/IRETD........................................283 Инструкция INT 3.............................................284 Инструкция INTO..............................................284 Процедуры обработки прерываний...................................284 Управление внешними прерываниями.............................284 Прерывания в IBM PC..........................................285 6.5. Управляющие инструкции.........................................286 Команды STC, CLC и СМС...........................................287 Инструкция WAIT..................................................287 Инструкция HLT...................................................287 Инструкция NOP...................................................287 Префикс LOCK.....................................................288 Инструкция ESC...................................................288 Инструкция BOUND.................................................288 Инструкции ENTER и LEAVE.........................................289 Итоги...............................................................290 Контрольные вопросы.................................................293 Глава 7. Возможности программирования на ассемблере.................296 Введение............................................................296 Темы главы..........................................................296 7.1. Модульное программирование.....................................296 Ассе мблер и компоновщик........................................297 Директивы PUBLIC и EXTRN.........................................298 Библиотеки.......................................................300 Создание файла библиотеки....................................300 Макрокоманды.....................................................302 Локальные переменные в макрокомандах.........................303 Размещение макроопределений в отдельном файле................304 Макрокоманды и директивы условной трансляции.....................304 Директивы условной трансляции....................................304 Директивы условной трансляции в макроопределениях................306 Директива REPEAT в макрокомандах.............................307 Директива WHILE в макрокомандах..............................308 Директива FOR в макрокомандах................................309 Директивы IF, ELSE и ENDIFb макрокомандах....................310 Модульное программирование.......................................312 7.2. Работа с клавиатурой и дисплеем................................312 Ввод с клавиатуры функциями DOS..................................312 Ввод символа с эхо-печатью...................................316 Ввод символа без эхо-печати..................................316 Ввод строки символов с эхо-печатью...........................317 Вывод на дисплей функциями DOS...................................318 Вывод одиночного ASCII-символа...............................318 Вывод строки символов........................................319 Видеофункции BIOS................................................319 Позиционирование курсора.....................................320 пгпавление- 11 Макрокоманда для вывода символа....................................322 Работа с мышью.....................................................323 Проверка наличия драйвера мыши.....................................323 Определение типа мыши и версии драйвера............................324 Взаимодействие с драйвером мыши....................................326 7.3. Преобразования данных............................................329 Преобразование двоичного числа в строку ASCII-символов.............329 Преобразование строки ASCII-символов в двоичное число.............332 Ввод-вывод шестнадцатеричных чисел.................................333 Ввод шестнадцатеричных данных.................................333 Вывод шестнадцатеричных чисел.................................335 Табличные преобразования данных....................................336 Преобразование в семисегментный код...........................336 Таблицы строк ASCII-символов..................................337 Пример табличного преобразования данных............................338 7.4. Дисковые файлы...................................................342 Структура данных на диске..........................................342 Имена файлов.......................................................345 Имена каталогов...............................................346 Хранение длинных имен файлов..................................346 Последовательный доступ к файлам...................................347 Создание файла................................................347 Запись в файл.................................................348 Открытие, чтение и закрытие файла.............................349 Указатель файла...............................................350 Прямой доступ к файлам.............................................353 Создание файла с прямым доступом..............................354 Чтение и запись...............................................355 7.5. Примеры программ.................................................355 Программа-калькулятор..............................................355 Сортировка числовых данных.........................................357 Шестнадцатеричный дамп файла.......................................360 7.6. Обработка прерываний.............................................364 Перехват прерываний................................................364 Пример резидентной программы.......................................365 Пример "всплывающей" программы.....................................371 Итоги.................................................................377 Контрольные вопросы...................................................378 Глава 8. Совместное использование языка ассемблер и C/C++.............381 Введение..............................................................381 Темы главы............................................................381 8.1. Ассемблер и C/C++ в 16-битных приложениях........................381 Ассемблерные вставки...............................................382 Ограничения при использовании ассемблерных вставок.................385 Работа со строками.................................................385 Доступ к элементам структур........................................386 Пример программы...................................................388 12 Оглавление 8.2. Применение ассемблера и C/C++ в 32-битных приложениях...........390 Пример консольного приложения.....................................390 Прямой доступ к портам............................................391 8.3. Объединение модулей на языках ассемблер и C/C++ при раздельной трансляции...........................................................394 Компоновка модулей на ассемблере и Visual С.......................394 Включение новых машинных команд в программы на языке C/C++........399 Итоги................................................................400 Контрольные вопросы..................................................400 Глава 9. Спецификации аппаратных средств микропроцессоров 8086/8088....402 Введение.............................................................402 Темы главы...........................................................402 9.1. Расположение и назначение выводов процессора....................402 Схема расположения выводов........................................403 Требования к источнику электропитания.............................404 Характеристики процессора по постоянному току.................404 Входные характеристики........................................404 Выходные характеристики.......................................404 Назначение выводов и сигналов.....................................406 Выводы процессора для минимального режима работы..............408 Выводы процессора для максимального режима работы.............410 9.2. Генератор синхронизирующих импульсов 8284А......................411 Назначение выводов................................................411 Работа генератора 8284А...........................................414 Работа узла синхронизации.....................................414 Работа узла формирователя сигнала сброса RESET................415 9.3. Буферизация шины и применение регистров-защелок.................416 Демультиплексирование шин.........................................416 Демультиплексирование для микропроцессора 8088................417 Демультиплексирование для микропроцессора 8086................418 Буферизированная система..........................................419 Полностью буферизированная система на базе микропроцессора 8088.420 Полностью буферизированная система на базе микропроцессора 8086.420 9.4. Циклы шины......................................................422 Основные операции шины............................................423 Понятие о циклах шины.............................................423 Временная диаграмма чтения........................................425 Временная диаграмма записи........................................430 9.5. Состояние готовности и ожидания.................................431 Вывод READY микропроцессора 8086/8088.............................431 RDY и 8284А.......................................................432 9.6. Сопоставление минимального и максимального режимов работы микропроцессоров 8086/8088...........................................435 Минимальный режим работы..........................................435 Максимальный режим работы.........................................435 Шинный контроллер 8288............................................438 Назначение выводов и сигналов.................................438 Огла0Л^!2.------------------------------------------------------------— Итоги.................................................................440 Контрольные вопросы и задания.........................................441 Глава Ю. Интерфейс памяти...........................................444 Введение..............................................................444 Темы главы............................................................444 10.L Запоминающие устройства..........................................444 Выводы элементов памяти...........................................445 Выводы адреса..................................................445 Выводы данных..................................................446 Выводы выбора..................................................447 Управляющие выводы.............................................447 ПЗУ...............................................................447 Статическая память................................................451 Динамическая память...............................................457 10.2. Дешифрирование адреса...........................................463 Зачем нужен дешифратор?...........................................463 Простой дешифратор на логическом элементе И-НЕ....................463 Линейный дешифратор "3-8" (74LS138)...............................465 Схема применения дешифратора...................................466 Сдвоенный линейный дешифратор "2-4" (74LS139).....................468 Адресный дешифратор на ППЗУ.......................................469 Программируемые дешифраторы на ПЛУ................................471 Комбинаторные программируемые логические матрицы...............471 10.3. Интерфейс памяти 8-разрядных микропроцессоров 8088 и 80188 .....475 Базовый интерфейс памяти микропроцессоров 8088/80188..............476 Сопряжение ПЗУ с микропроцессором 8088.........................476 Сопряжение ОЗУ с микропроцессором 8088 ........................477 Интерфейс флэш-памяти.............................................479 Проверка на четность для обнаружения ошибок памяти................481 Исправление ошибок................................................483 10.4. Интерфейс памяти 16-разрядных микропроцессоров 8086, 80186, 80286 и 80386SX.............................................................487 16-разрядная шина управления......................................487 Дешифраторы банков.............................................488 Отдельные стробы записи банков.................................490 Ю.5. Интерфейс памяти 32-разрядных микропроцессоров 80386DX и 80486...496 Банки памяти......................................................496 Интерфейс 32-разрядной памяти.....................................497 Ю.6. Интерфейс памяти 64-разрядных микропроцессоров Pentium—Pentium 4.499 Интерфейс 64-разрядной памяти.....................................501 Ю.7. Динамические запоминающие устройства.............................504 Повторное рассмотрение динамического ЗУ...........................504 Память EDO........................................................506 Синхронное динамическое ЗУ (SDRAM)................................507 Контроллеры динамического ЗУ......................................507 Итоги.................................................................510 Контрольные вопросы и задания.........................................512 14 Оглавление Глава 11. Базовый интерфейс ввода-вывода.............................515 Введение.............................................................515 Темы главы...........................................................515 11.1. Введение в интерфейс ввода-вывода..............................516 Команды ввода-вывода.............................................516 Изолированный и отображаемый в памяти ввод-вывод.................518 Изолированный ввод-вывод......................................518 Отображаемый в памяти ввод-вывод..............................519 Карта распределения устройств ввода-вывода персонального компьютера....................................................520 Элементарные интерфейсы ввода-вывода.............................521 Элементарный интерфейс ввода данных...........................521 Элементарный интерфейс вывода данных.............................522 Квитирование.....................................................523 Немного о схемах сопряжения......................................525 Устройства ввода..............................................526 Устройства вывода.............................................528 11.2. Дешифрирование адреса порта ввода-вывода.......................530 Дешифрирование 8-разрядных адресов устройств ввода-вывода........530 Дешифрирование 16-разрядных адресов устройств ввода-вывода.......532 8- и 16-разрядные порты ввода-вывода............................533 32-разрядные порты ввода-вывода..................................536 11.3. Программируемый периферийный интерфейс 8255А/8255А-5/82С55 ....538 Описание ППИ 82С55 ..............................................539 Программирование ППИ 82С55.......................................541 Функционирование в режиме 0......................................543 Подключение жидкокристаллического индикатора к ППИ 82С55......547 Подключение шагового двигателя к ППИ 82С55....................553 Подключение матричной клавиатуры..............................556 Стробированный ввод режима 1.....................................561 Описание сигналов стробированного ввода режима 1..............561 Пример стробированного ввода..................................563 Стробированный вывод режима 1.................................564 Описание сигналов стробированного вывода режима 1.............564 Пример стробированного вывода.................................566 Двунаправленные операции режима 2................................567 Описание сигналов для двунаправленной передачи режима 2.......569 Двунаправленная шина..........................................569 Краткие суммарные сведения о режимах ППИ 82С55...................571 11.4. Программируемый интерфейс клавиатуры/дисплея 8279..............571 Краткое описание интерфейса 8279.................................572 Описание выводов интерфейса 8279..............................573 Сопряжение интерфейса 8279 с микропроцессором....................574 Интерфейс клавиатуры.............................................576 Программирование интерфейса клавиатуры........................576 Описание командных слов.......................................576 Интерфейс 6-разрядного дисплея...................................582 Оглавление 15 11.5. Программируемый интервальный таймер 8254.......................585 Функциональное описание таймера 8254.............................585 Назначение выводов...............................................587 Программирование таймера 8254....................................588 Режимы работы.................................................589 Формирование формы сигнала с помощью таймера 8254.............592 Считывание из счетчика........................................593 Управление скоростью и направлением вращения двигателя постоянного тока.............................................................595 11.6. Программируемый связной интерфейс 16550........................599 Последовательная асинхронная передача данных.....................599 Функциональное описание микросхемы 16550.........................600 Назначение выводов микросхемы 16550...........................601 Программирование микросхемы 16550................................604 Инициализация.................................................604 Программирование скорости передачи............................606 Пример выполнения инициализации...............................607 Передача последовательных данных..............................610 Прием последовательных данных.................................611 Ошибки универсального асинхронного приемопередатчика..........612 11.7. Аналого-цифровой (АЦП) и цифроаналоговый (ЦАП) преобразователи..612 Цифроаналоговый преобразователь DAC0830..........................612 Внутренняя структура преобразователя DACO830..................613 Подключение преобразователя DAC0830 к микропроцессору.........614 Аналого-цифровой преобразователь ADC0804.........................615 Аналоговый входной сигнал.....................................616 Генерирование синхронизирующего сигнала.......................617 Подключение преобразователя ADC0804 к микропроцессору.........618 Совместное применение ADC0804 и DAG0830..........................619 Итоги............................................................... 621 Контрольные вопросы и задания........................................624 Глава 12. Прерывания.................................................628 Введение.............................................................628 Темы главы...........................................................628 12.1. Основы процесса прерываний.....................................628 Назначение прерываний............................................628 Прерывания.......................................................629 Векторы прерываний............................................630 Команды прерываний: BOUND, INTO, INT, INT 3 и IRET...............633 Прерывания в реальном режиме.....................................634 Прерывания в защищенном режиме...................................635 Флаги, относящиеся к прерыванию..................................636 Процедура трассировки программы...............................638 Сохранение вектора прерывания в таблице векторов.................640 12.2. Аппаратные прерывания..........................................641 Сигнал NMI.......................................................641 Сигналы INTR и INTA .............................................644 16 Оглавление Использование буфера с тремя состояниями для выдачи вектора....645 Формируемый фронтом сигнал запроса на прерывание INTR..........646 Прерывание от клавиатуры, подключенной посредством микросхемы ППИ 82С55........................................................647 12.3. Расширение системы прерываний..................................650 Использование логического элемента И-НЕ и буфера 74ALS244........651 Принцип работы схемы..........................................652 Система прерывания с последовательным опросом....................652 12.4. Программируемый контроллер прерываний 8259А....................655 Общая характеристика контроллера 8259А...........................655 Подключение одного контроллера 8259А.............................657 Каскадное подключение контроллеров 8259А.........................658 Программирование контроллера 8259А...............................658 Командные слова инициализации.................................658 Командные слова операций......................................662 Регистры состояния............................................665 Пример программирования контроллера 8259А........................666 Инициализация.................................................666 Обработка запроса на прерывание от UART 16550.................669 Получение данных от UART 16550................................671 Передача данных на UART 16550.................................673 12.5. Примеры прерываний.............................................677 Часы реального времени...........................................678 Обработка прерываний клавиатуры..................................679 Итоги................................................................683 Контрольные вопросы и задания........................................685 Глава 13. Прямой доступ к памяти.....................................687 Введение.............................................................687 Назначение главы.....................................................687 13.1. Основы процесса прямого доступа к памяти.......................688 Основные операции................................................689 13.2. Контроллер DMA 8237............................................690 Назначение выводов и сигналов....................................692 Внутренние регистры..............................................694 Команды для программирования контроллера.........................700 Программирование регистров адреса и счета слов...................701 Подключение контроллера DMA 8237А к микропроцессору 80x86........703 Передачи данных типа ’’память-память”............................707 Пример передачи типа ’’память-память”.........................707 Пример заполнения памяти с использованием контроллера 8237....709 Прямой доступ к памяти при работе с принтером....................711 13.3. Функционирование общей шины....................................714 Типы шин.........................................................715 Арбитр шины 8289.................................................717 Организация арбитра шины 8289.................................717 Назначение выводов и сигналов.................................718 Принцип работы арбитра шины 8289..............................720 Оглавление 17 44 Ъ WK Иллюстрация системы с арбитрами шины, работающими в одношинном режиме и режиме с локальной шиной................721 Обслуживание приоритетов для арбитров шин 8289...................724 Схема с последовательным опросом..............................724 Схема с параллельным обслуживанием приоритетов................725 Спулер печати и интерфейс принтера...............................726 Интерфейс ведущего микропроцессора в одношинном режиме работы .... 727 Работа локальной шины подчиненного микропроцессора 8088.......729 Программное обеспечение спулера печати........................732 13.4. Системы памяти на дисках.......................................738 Память на гибких магнитных дисках................................738 Гибкий магнитный диск 5,25”...................................739 Гибкий магнитный диск 3,5”....................................742 Память на жестких магнитных дисках...............................744 Метод записи с кодированием RLL...............................746 Оптические диски.................................................749 13.5. Видеодисплеи...................................................751 Видеосигналы.....................................................751 Цифровой RGB-монитор.............................................752 Аналоговый RGB-монитор...........................................754 Итоги................................................................760 Контрольные вопросы и задания........................................761 Глава 14. Арифметический сопроцессор и расширение ММХ................763 Введение.............................................................763 Назначение главы.....................................................764 14.1. Форматы данных арифметического сопроцессора....................764 Знаковые целые...................................................765 Двоично-десятичные числа (BCD)........**.........................766 Данные с плавающей точкой........................................766 Преобразование к формату действительных чисел.................767 Преобразование из формата действительных чисел................768 Хранение действительных чисел в памяти........................768 14.2. Архитектура сопроцессора 80x87.................................769 Внутренняя организация сопроцессора 80x87........................769 Регистр состояния.............................................771 Регистр управления............................................774 Регистр тегов.................................................776 14.3. Команды сопроцессора...........................................776 Команды передачи данных..........................................777 Команды передачи действительных чисел.........................777 Команды передачи целочисленных данных.........................777 Команды передачи BCD-данных...................................777 Команды условной передачи данных для процессоров Pentium Pro— Pentium 4.....................................................778 Арифметические команды...........................................779 Разновидности команд базовой арифметики.......................780 Дополнительные команды арифметических операций................781 18 Оглавление Команды сравнения.................................................782 Трансцендентные команды...........................................783 Команды загрузки констант.........................................784 Команды управления сопроцессором..................................784 Список команд сопроцессора........................................788 14.4. Программирование сопроцессора...................................802 Вычисление площади круга..........................................802 Вычисление резонансной частоты....................................804 Решение квадратного уравнения.....................................804 Запись результатов в массив.......................................806 Вывод на экран действительных чисел одинарной точности............807 Ввод действительных чисел с клавиатуры............................809 14.5. Введение в технологию ММХ.......................................811 Типы данных ММХ...................................................811 Система команд ММХ................................................811 Арифметические команды.........................................812 Инструкции сравнения...........................................812 Команды преобразования.........................................813 Логические команды.............................................813 Команды сдвига.................................................813 Команды передачи данных........................................813 Команда EMMS...................................................814 Список команд ММХ..............................................814 Итоги.................................................................824 Контрольные вопросы...................................................826 Глава 15. Шины ввода-вывода...........................................829 Введение..............................................................829 Назначение главы......................................................829 15.1. Шина ISA........................................................829 Эволюция шины ISA.................................................830 Интерфейс вывода данных для 8-разрядной шины ISA..................830 Интерфейс ввода данных для 8-разрядной шины ISA...................836 16-разрядная шина ISA.............................................838 15.2. Шины EISA и VLB................................................ 840 Шина EISA.........................................................840 Пример схемы интерфейса для шины EISA.............................840 Счетчик событий................................................842 Частотомер.....................................................843 Шина VLB..........................................................845 Схема расположения выводов шины VLB............................845 15.3. Шина PCI........................................................847 Схема расположения выводов шины PCI...............................848 Мультиплексированные линии шины PCI...............................848 Конфигурационное пространство................................... 852 BIOS для шины PCI.................................................855 Интерфейс PCI.................................................... 859 Оглавление 19 15 4. Порт параллельного интерфейса (LPT-порт)........................859 Описание LPT-порта................................................860 Использование параллельного порта без поддержки режима ЕСР........863 15 5. Универсальная последовательная шина USB.........................863 Разъем............................................................864 Данные шины USB...................................................865 Управление шиной USB..............................................866 15.6. Ускоренный графический порт AGP.................................870 Итоги.................................................................871 Контрольные вопросы и задания.........................................872 Глава 16. Микропроцессоры 80186, 80188 и 80286 .......................874 Введение..............................................................874 Назначение главы......................................................874 16.1. Архитектура микропроцессоров 80186/80188........................875 Версии микропроцессоров 80186/80188...............................875 Базовая блок-схема микропроцессора 80186..........................875 Основные особенности микропроцессоров 80186/80188.................876 Генератор тактовых импульсов...................................877 Программируемый контроллер прерываний..........................878 Таймеры........................................................878 Программируемый блок DMA.......................................879 Программируемый блок выбора кристалла..........................879 Режимы экономии электроэнергии и выключения питания............880 Блок управления регенерацией памяти............................880 Схема расположения выводов........................................880 Описание выводов и соответствующих сигналов....................881 Характеристики процессора по постоянному току.....................885 Временные соотношения сигналов микропроцессоров 80186/80188.......885 Время доступа к памяти.........................................886 16.2. Программирование расширенных возможностей микропроцессоров 80186/80188...........................................................891 Блок управления периферией........................................891 Прерывания в микропроцессорах 80186/80188.........................893 Контроллер прерываний.............................................894 Регистры контроллера прерываний................................896 Каскадное включение с внешними контроллерами прерывания........897 Регистры управления прерываниями...............................898 Регистр запросов прерываний....................................899 Регистр масок и регистр маски приоритета.......................899 Регистр обслуживания прерываний................................900 Регистр опроса и регистр состояния опроса......................900 Регистр завершения прерывания..................................901 Регистр состояния прерываний...................................901 Регистр вектора прерываний.....................................902 Таймеры...........................................................902 Принцип действия регистров таймера.............................904 Выходные выводы таймера........................................908 Пример часов реального времени.................................908 20 Оглавление Контроллер DMA....................................................911 Регистр управления каналом....................................912 Пример передачи типа "память-память"..........................913 Блок выбора кристалла.............................................914 Выбор элементов памяти........................................914 Выбор периферийных устройств..................................915 Программирование блока выбора кристалла процессоров 80186/80188 версий XL и ЕА................................................915 Программирование блока выбора кристалла процессоров 80186/80188 версий ЕВ и ЕС................................................919 16.3. Пример использования процессора 80С188ЕВ.......................921 16.4. Операционная система реального времени.........................925 Что представляет собой операционная система реального времени?...926 Пример системы...................................................926 Многопоточная система............................................940 16.5. Микропроцессор 80286...........................................945 Аппаратные особенности...........................................945 Система команд...................................................948 Виртуальная память...............................................950 Итоги................................................................951 Контрольные вопросы и задания........................................952 Глава 17. Микропроцессоры 80386 и 80486..............................955 Введение.............................................................955 Назначение главы.....................................................955 17.1. Микропроцессор 80386...........................................956 Система памяти...................................................961 Буферизованная система........................................963 Конвейерная адресация и кэш-память............................963 Системы памяти с чередованием адресов.........................965 Система ввода-вывода.............................................970 Сигналы, управляющие памятью и вводом-выводом....................971 Временные диаграммы..............................................972 Такты ожидания...................................................974 17.2. Специальные регистры микропроцессора 80386.....................976 Управляющие регистры.............................................977 Регистры отладки и тестирования..................................978 17.3. Управление памятью.............................................981 Дескрипторы и селекторы..........................................981 Дескрипторы сегмента кода и данных............................984 Дескриптор системных сегментов................................986 Таблицы дескрипторов.............................................987 Сегмент состояния задачи TSS.....................................990 17.4. Переход в защищенный режим.....................................992 17.5. Режим виртуального микропроцессора 8086...................... 1009 17.6. Страничное управление памятью.................................1010 Каталог страниц.................................................1011 Таблица страниц................................................ 1012 Оглавление 21 17.7. Микропроцессор 80486......................................... 1016 Схема расположения выводов микропроцессоров 80486DX и 80486SX...1017 Назначение сигналов и выводов................................1018 Базовая архитектура микропроцессора 80486...................... 1024 Система памяти микропроцессора 80486........................... 1025 Блок проверки/генератора паритета............................1026 Кэш-память...................................................1027 Временная диаграмма чтения памяти............................1028 Управление памятью микропроцессора 80486....................... 1030 Тестовые регистры кэш-памяти....................................1030 Итоги...............................................................1032 Контрольные вопросы и задания.......................................1034 Глава 18. Микропроцессоры Pentium и Pentium Pro.....................1037 Введение............................................................1037 Назначение главы.................................................... 1037 18.1. Микропроцессор Pentium........................................1038 Система памяти..................................................1046 Система ввода-вывода............................................1048 Синхронизация системы...........................................1049 Логика предсказания ветвления...................................1052 Структура кэш-памяти............................................1053 Суперскалярная архитектура......................................1053 18.2. Специальные регистры микропроцессора Pentium..................1053 Управляющие регистры............................................1053 Регистр флагов EFLAG............................................1056 Встроенный самоконтроль.........................................1056 18.3. Управление памятью микропроцессора Pentium....................1056 Блок страничной трансляции адресов..............................1057 Режим системного управления SMM.........•/......................1058 18.4. Новые команды микропроцессора Pentium.........................1060 18.5. Микропроцессор Pentium Pro....................................1065 Внутренняя структура микропроцессора Pentium Pro................1065 Назначение сигналов и выводов процессора........................1069 Система памяти................................................ 1075 Система ввода-вывода............................................1077 Синхронизация системы...........................................1077 18.6. Специальные особенности микропроцессора Pentium Pro...........1079 Управляющий регистр CR4.........................................1079 Итоги...............................................................1080 Контрольные вопросы и задания.......................................1082 Глава 19. Микропроцессоры Pentium II, Pentium III и Pentium 4.......1084 Введение........................................................:...1084 Назначение главы....................................................1085 19.1. Микропроцессор Pentium II.....................................1085 Система памяти..................................................1095 Система ввода-вывода............................................1098 Системная синхронизация.........................................1098 22 Оглавление 19.2. Изменения в программном обеспечении Pentium II...............1099 Команда CPUID..................................................1099 Команды SYSENTER и SYS EXIT....................................1100 Команды FXSAVEh FXRSTOR........................................1102 19.3. Микропроцессор Pentium III...................................1103 Чипсеты........................................................1103 Шина...........................................................1103 Схема расположения выводов.....................................1104 19.4. Микропроцессор Pentium 4.....................................1105 Сопряжение с памятью...........................................1106 Набор регистров................................................1107 Гиперконвейерная технология....................................1109 Команда CPUID..................................................1109 Особенности применения микропроцессора Pentium 4...............1110 Итоги..............................................................1110 Контрольные вопросы и задания......................................1111 Приложение 1. Директивы ассемблера, функции DOS и BIOS, управление мышью и интерфейс DPMI..................................1113 Использование инструментальных средств.............................1113 Модели памяти в ассемблере.........................................1114 Вызов функций DOS..................................................1120 Вызов функций BIOS.................................................1148 Прерывание INT ЮН..............................................1148 Выбор видеорежима...........................................1148 Управление курсором и изображением..........................1150 Прерывание INT НН..............................................1154 Прерывание INT 12Н............................................. 1154 Прерывание INT 13Н.............................................1154 Прерывание INT 14Н.............................................1155 Прерывание INT 15Н.............................................1156 Прерывание INT 16Н.............................................1157 Прерывание INT 17Н.............................................1157 Системная область DOS/BIOS.....................................1158 Функции драйвера мыши..............................................1160 Функции DPMI.......................................................1171 Приложение 2. Система команд микропроцессоров 80x86/Pentium........1192 SIMD-команды.......................................................1260 Приложение 3. Воздействие инструкций на флаги......................1270 Приложение 4. Ответы на контрольные вопросы с четными номерами.....1273 Глава 1............................................................1273 Глава 2............................................................1275 Глава 3............................................................1276 Оглавление 23 Глава 4......................................................................1277 Глава 5......................................................................1278 Глава 6......................................................................1280 Глава 7......................................................................1282 Глава 8......................................................................1287 Глава 9......................................................................1287 Глава 10.................................................................... 1288 Глава 11.....................................................................1292 Глава 12.....................................................................1297 Глава 13.....................................................................1299 Глава 14................................................................... 1301 Глава 15.....................................................................1304 Глава 16.....................................................................1307 Глава 17.....................................................................1308 Глава 18.....................................................................1310 Глава 19....................................................................13-10 Предметный указатель.........................................................1312 Посвящается моей любимой жене Шейле Посвящается моей любимой жене Шейле ВВЕДЕНИЕ Предлагаемое вашему вниманию учебно-справочное пособие адресовано, в первую очередь, тем учащимся, чья специализация требует не только общих навыков программирования, но и глубоких знаний по организации интерфейсов вычислительных систем на базе микропроцессоров фирмы Intel. Микропроцессоры Intel широко применяются в различных областях электроники, в системах связи, в системах автоматического управления, а также в персональных компьютерах. Поэтому на сегодня всем, кто связывает свою деятельность с применением компьютеров, следует иметь представление об организации вычислительных систем на базе микропроцессоров Intel и программировании этих систем на языке ассемблера. В настоящее издание включена глава о совместном использовании языка C/C++ и языка ассемблера применительно к операционным системам DOS и Windows. Содержание книги и ее особенности Каждая глава открывается кратким перечнем целей и рассматриваемых предметов. Основное изложение сопровождается многочисленными примерами программ. В конце глав подводятся итоги и предлагаются контрольные вопросы. Примеры программ написаны на языках MASM (ассемблер фирмы Microsoft) и C++ (вариант Visual C++). Предполагается, что система автоматизации программирования и операционная система включают в себя компоновщик, библиотекарь, набор макрокоманд, функции BIOS и DOS, а также среду программирования Visual C++ (возможность ассемблерных вставок в текст на языке C/C++ рассмотрена применительно к 16- и 32-разрядным версиям Visual C++). В книге приведено подробное описание: поколений микропроцессоров семейства i80x86; О вариантов организации памяти; О системы ввода-вывода (включая дисковую память); □ устройств аналого-цифрового и цифроаналогового преобразования; □ последовательного канала связи на базе микросхемы 16550; О PIAs; О таймеров; О контроллеров дисплея и клавиатуры; О арифметического сопроцессора; интерфейсов и системных шин персонального компьютера на примерах стандартов AGP, ISA, PCI, VESA и USB. 28 Введение Порядок изложения Поскольку между поколениями семейства i80x86 разница довольно существенная, в начале книги рассматривается программирование в реальном режиме, общее для всех поколений. В дальнейшем изложении новые инструкции микропроцессоров 80386, 80486, Pentium, Pentium Pro, Pentium II, Pentium III и Pentium 4 сопоставляются с базовым набором инструкций микропроцессора 8086/8088. Поколения от 80386 до Pentium 4 различаются между собой незначительно, и для понимания их особенностей нам вполне достаточно будет знакомства с базовым вариантом — микропроцессором 8086/8088. Заметим, что микропроцессор 8086/8088 и по сей день используется в контроллерах — наряду с 80186/80188 и встроенным микроконтроллером 80386ЕХ. В книге рассматриваются также устройство и программирование арифметического сопроцессора. Сопроцессор i80x87 позволяет ускорить операции над данными в формате с плавающей точкой, что и определяет области его применения — системы автоматического управления, машинная графика, в частности, системы автоматизированного проектирования. В книге приведены описание и назначение контактов микросхемы для каждого из микропроцессоров семейства i80x86/Pentium. Изложение принципов организации микропроцессорных систем мы начинаем с примера системы на базе процессора 8086/8088 с включением периферийных компонентов общего назначения. В дальнейшем обсуждаются системы на базе микропроцессоров 80186/80188, 80386, 80486, а также от Pentium до Pentium 4. (Процессор 80286, представляющий собой нечто среднее между 8086/8088 и 80368, подробно не обсуждается.) Материал, представленный в книге, позволит вам: 1. Разрабатывать прикладное программное обеспечение для операционных систем DOS и Windows. 2. Использовать в программах на языке ассемблера вызовы DOS для обслуживания клавиатуры, дисплея и дисковой памяти. 3. Использовать функции BIOS для обслуживания клавиатуры, дисплея и иных компонентов вычислительной системы. 4. Применять в программах на языке ассемблера макрокоманды, вызовы процедур, директивы условной трансляции, а также логические операторы структурного ассемблера1. 5. Использовать перехват прерываний и разрабатывать резидентные программы, активизируемые нажатием комбинации клавиш. 6. Программировать арифметический сопроцессор для вычисления сложных выражений в формате с плавающей точкой. 7. Выяснить для себя и уметь объяснить особенности разных представителей семейства микропроцессоров i80x86/Pentium. 1 Директивы структурного ассемблера, встроенные в MASM 6.0 и специфические для этого ассемблера. — Пер. Введение 29 8. Применять реальный и защищенный режимы работы микропроцессора. 9. Иметь представление об организации интерфейса с памятью и устройствами ввода-вывода. 10. Представлять себе особенности построения аппаратных и программных систем на основе микропроцессоров Intel. 11. Понимать функционирование операционных систем реального времени для встроенных микропроцессорных систем. 12. Иметь представление об организации видео- и дисковой подсистем. 13. Проектировать периферийные компоненты персональных компьютеров, подключаемые к системной шине (ISA, VESA или PCI), или через внешние интерфейсы (параллельный интерфейс или USB). Структура изложения Глава 1 — вводная: в ней содержится обзор истории компьютеров, и приведены основные сведения о принципах организации современных вычислительных систем, в частности, обсуждаются системы счисления. В главе 2 рассмотрены: программная модель микропроцессора и системная архитектура вычислительной машины, реальный и защищенный режимы. После изложения основ организации микропроцессорных систем следует подробное изучение машинных инструкций микропроцессоров Intel с примерами. Изучению машинных инструкций посвящены главы 3—6. В главе 7 приведен разбор программы, включающей в себя вызовы функций BIOS и DOS. В частности, здесь обсуждаются функции обслуживания мыши, операции с файлами на дисках, ввод с клавиатуры и вывод на дисплей. Заметим, что средства, представленные в этой главе, позволяют разрабатывать полноценные программы. В данной главе также вводятся понятия прерывание и "горячая" клавиша. В главе 8 ъЪсуукпгтъя возможность совместного использования языков ассемблер и C/C++ — как с использованием встроенного ассемблера, так и за счет компоновки раздельно транслируемых программных модулей. В главе 9 представлена организация интерфейса с памятью и устройствами ввода-вывода на примере системы, построенной на базе микропроцессора 8086/8088. В главе 10 рассмотрено построение интерфейса с памятью с использованием схем дешифрации и устройств программируемой логики, с иллюстрацией на примерах контроля четности и динамической памяти. Обсуждается также организация памяти разрядностью 8, 16, 32 и 64 бита для процессоров семейства i80x86/Pentium. Глава 11 содержит подробности организации интерфейса с такими периферийными Устройствами, как PIAs, таймер, контроллеры дисплея и клавиатуры, последовательный интерфейс 16550, устройства аналого-цифрового и цифроаналогового преобразования, шаговый двигатель и двигатель постоянного тока. В главах 12 и 13 рассматриваются методы, обеспечивающие дополнительные возможности взаимодействия с устройствами ввода-вывода — в режиме прерываний и в 30 Введение режиме прямого доступа к памяти. Приведены примеры для принтера, часов реального времени, дисковой памяти и видеоадаптеров. Глава 14 содержит описание программной модели арифметического сопроцессора, от i8087 до Pentium, и возможностей его программирования, включая ММХ-рас-ширение процессора Pentium. Заметим, что на сегодня доля приложений, эффективно работающих без сопроцессора, невелика; вместе с тем он всегда в наличии, с момента появления 80486 со встроенным сопроцессором. В главе 15 обсуждается проектирование периферийных компонентов персонального компьютера, подключаемых через параллельный интерфейс или к системной шине (ISA, VESA или PCI). В главе 16 излагаются особенности микропроцессоров 80186/80188—80486, их отличия от 8086/8088. Здесь и в главе //обсуждаются нововведения, касающиеся устройства системной памяти, в частности, рассматриваются кэш-память в процессорах 80386 и 80486 и страничная организация памяти. В главе 18 подробно обсуждаются особенности процессоров Pentium и Pentium Pro. В главе 19 приведены основные сведения о процессорах Pentium II, Pentium III и Pentium 4, касающиеся вариантов исполнения, дополнительных возможностей и инструкций. В Приложении 1 представлен полный перечень функций DOS прерывания 1NT 21Н, функций BIOS прерывания INT ЮН и прерывания для обслуживания мыши, а также вызовов DPMI. Приложение 2 содержит список инструкций процессоров от 8086 до Pentium 4, с указанием времени выполнения и с примерами на языке ассемблера (показаны также соответствующие машинные коды). Команды, воздействующие на флаги процессора, указаны в Приложении 3. В Приложении 4 приведены ответы на контрольные вопросы к главам (выборочно). Благодарности Автор глубоко признателен за ценные замечания и предложения Роберту Дугласу из Мемфисского университета, Айзеку Гэнса из Калифорнийского государственного университета, Рейно Хентону из Южного университета (штат Лос-Анжелес) и Полу Уилеру из государственного университета Юты. Адрес для связи Авторский сайт находится по адресу http://membcrs.ec.net/brey. Там вы найдете сведения о других публикациях автора и множество ссылок на ресурсы, касающиеся микропроцессоров, персональных компьютеров, аппаратного и программного обеспечения. Раз в неделю на этом сайте проводятся уроки с обсуждением различных аспектов вычислительной техники. Некоторые сведения, не вошедшие в книгу, можно найти в разделе сайта под названием "Technical Section". ГЛАВА 1______________________ Введение в микропроцессоры компьютеры Введение В этой главе мы дадим краткий обзор микропроцессоров семейства Intel 80х86/Реп-tium, рассмотрим этапы развития вычислительной техники и обсудим основные функции микропроцессоров в современных компьютерных системах. Вы также ознакомитесь с терминами, применяемыми в этой области техники. Мы рассмотрим назначение и функции элементов вычислительной системы на блок-схеме. Также мы обсудим организацию памяти и системы ввода-вывода, хранение данных в памяти, типы данных и их представление. Числовые данные хранятся в формате целых чисел, чисел с плавающей точкой, двоично-десятичных (BCD — Binary Coded Decimal) значений; строковые данные представлены в коде ASCII (American Standard Code for Information Interchange). Темы главы В этой главе мы рассмотрим: □ компьютерные термины: байт, данные, основная память, дополнительная или иначе отображаемая (EMS — Expanded Memory System) и расширенная память (XMS — Extended Memory System), DOS, BIOS, система ввода-вывода и т. д.; □ этапы развития вычислительной техники и области применения современных компьютеров; поколения микропроцессоров семейства Intel 80x86/Pentium; □ блок-схему вычислительной системы и функции блоков; О работу микропроцессора и операции, которые он выполняет; □ структуру памяти персонального компьютера на базе микропроцессора Intel; выполнение преобразований между двоичными, десятичными и двоично-десятичными числами; Форматы целых чисел, чисел с плавающей точкой, двоично-десятичных и строковых данных. 32 Глава 1 1.1. Исторический обзор Проследим этапы развития вычислительной техники до современного уровня, представленного, в частности, микропроцессорами семейства Intel вОхвб’/Репишп1 2. Эпоха механики Идея вычислительной машины возникла задолго до открытия электричества и разработки элекгронных приборов. Первое механическое счетное приспособление — абака3 — было изобретено еще в V веке до н. э. в Древнем Вавилоне. Счет вели на бусах, пользовались этим приспособлением священники — для учета запасов зерна. Изменяясь незначительно, абаки — в виде знакомых вам бухгалтерских счетов — оставались в употреблении до недавнего времени. В 1642 г. математик Блез Паскаль построил первый механический автомат для вычислений4, на основе многоступенчатого редуктора с передаточным числом Ю во всех зубчатых парах. В этом устройстве при полном обороте ведущего десятизубого колеса ведомая шестерня (тоже десятизубая) прокручивается на один зуб, приводя в движение следующее колесо. Этот принцип положен в основу всех механических вычислителей (арифмометра, например), а также используется в автомобильных одометрах5. Кстати, известный язык программирования Pascal назван в честь Блеза Паскаля — выдающегося математика и автора первого в истории автоматического вычислителя. Механические калькуляторы вошли в обиход в начале XIX века, когда о промышленном использовании электричества еще не было и речи; пока что не изобрели еще даже лампочку накаливания. Но и в ту пору, на заре вычислительной техники люди мечтали о механизмах, выполняющих вычисления по программе, в отличие от арифмометров, способных лишь к отдельным арифметическим действиям. Первая попытка создания подобной машины была предпринята профессором математики Кембриджского университета Чарльзом Бэббиджем (при участии графини Августы Ады Байрон). Факт этой разработки был обнаружен по сохранившимся документам только в 1937 г. Бэббидж начал создание своей так называемой аналитической машины в 1823 г. по заказу Королевского астрономического общества Великобритании. Машина предназначалась Королевскому флоту для обсчета навигационных таблиц. Предполагалось, что аналитическая машина Бэббиджа будет хранить до 1 80x86 — сокращенная запись, которая включает 8086, 8088, 80186, 80286, 80386 и 80486 процессоры. 2 Pentium — официально зарегистрированное наименование процессоров корпорации Intel начиная с процессоров пятого поколения 80586. 3 Abacus — стол, столешница; подставка для драгоценной утвари (лат). По-видимому, в Древнем Риме этим словом называли пришедшую из Греции "саламинскую доску" — счетную дощечку с бороздками для камешков. С той поры "абакой" называют все аналогичные приспособления, даже если камешки, шарики, кукурузные зерна или вишневые косточки не лежат на доске, а подвешены на веревочках, как в китайском суан-пабе или в русском "дощатом счете". — Пер. 4 Чертежи и описание подобного устройства были обнаружены еще в рукописях Леонардо да Винчи (1452-1519 гг >. - Пер. 5 Одометр — прибор для счета оборотов колеса; при помощи его измеряется длина пути. — Ред. 34 Глава 1 лосс", вероятно, за ее габариты. Хотя с помощью этой машины англичанам удалось взломать шифры Энигмы7, к решению других задач этот компьютер не был приспособлен, поскольку программа в нем была фиксированной. Рис. 1.1. Компьютер Z3, разработанный Конрадом Цузе, с тактовой частотой 5,33 Гц (фотография предоставлена его сыном Хорстом Цузе) Первый программируемый электронный компьютер общего назначения был создан в 1946 г. в университете штата Пенсильвания8 9. Это гигантское устройство под названием ENIAC (Electronic Numerical Integrator and Calculator) содержало более 17000 электронных ламп и 900 км проводов. При массе более 30 т эта машина выполняла около 100000 операций в секунду. Для изменения программы нужно было переключить провода на коммутаторе, напоминающем пульт оператора телефонной станции. На эту операцию обычно уходило несколько человеко-дней. Кроме того, вычислительная машина ENIAC требовала частного ремонта, ввиду короткого срока службы электронных ламп. Ситуация изменилась в 1948 г., когда фирмой Bell Laboratories был создан первый транзистор?. А в 1958 г. Джек Килби из фирмы Texas Instruments изобретает интегральную микросхему. В последующее десятилетие на основе этого изобретения создаются микросхемы резисторно-транзисторной логики (RTL — Resistor-to-Transistor Logic). В 1971 г. фирма Intel выпускает свой первый микропроцессор i4004, с появлением которого началось бурное развитие вычислительной техники. Развитие инструментов программирования С появлением программируемых вычислительных машин возникли и начали развиваться средства программирования. Как мы уже говорили, программирование первой электронной вычислительной системы выполнялось за счет перекоммутации 7 Немецкая механическая шифровальная машина. — Пер. 8 Авторы — Джон Маучли и Джон Преспер Эккерт. — Пер. 9 Авторы — Джоном Бардин, Уолтер Браттейн и Уильям Шокли. — Пер. Введение в микропроцессоры и компьютеры 33 тысячи 20-значных десятичных чисел, а работать будет по изменяемой программе, что позволило бы настраивать ее на различные вычислительные задачи. Для ввода данных предполагалось использовать перфокарты — те самые перфокарты, что в 50-х и 60-х годах XX века будут применяться в большинстве электронных вычислительных машин (ЭВМ). Полагают, что идею ввода с перфокарт Бэббидж позаимствовал у французского изобретателя Жозефа Жаккара (Joseph Jacquard), создавшего в 1801 г. ткацкий станок, в котором узор ткани определялся набором перфокарт. После многих лет работы Бэббидж понял, что аналитическая машина технически неосуществима. Число требуемых деталей приблизилось к 50000, и для сборки надежно работающего механизма требовалась недостижимая по тем временам точность изготовления6. Эпоха электричества В XIX веке с появлением электрического двигателя, созданного по замыслу Майкла Фарадея, механические калькуляторы оснащаются электроприводом. Электромеханические калькуляторы, ставшие необходимой принадлежностью любой конторы, просуществовали до начала 70-х годов XX века, когда был выпущен электронный калькулятор Бомара. Калькулятор Монро, созданный примерно в то же время, невыгодно отличался от модели Бомара своими габаритами — он был размером с кассовый аппарат. Применение перфокарт, изобретенных Жаккаром, получает дальнейшее развитие в 1889 г., когда Герман Холлерит разработал механическую машину с электрическим приводом. Эта машина могла считать и упорядочивать информацию, заданную на перфокартах. Правительство США настолько заинтересовалось этим изобретением, что Холлериту поручили применить его устройство для хранения данных переписи населения 1890 г. и для составления таблиц на основе этих данных. В 1896 г. Холлерит создает фирму по разработке машин для обработки таблиц с использованием перфокарт. После объединения фирмы Холлерита с рядом других компаний была образована широко известная ныне корпорация IBM (International Business Machines). И перфокарты Холлерита, и принятая им 12-битная кодировка данных десятилетиями успешно применялись в вычислительной технике. В 1941 г. происходит событие, завершившее эпоху электромеханических вычислительных устройств. Немецкий изобретатель Конрад Цузе создает первую в мире электронную вычислительную машину Z3 — результат проведенных им исследований в области электроники, начатых еще в 30-х годах. Релейный компьютер Z3, показанный на рис. 1.1, применялся в разработке летательных аппаратов (ракет и самолетов) для Германской армии во время Второй мировой войны. Недавно, когда был открыт доступ к военным архивам Великобритании тех лет, выяснилось, что уже с 1943 г. англичане использовали электронный компьютер для расшифровки секретных кодов противника. Этот компьютер — изобретение Алана Тьюринга — был собран на электронных лампах. Автор назвал свою машину ”Ко 6 В 1812 г., задолго до разработки аналитической машины, Бэббидж создает проект механического компьютера для решения полиномиальных уравнений, действующая модель которого была продемонстрирована Британскому правительству в 1822 г. — Пер. 2 Зак 384 34 Глава 1 лосс", вероятно, за ее габариты. Хотя с помощью этой машины англичанам удалось взломать шифры Энигмы7, к решению других задач этот компьютер не был приспособлен, поскольку программа в нем была фиксированной. Рис. 1.1. Компьютер Z3, разработанный Конрадом Цузе, с тактовой частотой 5,33 Гц (фотография предоставлена его сыном Хорстом Цузе) Первый программируемый электронный компьютер общего назначения был создан в 1946 г. в университете штата Пенсильвания8 9. Это гигантское устройство под названием ENIAC (Electronic Numerical Integrator and Calculator) содержало более 17 000 электронных ламп и 900 км проводов. При массе более 30 т эта машина выполняла около 100000 операций в секунду. Для изменения программы нужно было переключить провода на коммутаторе, напоминающем пульт оператора телефонной станции. На эту операцию обычно уходило несколько человеко-дней. Кроме того, вычислительная машина ENIAC требовала частного ремонта, ввиду короткого срока службы электронных ламп. Ситуация изменилась в 1948 г., когда фирмой Bell Laboratories был создан первый транзистор?. А в 1958 г. Джек Килби из фирмы Texas Instalments изобретает интегральную микросхему. В последующее десятилетие на основе этого изобретения создаются микросхемы резисторно-транзисторной логики (RTL — Resistor-to-Transistor Logic). В 1971 г. фирма Intel выпускает свой первый микропроцессор i4004, с появлением которого началось бурное развитие вычислительной техники. Развитие инструментов программирования С появлением программируемых вычислительных машин возникли и начали развиваться средства программирования. Как мы уже говорили, программирование первой электронной вычислительной системы выполнялось за счет перекоммутации 7 Немецкая механическая шифровальная машина. — Пер. 8 Авторы — Джон Маучли и Джон Преспер Эккерт. — Пер. 9 Авторы — Джоном Бардин, Уолтер Браттейн и Уильям Шокли. — Пер. Введение в микропроцессоры и компьютеры 35 электрических цепей. Это было не слишком неудобно, и вскоре появляются языки, предназначенные для управления компьютерами. Первым языком программирования был машинный язык. В машинном языке программа представлена комбинацией двоичных чисел — нулей и единиц, образующих инструкции, которые хранятся в памяти машины10. Хотя использовать машинный язык было проще, нежели изменять схему коммутации, все же для задания большого количества двоичных цифр по-прежнему требовалось много времени. С появлением в 50-х годах таких вычислительных систем, как UNIVAC, в употребление входит язык ассемблера, позволяющий сократить трудоемкость рутинной работы по кодированию машинных инструкций. Язык ассемблера позволяет программисту использовать мнемонические обозначения инструкций, например, add, взамен набора двоичных чисел вроде 01000111. В 1957 г. появляется первый язык высокого уровня — Flow-Matic, разработанный Грейс Хоппер. Вскоре выходит в свет язык Fortran (FORniula TRANslator), созданный фирмой IBM для программирования ее систем. Этот язык, позволяющий автоматизировать кодирование формул11, используется учеными и в настоящее время. Через год появляется еще один язык такого уровня — Algol (ALGOrithmic Language). Первым по-настоящему успешным языком, получившим широкое распространение, стал язык Cobol (COmmon Business Oriented Language), ориентированный на коммерческие приложения. В последние десятилетия популярность этого языка уменьшилась, хотя в некоторых крупных коммерческих системах он по-прежнему играет важную роль. Еще одна популярная система программирования для информационных систем — это генератор программ отчетов RPG (Report Program Generator), который позволяет, в частности, описывать задачу посредством форм ввода и форм вывода. С того времени появилось множество других языков программирования. Наиболее известные из них — Basic, C/C++, Pascal и Ada. Языки Basic и Pascal, первоначально созданные для обучения программированию, вышли за пределы учебных заведений и сейчас применяются во многих коммерческих компьютерных системах. Наиболее простым для освоения из перечисленных языков является, пожалуй, Basic. По некоторым оценкам 80% программ для компьютерных систем написано именно на этом языке. Не так давно появилась известная версия этого языка под названием Visual Basic, упростившая разработку программ для операционной системы (ОС) Windows. Не исключено, что Visual Basic со временем потеснит такие языки, как C/C++ и Pascal. Для разработки управляющих программ в научных приложениях используются языки C/C++ и, реже, Pascal. Оба эти языка, в особенности C/C++, позволяют полностью контролировать вычислительную систему и среду программирования. Во многих случаях C/C++ обеспечивает функции низкого уровня, которые раньше можно было реализовать только на языке ассемблера. Тем не менее язык ассемблера по-прежнему сохраняет свои позиции. Так, большинство компьютерных игр почти 10 Идея вычислительной машины, хранящей инструкции в памяти наряду с данными, предложена математиком Джоном фон Нейманом. Любой компьютер, построенный по этому принципу, относится к классу машин фон Неймана. (Хотя Бэббидж пытался реализовать эту идею задолго до Неймана.) — Пер. 11 Точнее, арифметических выражений с плавающей точкой. — Пер. полностью написано на этом языке. Ассемблер используется совместно с языками C/C++ и Pascal там, где требуется высокая эффективность в управлении вычислительной системой. Язык Ada применяется, в основном, в системе Министерства обороны США. Этот язык назван в честь графини Августы Ады Байрон — соавтора аналитической машины Бэббиджа. Эпоха микропроцессоров Первый микропроцессор — Intel 4004 — представлял собой 4-разрядный однокристальный микроконтроллер с набором команд, состоящим из 45 инструкций, и с адресным пространством 4096 тетрад (тетрада образуется четырьмя двоичными разрядами, или битами). Производительность этого микропроцессора была относительно невысокой (0,05 млн оп./сек), т. к. в качестве элементной базы использовались Р-канальные полевые транзисторы. Главное преимущество в сравнении с вычислительной машиной на электронных лампах ENIAC, весившей около 30 т, состояло, конечно, в том, что микропроцессор весил в миллион раз меньше — около 28 г. Новому устройству нашлось немало интересных применений: компьютерные видеоигры, что было внове, и небольшие системы управления. Программирование i4004 было трудным из-за его низкой разрядности и жестких ограничений по скорости и памяти. Микропроцессор i4040, выпущенный следующим и последним в ряду 4-разрядных микропроцессоров Intel, отличался лишь большей скоростью. Из аналогичных разработок других фирм наиболее известны устройства компании Texas Instruments, например 4-разрядный микропроцессор TMS-1000. Четырехразрядные микропроцессоры выпускаются до сих пор и применяются в небольших системах управления, например, в микроволновых печах. Эти процессоры широко применяются в калькуляторах — данные там представлены в формате двоично-десятичных чисел (каждая десятичная цифра хранится в 4 битах), а обработка данных некритична по времени. В 1971 г., когда выгода от производства микропроцессоров стала очевидной, фирма Intel выпустила микропроцессор i8008 — усовершенствованный восьмиразрядный вариант микропроцессора i4004. Адресное пространство памяти в i8008 было расширено до 16 Кбайт12, а число инструкций достигло 48. Тем не менее, вскоре выяснилось, что и этих возможностей недостаточно для новых практических приложений. В 1973 г. Intel разрабатывает более совершенный 8-разрядный микропроцессор — i8080, а через шесть месяцев фирма Motorola выпускает 8-разрядный микропроцессор МС6800. В табл. 1.1 перечислены фирмы, участвовавшие в разработке и выпуске первых 8-разрядных микропроцессоров. Компании Intel и Motorola до сих пор являются ведущими в разработке новых микропроцессоров. Фирма Zilog занимается, в основном, только производством микропроцессоров; в области разработок их больше интересуют микроконтроллеры. Фирма Rockwell больше не выпускает процессоров, a Motorola, прежде занимавшая половину рынка микропроцессоров, практически сдала свои позиции в этой области. 12 Байт — единица, соответствующая 8 битам, а приставка К — 210 = 1024. иие в микропроцессоры и компьютеры Таблица 1.1- Первые 8-разрядные микропроцессоры и их производители 37 '"^^Гпроизводитель Название микропроцессора FairChild F-8 Intel 8080 MOS Technology 6502 Motorola MC6800 National Semiconductor IMP-8 Rockwell International PPS-8 Zilog Z-8 Особенности микропроцессора 18080 По сравнению с i8008 процессор i8080 позволяет адресовать больше памяти и располагает дополнительными инструкциями. Скорость выполнения инструкций возросла в десять раз. Если сложение на i8008 требует 20 мкс, что составляет 50000 оп./сек, то аналогичная операция на i8080 занимает всего 2 мкс, что соответствует 500000 оп./сек. Поскольку i8080, в отличие от 18008, является TTL-совмес-тимым13, интерфейсы вычислительных систем на базе i8080 становятся проще и дешевле. Адресное пространство, расширенное в четыре раза, составляет теперь 64 Кбайт. Можно считать, что эпоха микропроцессоров началась именно с i8080, благодаря предпринятым в нем улучшениям. Кстати, в 1974 г. фирмой MITS был выпущен первый персональный компьютер Альтаир 880014. Номер 8800 в названии отражает наличие процессора i8080, что не нарушало авторских прав корпорации Intel. Для этого компьютера были написаны транслятор с языка ассемблера и интерпретатор языка Basic. Ассемблер был разработан корпорацией Digital Research, которая в дальнейшем выпустила операционную систему DR-DOS, а автором интерпретатора Basic является Билл Гейтс, в будущем основатель корпорации Microsoft. Микропроцессор 18085 В 1977 г. корпорация Intel объявила о выпуске обновленной версии i8080 — микропроцессора i8085. На этом разработка 8-разрядных микропроцессоров Intel была закончена. Микропроцессор i8085, отличаясь от i8080 лишь в деталях, обладал более высоким быстродействием: сложение теперь выполнялось не за 2 мкс, а за 1,3 мкс. К дополнительным преимуществам i8085 относятся: встроенный тактовый генератор (с более высокой тактовой частотой) и встроенный системный контроллер. Повышение уровня интеграции в микропроцессоре i8085 положительно отразилось на стоимости и его эксплуатационных характеристиках. Было продано около 100 млн микросхем i8085 — причем, только фирмой Intel; а если принять в расчет сторонних производителей, то более 200 млн экземпляров. Приложения, в которых использу-Тся микропроцессоры i8085, по-видимому, будут востребованы и в будущем. Мик 14 ТП" (Transistor-Transistor Logic) — транзисторно-транзисторная логика. дик°МПЛеКТ 8800 входил процессор i8080, блок питания, лицевая панель с множеством ин-атоР°в и запоминающее устройство емкостью 256 байт. — Пер. 38 Глава 1 ропроцессор Z-80, разработанный фирмой Zilog и совместимый с i8085 на уровне машинных команд, был раскуплен в количестве 500 млн экземпляров. Таким образом, программы, написанные в системе команд i8O85/Z-8O, выполняются на 700 млн микропроцессоров! Современные микропроцессоры В 1978 г. Intel выпускает микропроцессор i8086, а год спустя — i8088. Оба микропроцессора — 16-разрядные, с временем выполнения инструкций около 400 нс, что составляет 2,5 MIPs (Millions of Instruction Per second) или иначе 2,5 млн оп./сек. Кроме того, эти процессоры позволяют адресовать до 1 Мбайт15 памяти, что в 16 раз больше предела, достижимого в системах на базе i8085. Благодаря лучшим возможностям новые микропроцессоры во многих приложениях вытеснили i8085. Еще одно нововведение, ускоряющее цикл отработки инструкций в i8086/88, — это буфер предвыборки, или очередь команд размером от 4 до 6 байт. Во всех последующих поколениях микропроцессоров Intel также используется очередь команд все возрастающего объема. В результате увеличения объема памяти и введения дополнительных инструкций в 18086/88 область применения микропроцессоров существенно расширилась. В систему команд были впервые введены инструкции умножения и деления, а общее число команд возросло до 20 00016 (в i8008 их было 45, а в i8085 — 246). Микропроцессоры i8086/88 за количество и сложность системы команд получили название CISC — Complex Instruction Set Computers (процессор с полным набором команд). Новые возможности появились и в программировании — не только благодаря изобилию команд, но и в связи с увеличением количества и разрядности внутренних регистров. В основном, 16-разрядные микропроцессоры обязаны своим появлением и развитием всевозрастающим требованиям к объему памяти. Популярность продукции фирмы Intel вновь подтвердилась в 1981 г., когда корпорация IBM приняла решение о выпуске персонального компьютера на базе микропроцессора i8088. Эффективное функционирование таких приложений, как электронные таблицы, текстовые процессоры, программы для проверки правописания и электронные справочники, требовало памяти гораздо большего размера, чем 64 Кбайт, которое было в ранних 8-разрядных микропроцессорах. Для подобных приложений системы на базе 16-разрядных процессоров i8086/88 обеспечивали доступ к 1 Мбайтам памяти. Конечно, вскоре и этого оказалось недостаточно, что ощущалось, например, при работе с большими базами данных. Поэтому в 1983 г. Intel выпускает усовершенствованный вариант i8086 — микропроцессор i80286. Микропроцессор i80286 Микропроцессор i80286, хотя и повторяет во многом i8086/88, позволяет адресоваться уже 16 Мбайтам памяти вместо 1 Мбайт. В систему команд включен ряд инст 15 I Мбайт соответствует 1 024 Кбайтам или 1 048 576 байтам = 220 байт. 16 Вероятно, автор принимает в расчет всевозможные сочетания операндов, отражающиеся в машинных кодах команд. Число мнемоник команд в языке ассемблера значительно меньше. — Пер. введение в микропроцессоры и компьютеры 39 рукций для управления дополнительным объемом памяти (15 Мбайт). Увеличена до 8 МГн тактовая частота, так что некоторые инструкции теперь выполняются не более чем за 250 нс. Внесены изменения в алгоритм выполнения инструкций, в результате чего время их выполнения уменьшилось, в большинстве случаев, в 8 раз. Микропроцессор i80386 С появлением новых приложений продолжают возрастать требования к скорости вычислений, разрядности данных и объему оперативной памяти. В 1986 г. Intel выпускает 32-разрядный микропроцессор i80386, весьма существенно отличающийся от своих 16-разрядных предшественников. Этот процессор был первым из удачно разработанных микропроцессоров фирмы Intel с 32-разрядной шиной адреса и данных. (Тому предшествовала разработка 32-разрядного микропроцессора iapx-432.) При 32-разрядной шине адреса открывается доступ к 4 Гбайт17 оперативной памяти. В памяти такого объема можно разместить около миллиона страниц текста в коде ASCII. Среди модификаций микропроцессора i80386 отметим i80386SX, с 16-раз-рядной шиной данных и 24-разрядной шиной адреса, что позволяло адресоваться к 16 Мбайтам памяти, а также i80386SL/80386SLC, с 16-разрядной шиной данных и адресным пространством 32 Мбайт, доступным посредством 25-разрядной шины адреса. В процессоре i80386SLC также имелась внутренняя кэш-память, что позволяло обрабатывать данные с более высокой скоростью. В 1995 г. Intel выпускает микропроцессор i80386EX, с 16-разрядной шиной данных, 26-разрядной шиной адреса памяти и 24-разрядной шиной адреса портов ввода-вывода. Этот процессор получил название встроенного персонального компьютера (embedded PC), поскольку в его микросхему были включены необходимые компоненты IBM PC/AT (например, контроллер регенерации динамической памяти). К приложениям, требующим высокой скорости вычислений и большого объема памяти, относятся, в частности, программные системы с графическим интерфейсом пользователя (Graphic User Interface — GUI). Современные графические дисплеи содержат порядка 256000 и более точек (пикселов). Даже самые простые дисплеи VGA (Variable Graphics Array) имеют разрешение 640 точек по горизонтали и 480 по вертикали. Для смены отображения на экране каждая из этих 307 200 точек должна быть заново нарисована, что требует от процессора высокой скорости (и часто предполагает наличие ускоренного видеоадаптера). К подобным программам относится, в частности, семейство операционных систем Microsoft Windows18. Вместо аббревиатуры GUI часто используется сокращение WYSIWYG — What You See Is What You Get (что видим, тем и располагаем). Для процессора i80386 характерна не только более высокая скорость и разрядность. Управление памятью в i80386 реализовано на аппаратном уровне, а не на программном, как в предшествующих микропроцессорах, что значительно ускоряет работу с памятью и сокращает необходимый для этого код. По системе команд микропроцессор i80386 совместим снизу вверх с i8088/86/286. Введены дополнительные инструкции для работы с 32-разрядными регистрами и для 17 1 Гбайт соответствует 1 024 Мбайтам или 1 073 741 824 байтам e 230 байт. 18 Windows — это официально зарегистрированное наименование операционной системы корпорации Microsoft, среди которых в настоящее время распространены: Windows 95, Windows 98, Windows 2000, Windows ME и Windows XP. 40 Глава 1 управления памятью. Кстати, инструкции для управления памятью, включенные в систему команд i80286, совместимы и с i80386. Микропроцессор I80486 В 1989 г. корпорация Intel выпускает микропроцессор i80486, объединивший в одной микросхеме процессор i80386, арифметический сопроцессор i80387 и внутреннюю кэш-память размером 8 Кбайт. В структуру центрального процессора (Central Processor Unit — CPU) были внесены изменения, позволяющие выполнять около половины инструкций не за два такта, а за один. В результате при тактовой частоте 50 МГц время выполнения таких инструкций составляло 25 нс. По сравнению с i80386 производительность i80486, работающего на той же тактовой частоте, выше на 50%. В дальнейшем был выпущен вариант микропроцессора i80486 с удвоенной тактовой частотой — i80486DX2. В нем базовая тактовая частота (33 МГц) использовалась при доступе к оперативной памяти, а на удвоенной частоте (66 МГц) выполнялись внутренние инструкции. В микропроцессоре i80486DX4 частота была утроена: базовая частота для доступа к памяти по-прежнему составляла 33 МГц, а выполнение инструкции шло на частоте 100 МГц. (Производительность микропроцессора i80486DX4 приблизительно равна производительности микропроцессора Pentium, работающего на частоте 60 МГц.) Также, в i80486DX4 был удвоен объем кэшпамяти — размер ее достиг 16 Кбайт. Аналогичное устройство с тактовой частотой шины данных 40 МГц и внутренней тактовой частотой 120 МГц было выпущено фирмой Advanced Micro Devices (AMD). Фирмой Intel были выпущены и другие разновидности i80486, известные как под названием Overdrive-процессоров. Процессор Overdrive — это i80486DX с удвоенной тактовой частотой, предназначенный для замены i80486SX или варианта i80486DX, работающего на частоте материнской платы. Например, при замене i80486SX, работающего на тактовой частоте 25 МГц, на Overdrive-процессор, частота шины данных остается прежней, но внутренние инструкции выполняются на частоте 50 МГц. В табл. 1.2 приведены сведения о микропроцессорах фирм Intel и Motorola, с указанием разрядности шины данных, размерности кэш-памяти и адресного пространства оперативной памяти. Таблица 1.2. Адресное пространство и разрядность шины данных процессоров Intel и Motorola Фирма-производитель Микропроцессор Разрядность шины данных (бит) Адресное пространство и размер кэш-памяти Intel 8048 8 2 Кбайт (встроенная память) 8051 8 8 Кбайт (встроенная память) 8085А 8 64 Кбайт 8086 16 1 Мбайт 8088 8 1 Мбайт 8096 16 8 Кбайт (встроенная память) 80186 16 1 Мбайт 80188 8 1 Мбайт введение в микропроцессоры и компьютеры 41 Таблица 1.2 (окончание) Фирма-производитель Микропроцессор Разрядность шины данных (бит) Адресное пространство и размер кэш-памяти 80251 8 16 Кбайт (встроенная память) 80286 16 16 Мбайт 80386ЕХ 16 64 Мбайт 80386DX 32 4 Гбайт 80386SL 16 32 Мбайт 80386SLC 16 32 Мбайт + 1 Кбайт кэш 80386SX 16 16 Мбайт 80486DX/DX2 32 4 Гбайт + 8 Кбайт кэш 80486SX 32 4 Гбайт + 8 Кбайт кэш 80486DX4 32 4 Гбайт + 16 Кбайт кэш Pentium 64 4 Гбайт + 16 Кбайт кэш Pentium Overdrive (Р24Т), на замену i80486 32 4 Гбайт + 16 Кбайт кэш Pentium Pro processor 64 64 Гбайт + 16 Кбайт Ll-кэш + 256 Кбайт 12-кэш Pentium II 64 64 Гбайт + 32 Кбайт Ll-кэш + 512 Кбайт 12-кэш Pentium II Xeon 64 64 Гбайт + 32 Кбайт Ll-кэш + 512 Кбайт или 1 Мбайт 12-кэш Pentium III. Pentium 4 64 64 Гбайт + 32 Кбайт И-кэш + 256 Кбайт 12-кэш Motorola 6800 8 64 Кбайт 6805 8 2 Кбайт 6809 8 64 Кбайт 68000 16 16 Мбайт 68008Q 8 1 Мбайт 68008D 8 4 Мбайт 68010 16 16 Мбайт 68020 32 4 Гбайт 68030 32 4 Гбайт + 256 байт кэш 68040 32 4 Гбайт + 8 Кбайт кэш 68050 32 Не был выпущен 68060 64 4 Гбайт + 16 Кбайт кэш PowerPC 64 4 Гбайт + 32 Кбайт кэш 42 Глава 1 Микропроцессор Pentium Микропроцессор Pentium, выпущенный в 1993 г., продолжает линию процессоров i80386/80486. (Названия Р5 и 80586, первоначально присвоенные этому микропроцессору, не были приняты официально ввиду сложностей патентования.) Первоначальные реализации процессора Pentium работали на тактовой частоте 60 и 66 МГц, с производительностью ПО млн оп./сек. Имелись также модификации, работающие на полуторной (100 МГц, 150 млн оп./сек) и на удвоенной частоте (120 и 133 МГц). Самый быстрый вариант Pentium, выпущенный фирмой Intel, работал на частоте 233 МГц. Общий объем кэш-памяти в Pentium составлял 16 Кбайт, в отличие от базовых версий процессора i80486, причем кэш данных (8 Кбайт) был выполнен отдельно от кэша инструкций (8 Кбайт). Адресное пространство в Pentium составляет 4 Гбайт. Частота шины данных по сравнению с i80486 возросла вдвое (60/66 МГц вместо 33 МГц), а ее размерность расширена до 64 бит. Расширение размерности шины данных дает значительное преимущество при работе с действительными числами удвоенной точности, что требуется, например, в приложениях, использующих векторную графику. Позднее система команд Pentium была расширена группой инструкций MMX (MultiMedia eXtention), ориентированных на мультимедийные приложения; правда, вопреки ожиданиям, MMX-команды не получили широкого практического применения. Затем появился долгожданный вариант Pentium Overdrive (Р24Т), имеющий целью модернизацию старых систем на базе микропроцессора i80486. Overdrive-процессор с частотой 63 МГц позволял заменить i80486DX2, работающий на частоте 50 МГц, а Overdrive с частотой 83 МГц позволял заменить i80486DX2 в системе, работающей на частоте 66 МГц. Последний вариант по скорости занимал промежуточное положение между обычными процессорами Pentium, работающими на частотах 66 и 75 МГц. По-видимому, наиболее существенная особенность Pentium — это наличие сдвоенного ядра процессора^, способного одновременно выполнять пару взаимнонезависимых инструкций. В результате, на Pentium возможно выполнение двух инструкций всего за один такт. Процессоры, в которых используется принцип одновременного выполнения, называются суперскалярными. Еще одно нововведение, также способствующее повышению производительности процессора Pentium при отработке циклов, — блок предсказания переходов. Кроме того, в Pentium имеется встроенный сопроцессор, который работает в пять раз быстрее аналогичного сопроцессора, входящего в микропроцессор i80486. Не исключено, что благодаря перечисленным особенностям процессоры семейства Pentium вытеснят некоторые из /?Л£С-процессоров19 20, способных выполнять одну инструкцию за один такт. Заметим, что некоторые RISC-процессоры, выполненные по суперскалярной технологии, выполняют за один такт более одной инструкции. Например, процессор PowerPC, RISC-процессор, выпущенный фирмами Motorola, Apple и IBM, имеет сдвоенное ядро центрального процессора и один сопроцессор. На базе этого RISC-процессора создан персональный компьютер Apple Macintosh с превосходной производительностью —• хотя и недостаточной для программной эмуляции современных микро 19 Ядро процессора — это основная составляющая часть процессора, осуществляющая выполнение команд. В ядро входит арифметико-логическое устройство (АЛУ) и конвейер команд. 20 RISC (Reduced Instructions Set Computer) — процессор с сокращенным набором команд. — Пер. введение в микропроцессоры и компьютеры 43 процессоров Pentium. По результатам тестов, производительность эмулятора IBM PC на Apple Macintosh соответствует производительности микропроцессора Intel 80486SX на частоте 25 МГц. Вместе с тем, число персональных вычислительных систем на базе процессоров Intel на сегодня достигло 260 млн (по данным 1998 г. на 96% этих систем установлена ОС Windows). В то же время, число экземпляров Apple Macintosh достигло всего лишь 6 млн Отсюда можно сделать вывод, что потребность в микропроцессорах Intel в ближайшем будущем сохранится. Для сопоставления скоростей различных процессоров фирма Intel ввела показатель iCOMP (Intel Comparative Microprocessor Performance), выводимый по результатам тестов SPEC92, ZD Bench и Power Meter. На рис. 1.2 приведены значения iCOMPl для процессоров Intel, от i80386SX 16 до Pentium 200 (число справа — тактовая частота в МГц). Примечание_______________________________________________________ Символом "звездочка" (*) на рис. 1.2 отмечены процессоры Pentium Overdrive; в процессоры Pentium 166/200 включены команды мультимедийного расширения ММХ (MultiMedia extension). Pentium 200 Pentium 166 Pentium 133 Pentium 120 Pentium 100 Pentium 90 Pentium 75 Pentium 83* Pentium 66 Pentium 60 Pentium 63* 486 DX4 100 486 DX4 75 486 DX2 66 486 DX 50 486 DX2 50 486 SX2 50 486 DX 33 486 SX2 40 486 SX 33 486 DX 25 486 SX 25 486 SX 20 386 DX 33 386 SX 33 386 DX 25 386 SX 25 386 SX 20 386 SX16 0 100 200 400 600 800 1000 1200 1400 1600 1800 Примечание: *= Pentium OverDrive 1810 Рис. 1.2. Результаты тестов микропроцессоров по показателю iCOMPl К моменту выпуска Pentium Pro и Pentium II фирма Intel использует вместо iCOMl показатель iCOMP2. Значение iCOMP2 для процессоров предыдущих поколений 44 Глава 1 составляет I/IO значения iCOMPl. Например, процессор со значением iCOMPl = 1 000 характеризуется iCOMP2 = 100. Кроме того, несколько изменилась методика тести- Примечание: * В Pentium II Celeron кэш-память отсутствует. Для преобразования приведенных индексов iCOMP2 в индексы ЮОМРЗ их следует умножить на коэффициент 2,568. Рис. 1.3. Результаты тестов микропроцессоров по показателю iCOMP2 введение в микропроцессоры и компьютеры 45 Примечание_________________________________________________________ Символом "звездочка" (*) на рис. 1.3 отмечен процессор Pentium II Celeron; для получения показателя ЮОМРЗ значения ЮОМР2 следует умножить на 2,568. Celeron — это официально зарегистрированное наименование микропроцессора корпорации Intel. Pentium Pro Микропроцессор Pentium Pro (первоначальное название — Р6) выпущен Intel в конце 1995 г. Он содержит 21 млн транзисторов, ядро, состоящее из трех конвейеров, и арифметический сопроцессор. Первые экземпляры Pentium Pro работали на частоте 150 и 166 МГц. В дополнение к кэш-памяти первого уровня (L1) объемом 16 Кбайт (8 Кбайт кэш данных и 8 Кбайт кэш команд) в Pentium Pro введен кэш второго уровня (L2) объемом 256 Кбайт. Поскольку процессор имеет три конвейера, возможно выполнение до трех команд за один такт, причем, в отличие от Pentium, одновременное выполнение возможно даже при конфликтующих сочетаниях инструкций. Обработка 32-разрядных данных в Pentium Pro оптимизирована, поскольку этот процессор предназначался для построения серверов. Адресное пространство увеличено до 64 Гбайт; ширина шины адреса — 36 бит. Pentium II и Pentium Хеоп Микропроцессор Pentium II, выпущенный в 1997 г., стал совершенно новым для процессоров Intel с точки зрения конструкции. Процессор выполнен не в виде интегральной микросхемы, а в виде компактной печатной платы21, на которой дополнительно установлена кэш-память второго уровня (L2). В Pentium кэш L2 работал на частоте системной шины — 60/66 МГц. В Pentium II кэш L2 (объемом 512 Кбайт) и процессор объединены в модуле Pentium II. Кэш L2 в этой системе функционирует на частоте 133 МГц. Процессор в составе модуля Pentium II — это по сути Pentium Pro (с поддержкой ММХ), но без встроенной кэш-памяти второго уровня. Pentium II, при внутренней тактовой частоте 26^/333 МГц, выполнял доступ к памяти на частоте всего 66 МГц. В 1998 г. тактовая частота шины данных была поднята до 100 МГц; это значение использовалось в Pentium II 350/400/450, что потребовало уменьшения времени цикла обращения к динамической памяти с 10 до 8 нс. В середине 1998 г. корпорация Intel объявила о выпуске новой версии Pentium 11 — Pentium Хеоп. Новый процессор был специально разработан для серверов и сильно нагруженных рабочих станций. Процессор Хеоп, по сравнению с Pentium II, обладает большей кэш-памятью: L1 — 32 Кбайт, L2 — 512 Кбайт, или 1 Мбайт, или даже 2 Мбайт. Некоторые особенности процессора Pentium Хеоп — он работает с чипсетом22 440GX, и на его основе возможно построение 4-процессорной системы (в этом подобен Pentium Pro). Выпуск Pentium II Хеоп в дополнение к Pentium 11 означал изменение в стратегии корпорации Intel: выполнять каждый новый процессор в двух версиях — профессиональной и бытовой. 21 Тип корпуса — картридж с односторонним контактом (Single Edge Contact — SEC). — Пер. 22 Чипсет — это набор микросхем, устанавливаемых на материнскую плату и предназначенных для обеспечения обмена данными между процессором, оперативной памятью и различными внешними устройствами. — Ред. введение в микропроцессоры и компьютеры 47 должен был появиться в 1999 г., но из-за ряда технических проблем этого так и,не произошло. В октябре 1999 г. корпорация Intel заявила о разработке нового 64-раз-рядного процессора под названием Itanium. Процессор появился на рынке в середине 2001 г. Архитектура процессора была построена на основе технологии EPIC (Explicitly Parallel Instruction Computing — вычисления с явным параллелизмом команд), которая по уровню параллелизма значительно превосходит традиционную архитектуру Р6. Процессор был анонсирован для серверов масштаба предприятий, компьютеров, работающих с большими базами данных, систем автоматизированного проектирования, высокопроизводительных вычислений и т. л. Начиная с середины 2002 г. корпорация Intel выпустила второго представителя семейства процессоров Itanium — микропроцессор Itanium 2 с тактовой частотой 900 МГц и 1,2 ГГц и с объемом интегрированной кэш третьего уровня (L3), равного 1,5 и 3 Мбайт. Рис. 1.4 иллюстрирует основные особенности структур процессоров Intel — от 80486 до Pentium 4. Ядро Ядро Сопроцессор Кэш L1 16 Кбайт Pentium Pentium II, Pentium III и Pentium 4 Рис. 1.4. Структурные отличия микропроцессоров 80486, Pentium Pro, Pentium II, Pentium III и Pentium 4 46 Глава 1 Pentium III Хотя в процессоре Pentium III применено более быстродействующее ядро, это по-прежнему все тот же процессор Р6 (Pentium Pro). Конструктивные версии Pentium III — в корпусе S.E.C.C.2 (Single Edge Contact Catridge), устанавливаемый в Slot 1, и в корпусе PPGA (Plastic Pin Grid А(гау), под названием flip-chipPGX, устанавливаемый в Socket 370. Последний вариант по своей конструкции напоминает процессор Pentium и, по утверждению корпорации Intel, имеет меньшую стоимость. В обоих вариантах тактовая частота достигает 1 ГГц. Кэш-память в первом варианте составляет 512 Кбайт, а во втором — 256 Кбайт. Вместе с тем, в первом варианте кэш работает на половинной частоте, так что указанные варианты Pentium III различаются по скорости незначительно. Частота системной шины в обоих вариантах составляет 100 МГц (Intel Celeron использует частоту 66 МГц). В остальных магистралях, предназначенных для соединения с конгроллерами, такими как контроллер PCI, контроллер памяти или контроллер AGP, применяется тактовая частота 100 или 133 МГц. Pentium 4 Последнее детище корпорации Intel, микропроцессор Pentium 4, появился в конце 2000 г. В нем сохранена прежняя архитектура Р6. Выигрыш достигнут за счет подъема тактовой частоты до 1,3/1,4/1,5 ГГц, что стало возможным благодаря прогрессу технологии микросхем. Чипсет, который обеспечивает работу Pentium 4, использует технологию памяти RAMBUS взамен прежней технологии SDRAM (Synchronous Dynamic Random Access Memory). Интересно отметить, что размер кэш-памяти первого уровня сокращен до 8 Кбайт. Как выяснилось, 8 Кбайт вполне достаточно для первой модели Pentium 4; в дальнейшем объем L1, возможно, будет увеличен до 32 Кбайт. Кэш L2 остался прежним, как в Pentium III — 256 Кбайт. Переход в Pentium 4 к ’’медной" технологии позволил существенно повысить тактовую частоту шин. (Медь является лучшим проводником, но технология ее применения в микропроцессорах была освоена не так давно.) В результате тактовая частота системной шины уже в первых версиях Pentium 4 достигла и превысила 400 МГц. Будущее микропроцессоров Можно утверждать, что в ближайшие годы микропроцессорам Intel успех гарантирован. Не исключено, что технология RISC-процессоров также будет усовершенствована, но более вероятным представляется выпуск нового CISC-процессора в результате исследований, проводимых совместно фирмами Intel и Hewlett-Packard. Тогда CISC-процессоры и разработанное для них программное обеспечение сохранят свои позиции. Новые технологии будут основаны на параллельной обработке и прямом межпроцессорном взаимодействии. Если в суперскалярной архитектуре взаимодействующие процессоры используют все-таки общий набор регистров, то в новой технологии каждый из процессоров будет иметь свой набор регйстров, но эти наборы будут доступны всем процессорам. Предполагается, что параллельность работы процессоров будет обеспечиваться полностью на аппаратном уровне, без программной поддержки. Еще в 1994 г. корпорация Hewlett-Packard объявила о начале работы над 64-разряд-ными процессорами. Первый подобный процессор под кодовым названием Merced введение в микропроцессоры и компьютеры 47 должен был появиться в 1999 г., но из-за ряда технических проблем этого так и,не произошло. В октябре 1999 г. корпорация Intel заявила о разработке нового 64-раз-рядного процессора под названием Itanium. Процессор появился на рынке в середине 2001 г. Архитектура процессора была построена на основе технологии EPIC (Explicitly Parallel Instruction Computing — вычисления с явным параллелизмом команд), которая по уровню параллелизма значительно превосходит традиционную архитектуру Р6. Процессор был анонсирован для серверов масштаба предприятий, компьютеров, работающих с большими базами данных, систем автоматизированного проектирования, высокопроизводительных вычислений и т. л. Начиная с середины 2002 г. корпорация Intel выпустила второго представителя семейства процессоров Itanium — микропроцессор Itanium 2 с тактовой частотой 900 МГц и 1,2 ГГц и с объемом интегрированной кэш третьего уровня (L3), равного 1,5 и 3 Мбайт. Рис. 1.4 иллюстрирует основные особенности структур процессоров Intel — от 80486 до Pentium 4. Ядро Ядро Сопроцессор Кэш L1 16 Кбайт Pentium Pentium II, Pentium III и Pentium 4 Рис. 1.4. Структурные отличия микропроцессоров 80486, Pentium Pro, Pentium II, Pentium III и Pentium 4 48 Глава 1 1.2. Персональные вычислительные системы на базе микропроцессоров Современные вычислительные системы по сравнению с первыми ламповыми ком» пьютерами изменились неузнаваемо. Машины, некогда занимавшие площадь в сотни квадратных метров, теперь, благодаря развитию микропроцессоров, при невиданной ранее производительности помещаются на письменном столе. Даже процессор 180486 обладает вычислительной мощностью, превосходящей возможности больших вычислительных машин (mainframe23) 80-х гг. стоимостью около миллиона долларов. Многие фирмы, такие как, например, DEC (Digital Equipment Corporation), давно закончили выпуск mainframe в пользу микропроцессорных систем. В этом разделе мы рассмотрим структуру персональных вычислительных систем на базе микропроцессоров, в частности, состав памяти и характеристики операционной системы. На рис. 1.5 показана блок-схема персонального компьютера. Представленная блок-схема отражает структуру произвольной вычислительной системы, от больших вычислительных машин до современных микрокомпьютеров. Системная память Внешние устройства Динамическая память RAM (DRAM) 8086 Статическая память RAM (SRAM) 8088 Кэш 80186 Постоянная память (ROM) 80188 Флэш-память 80286 EEPROM 80386 SDRAM 80486 RAMBUS Pentium Pentium Pro Pentium II Pentium III Pentium 4 Принтер СОМ-порты Накопители на гибких дисках Винчестеры Мышь Привод CD-ROM Плоттер Клавиатура Дисплей Стример Сканер Привод DVD Рис. 1.5. Блок-схема микропроцессорной вычислительной системы Компьютер состоит из трех основных блоков, соединенных между собой шинами. Шина — это набор проводников для передачи однотипной информации; например, шина адреса, которая содержит 20 и более проводников, передает в блок памяти адрес ячейки памяти. Рассмотрим назначение блоков, показанных на рис. 1.5. 23 Mainframe — (мэйнфрейм) главный компьютер вычислительного центра. Обычно это многопользовательская большая супермини- или мини-ЭВМ. — Ред. Введение в микропроцессоры и компьютеры 49 Память и система ввода-вывода Структура памяти, показанная на рис. 1.6, одинакова для всех компьютерных систем, построенных на базе процессоров Intel, от i8088 до Pentium 4. Рис. 1.6. Структура памяти персонального компьютера Память разделяется на три части: память для транзитных программ — ТРА (Transient Program Area) или иначе стандартная память (Conventional memory), системная область и расширенная память — XMS (Extended Memory System). Наличие XMS определяется типом микропроцессора. В системах PC24 и XT25, построенных на микропроцессорах i8086/88, расширенная память отсутствует. В компьютерах класса IBM PC/XT область ТРА составляет 640 Кбайт, системная область или иначе верхняя па-мять UМА (Upper Memory Area) занимает 384 Кбайт — итого I Мбайт. Область памяти размером I Мбайт, расположенная в начале адресного пространства, иногда называется реальной (real), поскольку она доступна в реальном режиме любому микропроцессору семейства Intel 80x86. Расширенная память доступна для процессоров от 80286 до Pentium 4. Персональные компьютеры на базе этих процессоров называются машинами класса АТ26. Системы PS/1 и PS/2, выпущенные фирмой IBM, также имеют доступ к расширенной памяти. Их иногда называют ISA- или EISA-машинами (ISA — Industry Standard Architecture, EISA - Extended ISA) по названию используемой системной шины. Для вычислительных систем PS/2 соответственно принято название МСА-систем (Micro Channel27 Architecture). PC (Personal Computer) товарная марка корпорации IBM для обозначения персональных компьютеров. 25 Х*Г _ /р; (extended Technology) товарная марка корпорации IBM для обозначения персональных омпьютеров, изготовленных по расширенной технологии. АТ Ко (Advanced Technology) товарная марка корпорации IBM для обозначения персональных 27 Пьютеров, изготовленных по современной передовой технологии. Cro“ChanneI — торговый знак корпорации IBM. — Пер. 50 Глава 1 В системах на базе Pentium—Pentium 4 вместо шины ISA используется, в основном, шина PC/ (Peripheral Component Interconnect). С появлением микропроцессора i80286 расширенная память становится доступна, ее размер пока ограничивается 15 Мбайтами. В персональных компьютерах на базе 80386DX, 80486 и Pentium мак-симальный размер XMS составляет 4095 Мбайт — в дополнение к I Мбайтам реальной памяти. Начиная с Pentium Pro, предельный объем XMS-памяти достигает 4 или 64 Гбайт. В ISA-машинах имеется 8-разрядная периферийная шина для обмена с 8-разрядными внешними устройствами системы PC/XT. В машинах класса АТ, которые также называются ISA-машинами, используются 16-разрядная периферийная шина и процессор от i80286 и выше. Шина EISA шириной 32 бита не нашла широкого применения; сейчас ее можно обнаружить в некоторых старых машинах на базе i80386DX или i80486. Заметим, что все новые версии шины ISA были совместимы с предшествующими. Так, 8-битная плата расширения могла работать со всеми шинами ISA: 8- и 16-битной ISA и 32-битной EISA. Аналогично, внешнее устройство с 16-разрядным интерфейсом могло функционировать с 16-разрядной шиной ISA или с 32-разрядной шиной EISA. Во многих персональных компьютерах на базе i80486 использовалась локальная шина VESA (Video Electronic Standard Association), или точнее VL-bus. Локальная шина позволяет подключать дисковые накопители и видеосистему к микропроцессору отдельно от других устройств. За счет локальности шины реализуется 32-битный интерфейс на частоте процессора. Последняя версия шины VESA поддерживала 64-битный обмен данными с Pentium, что, несмотря на возможность конкуренции локальной шины (VL-bus) с шиной РС1, не вызвало особого интереса у разработчиков персональных вычислительных систем. Шины ISA и EISA работают на частоте всего лишь 8 МГц, что ограничивает производительность системы при работе с дисками и видеоадаптерами. Тактовая частота шины PCI — 33 МГц, разрядность составляет 32 или 64 бита. Эта шина была специально разработана для систем на базе Pentium. В последние модели компьютеров включены две новые шины. Первая — это USB (Universal Serial Bus, что означает универсальная последовательная шина). Интерфейс USB предназначен для подключения к микропроцессору периферийных устройств (клавиатуры, мыши, модема, звуковой карты и т. д.) через последовательный канал связи типа витой пары. С уменьшением числа проводов система становится дешевле и надежней. Кроме того, звуковая система может теперь использовать собственный источник питания, отдельный от PC, что позволяет снизить уровень шума. На сегодняшний день интейфейс USB обеспечивает скорость передачи 10 Мбит/с; в стандарте USB-2 предполагается повышение скорости до 100 Мбит/с. Еще одна из новых шин — AGP (Advanced Graphics Port) — предназначена для обмена данными с видеоадаптером. Частота шины AGP составляет 66 МГц, разрядность — 64 бита, что обеспечивает рекордную скорость обмена — 533 Мбайт/с. Разработка этой шины была обусловлена появлением накопителей DVD (Digital Versatile Disk или Digital Video Disk — универсальный цифровой диск или цифровой видеодиск). ТРА В области транзитных программ ТРА, или иначе в стандартной памяти, размешаются операционная система DOS (Disk Operating System) и другие программы для управления компьютерной системой. В ТРА также хранятся все приложения DOS — 51 111Лв в микропроцессоры и компьютеры ------------- ie и неактивные в текущий момент. Размер ТРА составляет 640 Кбайт. После a**’ MS-DOS 1.x для приложений остается около 628 Кбайт свободной памяти. заГтим, что Ранние версии DOS требовали больше оперативной памяти, оставляя ^аМС0^ениЯМ не более 530 Кбайт. Вместо MS-DOS (Microsoft Disk Operating System) nPHJlT использоваться совместимая с ней операционная система, например, РС-MOS (Personal Computer Disk Operating System) (разработка фирмы IBM). ОС P. dows и OS/2 также обеспечивают выполнение приложений DOS. Операционная WLreMa DOS (Disk Operation System) организует и контролирует данные дисковых С копителей, а также предоставляет прикладным программам средства для управле-Н я устройствами ввода-вывода. ОС Windows обеспечивает аналогичные функции Windows-приложений. Структура ТРА (стандартной памяти) в компьютере с установленной операционной системой MS-DOS показана на рис. 1.7. 9FFFF 9FFF0 Транзитный модуль COMMAND.COM Свободная память 08Е30 08490 02530 01160 00700 00500 00400 00000 Резидентный модуль COMMAND.COM Драйверы MSDOS.SYS IO.SYS Область данных DOS Область данных BIOS Таблица векторов прерываний Рис. 1.7. Структура ТРА при наличии операционной системы MS-DOS На карте памяти, представленной на рис. 1.7, показаны многочисленные области занятые системными программами, данными и драйверами, а также обширная 0 ласть памяти для прикладных программ. Слева проставлены адреса, представление в шестнадцатеричной системе — на границам областей памяти. Шестнадцате-чное число — это обозначение числа в системе счисления с основанием 16, с по-оц1ью знаков 0—9 и A—F. Чтобы отличать шестнадцатеричные числа от десятич-иЫх’ в конце шестнадцатеричных обычно записывается буква Н (hexadecimal), апРимер, 1234Н. Возможно и такое обозначение — 0x1234. и Ласть векторов прерываний обеспечивает приложениям доступ к функциям DOS Bbq05060^ системы ввода-вывода (BIOS — Basic Input Output System). Базовая система ^-вывода представляет собой набор программ, записанных в энергонезависимой 52 Глава 1 памяти — либо в постоянном запоминающем устройстве (ПЗУ), иначе по-английски ROM (Read-Only Memory), либо во флэш-памяти. Программы BIOS обеспечивают управление основными устройствами ввода-вывода. Заметим, что флэш-память относится к типу EEPROM (Electrically Erasable Programmable Read-Only Memory), т. e. является электрически стираемой, причем перезапись содержимого возможна средствами самого же компьютера. Напротив, запись EPROM выполняется на отдельном устройстве, которое называется программатором EPROM (Erasable Programmable Read-Only Memory), или в заводских условиях. Программы BIOS находятся в системной области памяти, структура которой рассмотрена далее. В областях данных BIOS и DOS хранятся данные, обеспечивающие прикладным программам доступ к устройствам ввода-вывода и настройкам системы. Подробнее состав областей данных BIOS и DOS см. в Приложении 1. Эти данные находятся в памяти, доступной для чтения и записи, называемой ОЗУ (Оперативное Запоминающее Устройство), или иначе по-английски RAM (Random Access Memory), и поэтому могут быть изменены прикладными программами. Модуль расширения BIOS, хранящийся в файле IO.SYS (MS-DOS) или IBMBIO.COM (PC-DOS), загружается в память с диска при запуске соответствующей операционной системы. В нем содержатся подпрограммы, обеспечивающие в DOS работу с клавиатурой, дисплеем, принтером и с другими часто используемыми устройствами ввода-вывода. Подпрограммы IO.SYS связывают DOS с процедурами ROM BIOS. После загрузки DOS занимает две области памяти. Первая, длиной 16 байт, находится на вершине ТРА. Эту область занимает транзитный модуль командного процессора COMMAND.COM. Вторая, значительно большего размера, находится в начале ТРА. Размер и расположение областей DOS зависят от версии и конфигурации DOS. Например, если DOS загружается в область высокой памяти (НМА — High Memory Area), находящуюся выше 1 Мбайт и доступную при установке драйвера Hl MEM.SYS в реальном режиме работы процессора, то большая часть ТРА остается свободной для прикладных программ. Следует отметить, что высокая память (НМА) доступна только в системах с микропроцессором i80286 и выше. Размер области драйверов и количество таких областей зависят от настройки системы. Драйвер — это программа для управления периферийным устройством: мышью, электронным диском, ручным сканером, накопителями CD-ROM (Compact Disk Read-Only Memory) или DVD (Digital Versatile Disk или Digital Video Disk — универсальный цифровой диск или цифровой видеодиск). Инсталлируемые драйверы обеспечивают управление устройствами, дополняющими вычислительную систему. Чаще всего драйверам дают расширение SYS, например MOUSE.SYS; в DOS 3.2 и выше используется также расширение ЕХЕ, например EMM386.EXE. Поскольку персональные системы настроены все по-разному, количество драйверов и суммарный размер занимаемой ими памяти — величины непостоянные. Хотя эти файлы не нужны для операционной системы Windows, они все же используются в сеансах DOS, даже в среде Windows. Загрузка драйверов в Windows определяется файлом SYSTEM.INI. В новых версиях Windows для хранения информации о системе и загружаемых драйверах используется системный реестр, содержимое которого доступно посредством утилиты REGEDIT.EXE. Программа COMMAND.COM, или иначе командный процессор, выполняет команды, вводимые с клавиатуры в режиме командной строки. Например, при вводе команды DIR программа COMMAND.COM отображает на экране названия дисковых фай Введение в микропроцессоры и компьютеры 53 лов текущего каталога. Ни в коем случае не следует удалять программы COMMAND.COM и IO.SYS, пытаясь освободить память для прикладных программ — компьютер не будет работать. Эти программы могут быть установлены заново при помощи утилиты SYS.COM из каталога DOS (или из каталога WIN DOWS/COM MAN D). В оставшиеся области ТРА загружаются прикладные программы (текстовые процессоры, электронные таблицы, системы автоматизации проектирования и т. п.) на время их выполнения. В ТРА также помещаются резидентные программы (TSR — Terminate and Stay Resident), которые после их завершения остаются в памяти и активизируются либо нажатием "горячей" клавиши, либо наступлением какого-либо иного события, связанного с аппаратными или программными прерываниями. Пример TSR-программы — калькулятор, активизируемый нажатием комбинации клавиш, например, <Alt>+<C>. TSR-программы такого типа часто называют всплывающими (pop-up), поскольку при активизации они оказываются "наверху", вытесняя прерванную программу. Если установлена система Windows, то она использует часть ТРА для хранения управляющей информации, применяемой для доступа к расширенной памяти. Системная область Системная область, или иначе верхняя память (UMA — Upper Memory Area), хотя и меньше по размеру, чем ТРА, но также является очень важной. Она, как правило, содержит программы, хранящиеся ПЗУ (ROM) или в энергонезависимой флэш-памяти, и данные в памяти, предназначенной как для чтения, так и для записи (RAM). Содержимое системной области показано на рис. 1.8. FFFFF F0000 ЕОООО ROM BIOS ПЗУ Basic (в ранних моделях PC) Свободная область ПЗУ винчестеров и сетевых карт С8000 СОООО воооо АОООО Рис. 1.8. Содержимое системной области ПЗУ видео-BIOS Видеопамять (текстовый режим) Видеопамять (графический режим) В начале системной области (по адресам АООООН—C7FFFH) находятся видеопамять и программы для обслуживания видеосистемы — видео-BIOS, хранящейся в ПЗУ (ROM) или во флэш-памяти. Размер используемой памяти зависит от типа видео 54 Глава/j адаптера — CGA (Color Graphics Adapter), EGA (Enhanced Graphics Adapter) или’ VGA (Variable Graphics Array). В общем случае, видеопамять в диапазоне адресов. A0000H—AFFFFH предназначена для графических данных; текстовые данные хранятся по адресам B0000H—BFFFFH. Некоторые из недавно выпущенных видеоадаптеров могут адресовать области и большего размера в области верхней памяти; эта возможность поддерживается Windows. Некоторые видеоадаптеры обращаются к области видеопамяти Windows в диапазоне адресов Е1800000Н—E2FFFFFF. Управление видеоадаптерами в DOS обеспечивается видеофункциями BIOS, расположенными в ПЗУ (ROM) или во флэш-памяти по адресам C0000H—C7FFFH. Адаптеры MFM- и RLL-винчестеров28 29 содержат постоянную память с программой низкоуровневого форматирования, расположенной по адресу С8005Н. Размер ПЗУ и его положение в адресном пространстве зависят от типа винчестера. Большинство IDE-винчестеров не содержат встроенного программного обеспечения в ПЗУ, но во многих SCSI-винчестерах оно имеется. Память в диапазоне адресов С8000Н—DFFFFH чаще всего свободна. Ее используют для отображения страниц дополнительной1* или иначе отображаемой памяти (Expanded Memory System — EMS) в PC/XT или для работы с верхней памятью (UMA) в АТ-системах. Доступ к отображаемой памяти обеспечивается посредством верхней памяти за счет страничного отображения. Кадр страницы (page frame), или иначе окно размером 64 Кбайт, расположенный в свободной области верхней памяти (LIMA), например, по адресам D0000H—DFFFFH, отображает такой же объем дополнительной памяти блоками по 16 Кбайт. Отображение страниц при использовании EMS показано на рис. 19. Отображаемая память (EMS) 64 Кбайт Страница 255 64 Кбайт Страница 2 64 Кбайт Страница 1 64 Кбайт Страница О Рис. 1.9. Отображение страниц при использовании EMS 28 Винчестеры MFM и RLL в PC уже не используются. MFM-винчестеры были стандартом в IBM PC/XT и АТ 286; наиболее известные из них — Seagate ST255 (21,4 Мбайт) и ST251 (42,8 Мбайт). - Пер. 29 Память называется дополнительной, поскольку ранее для расширения объема памяти доступного для DOS свыше 1 Мбайт, применялся отдельный дополнительный адаптер памяти со схемами коммутации банков по 64 Кбайт, вставляемый в слот расширения на материнской плате. — Ред. 55 ние в микропроцессоры и компьютеры ьзование EMS стандартизировано спецификацией LIM 4.0, разработанной ИсП°Л и Lotus, Intel и Microsoft. Недостатком EMS является ее низкая скорость, Ф^Р^вленная тем, что переключение блоков требует вмешательства EMS-драйвера, о^^вдением процессора i80386 необходимость в EMS отпала30 (разве что для за-С п° старых игр, написанных под DOS), и в большинстве вновь разрабатываемых ПУска ний отображаемой (Expanded) памятью лучше не пользоваться. прил° E0000H—EFFFFH в первых моделях IBM PC были заняты ПЗУ с интерпре-языка Basic. В новых системах эта область свободна и используется в качестве RAM. п ледние 64 Кбайт системной области памяти заняты ROM BIOS — по адресам FO000H—FFFFFH. Здесь находятся тестовая программа POST (Power On Self Test), которая при включении компьютера проверяет все его важнейшие компоненты, ооцедуры для обслуживания основных устройств ввода-вывода компьютерной системы, кроме дисплея (видеофункции находятся в отдельном ROM BIOS, начиная с адреса C0000H), программа CMOS Setup, предназначенная для установки параметров BIOS и конфигурации компьютера, а также программа начальной загрузки системы Bootstrap. В первой части BIOS по адресам F0000H—F7FFFH обычно находятся программы, выполняемые при включении компьютера для его начального тестирования и настройки; вторая часть содержит процедуры базовой системы ввода-вывода. После загрузки системы адреса F0000H—F7FFFH можно использовать в качестве блоков верхней памяти UMA, при установленном драйвере EMM386.EXE. С этой же целью может быть занят блок памяти в диапазоне адресов B0C00H— B7FFFH (видеопамять монохромного дисплея). Пространство адресов системы ввода-вывода Пространство адресов системы ввода-вывода PC составляет 64 Кбайт. Адрес порта ввода-вывода, или иначе номер порта, подобен адресу памяти, но используется для обращения к периферийному устройству. Периферийные устройства обеспечивают взаимодействие процессора с внешним миром. Пространство адресов системы ввода-вывода в 64 Кбайт позволяет обращаться к 65 536 различным восьмибитным внешним устройствам, и на сегодня этого более чем достаточно. На рис. 1.10 показано распределение адресов ввода-вывода для типичной компьютерной системы. В области адресов системы ввода-вывода можно выделить два больших фрагмента. Рагмент ниже адреса 0400Н зарезервирован для системных устройств, многие из 04плРЫХ показаны на Рис- 1-Ю- Пространство ввода-вывода в диапазоне адресов Н—FFFFH оставлено для дополнительных устройств, хотя некоторые из совре-нных материнских плат используют и эту область. В общем случае, адреса из диакона 0000H-00FFH имеют отношение к компонентам материнской платы; а диа-Ров %°Т 01 МН до 03FFH предназначен для адресации регистров съемных адапте-Пе0 (Разделение области ввода-вывода на границе 0400Н связано с применением в Дилг?1Х моделях PC шины ISA, которая не позволяет адресовать порты за пределами вазона 0000Н—03FFH.) 30 Про ПоэтССС°РЬ1’ начиная с i80386, имеют встроенные средства имитации коммутации банков памяти. (ЕХ( в компьютерах, использующих такие процессоры, можно использовать расширенную nded) память для имитации отображаемой (Expanded) памяти. — Ред. 56 FFFF Область адресов расширения системы ввода-вывода 03F8 03F0 03D0 0378 0320 02F8 0060 0040 0020 0000 _________СОМ1___________ Контроллер накопителя на гибких дисках Адаптер CGA LPT1 Контроллер жестких дисков COM2 ~ Программируемый периферийный интерфейс (микросхема 8255) Таймер (микросхема 8254) Контроллер прерываний Контроллер DMA Рис. 1.10. Внешние устройства PC в адресном пространстве системы ввода-вывода Операционная система DOS Операционной системой (ОС) называется комплекс программ, управляющих работой компьютера. В дальнейшем изложении под операционной системой в основном будет подразумеваться DOS (Disk Operation System) — самая распространенная система, которая применяется, согласно недавней публикации в журнале PC Magazine, в 85% персональных компьютеров — с учетом того, что DOS входит в состав Windows. Операционная система хранится на гибком диске или на одном из разделов жесткого диска (локального или сетевого). В ряде персональных вычислительных систем DOS хранится в постоянной памяти (пример — персональный компькь тер фирмы Tandy Corporation). При включении компьютера операционная система загружается, т. е. копируется в оперативную память с локального или сетевого диска. Будучи загруженной в память, DOS организует функционирование компьютерной системы, в том числе устройств ввода-вывода и прикладных программ. В конце загрузки считывается файл CONFIG.SYS, в котором задана конфигурация системы и указаны драйверы, которые следует дополнительно установить. Заметим, что этот файл не влияет на настройку операционной системы Windows, которая определена отдельно в системном реестре Windows. В примере l.l показан один из вариантов содержимого CONFIG.SYS для DOS. Файл CONFIG.SYS при работе с Windows обычно содержит меньше операторов. Пример 1.1. Вариант содержимого файла CONFIG.SYS для DOS REM DOS CONFIG.SYS FILE DEVICE=C:\DOS\HIMEM.SYS DEVICE=C:\DOS\EMM386.EXE NOEMS i=c800-efff 57 С:\LASERLIB\SONY_CDU.SYS C:\DOS\SETVER.EXE :\MOUSE1\MOUSE.SYS я микропроцессоры и компьютеры BgegSUH------------ DOS8^ fILES2°io B°f^C-\DOS\COMMAND,COM C:\DOS\ /Е:2048 /Р S^igh u nrVlCEHlGH ^XlCEHlGH C:\DOS\SETVEK.EXE °EVICEHIGH c: \MOUSE1 \MOUSE. SYS lastdrive=f и пвый оператор в примере 1.1 начинается с комментария, заданного командой rem mark). В результате, первый оператор при обработке файла CONFIG.SYS игнори-veTCH. Второй оператор задает загрузку драйвера расширенной и высокой (НМА) памяти HIMEM.SYS. Драйвер — это программа, которая управляет периферийным устройством или вмешивается в работу других программ; драйверы загружаются при обработке файла CONFIG.SYS — до запуска прикладных программ. Высокая память (НМА) — это память по адресам 100000Н— 10FEFFH, примыкающая к памяти, ограниченной I Мбайтом, и доступная в системах с процессором 80286 и выше. Размер высокой памяти составляет 64 Кбайт — 16 байт. В следующих операторах CONFIG.SYS указано число файлов, буферов и стеков, а также количество блоков управления файлами, необходимых для работы прикладных программ. Требуемые значения могут быть указаны в документации на прикладную программу либо они автоматически записываются в CONFIG.SYS при инсталляции программного обеспечения. Если в качестве основной операционной системы используется Windows, установки CONFIG.SYS учитываются ею при запуске DOS-приложений. Доступ к блокам высокой памяти (НМА) в системах на базе процессора 80386 и выше предполагает загрузку менеджера отображаемой памяти (EMS) — драйвера EMM386.EXE. Загрузка драйвера EMM386.EXE позволяет запускать программы, разработанные для компьютеров на базе 80286 и использующие EMS-память. В примере 1.1 вызов EMM386.EXE задан с несколькими параметрами. Аргумент i*c8oo-efff определяет диапазон адресов области в стандартном адресном пространнее, предназначенной для блоков верхней памяти (Upper Memory Block — UMB). ^еРед заданием значений для параметра i следует убедиться, что эта область памяти пересекается с системными программами или с данными в ROM/RAM. Параметр То°18 отключает эмуляцию дополнительной памяти. Если требуется доступ к EMS, вместо параметра noems следует задать параметр ram со значением числа байт ДУет ИРеНН°Й памяти’ напРимеР> пам 1024 задает резервирование 1 Кбайт EMS. Сле-Пам Напомнить’ что на сегодняшний день дополнительная или иначе отображаемая браж Ь В Рольшинстве систем не используется. Расположение кадра страницы ото-МестаСМ0Й памяти (окна) задает параметр frame; например, frame=dooo определяет страницы в Wecax D0000H—DFFFFH. Начиная с DOS 6.0 доступ к EMS (Vi *ен Даже ПРИ указании параметра NOEMS, посредством драйвера VCPI ВацИ1^ Control Program Interface). Драйвер VCP1 распределяет блоки EMS по требо-°своб0Текущей программы (т. е. динамически), а после завершения программы сам (Dqc блоки. В Windows аналогичную функцию выполняет интерфейс DPMI rotected Mode Interface). 58 Глава 1 Продолжим рассмотрение примера 1.1. Оператор dos=umb указывает системе предусмотреть блок верхней памяти (LIMB) для использования DOS. Операторы files=30 и buffers=io определяют, соответственно, максимальное количество одновременно открытых файлов и число буферов для чтения-записи данных файлов. Команда shell обеспечивает настройку и указывает местонахождение файла командного процессора для DOS. В примере 1.1 в качестве командного процессора указан COMMAND.COM (он используется по умолчанию) с опциями Е:2048 и /р. Опция Е:2048 задает размер области памяти для переменных окружения в байтах. В переменных окружения хранится информация, доступная для всех приложений. Например, оператор set темр=с:\темр означает, что временные данные рекомендуется записывать в каталог, указанный в переменной temp (в данном случае, это каталог C:\TEMP). Команда set, предназначенная для установки переменной окружения, может быть включена в файл AUTOEXEC.BAT или вызвана из командной строки DOS. Переключатель /р указывает, что командный процессор должен быть загружен в память раз и навсегда, т. е. используется резидентный режим работы командного процессора. Без опции /р он будет загружаться каждый раз при возвращении к командной строке; хотя это позволяет высвободить часть памяти, частая загрузка командного процессора приводит к ускоренному износу диска и отнимает время. Следующий оператор — dos=high — задает загрузку DOS в высокую память (НМЛ), которая становится доступной после загрузки драйвера HIMEM.SYS. Команда devicehigh задает загрузку указанного драйвера или программы в блок верхней памяти, распределенный драйвером EMM386.EXE. В соответствии с примером 1.1 три драйвера (SONY_.CDU.SYS, SETVER.EXE и MOUSE.SYS) будут помещены в верхнюю память с адреса С8000Н. Последний оператор в примере — команда lastdrive — задает максимальное число дисков в системе, точнее, букву, обозначающую последний логический диск. Каждый диск требует наличие буфера в оперативной памяти, поэтому не следует задавать лишнего в этой команде. Также в CONFIG.SYS может быть указана загрузка драйверов PRINT.SYS, ANSI.SYS и других программ, функционирующих в качестве драйверов. Обычно файлы драйверов обозначаются расширением SYS. В ранних версиях DOS корректировка CONFIG.SYS требовала осторожности — ошибка могла привести к блокировке системы. В DOS 6.0 и выше отработка файла CONFIG.SYS может быть отключена нажатием комбинации клавиш <Ctrl>+<C> при загрузке, что позволяет впоследствии исправить ошибку. После завершения обработки файла CONFIG.SYS компьютер выполняет команды, заданные в пакетном файле AUTOEXEC.BAT (AUTOmatic EXECution BATch). Если AUTOEXEC.BAT отсутствует, то компьютер при загрузке запрашивает время и дату. Пример 1.2 иллюстрирует один из вариантов файла AUTOEXEC.BAT. Команды, заданные в нем, можно было бы ввести и в режиме командной строки, но файл AUTOEXEC.BAT избавляет пользователя от необходимости задавать команды вручную после каждой загрузки системы. Этот файл используется также при вызове сеанса DOS из Windows. ................................................................y..........T.v_7....... Г Пример 1.2;. Вариант файла AUTOEXEC.BAT : j PATH С:\DOS;С:\;С:\MASM\BIN;С:\MASM\BINB\;С:\UTILITY SET BLASTER=A220 17 DI ТЗ Введение в микропроцессоры и компьютеры 59 SET INCLUDE=C:\MASM\INCLUDE\ SET HELPFILES=C:\MASM\HELP\*.HLP SET INIT=C:\MASM\INIT\ SET ASMEX=C:\MASM\SAMPLES\ SET TMP=C:\MASM\TMP SET SOUND=C:\SB LOADHIGH C:\LASERLIB\MSCDEX.EXE /D:SONY_001 /L:F /M:10 LOADHIGH C:\LASERLIB\LLTSR.EXE ALT-Q LOADHIGH C:\DOS\FASTOPEN C:=256 LOADHIGH C:\DOS\DOSKEY /BUFSIZE=1024 LOADHIGH C:\LASERLIB\PRINTF.COM DOSKEY GO=C:\WINDOWS\WIN.EXE GO Оператор path в примере 1.2 задает путь поиска исполняемого файла при вводе имени программы в командной строке. Порядок просмотра каталогов при поиске определяется последовательностью их перечисления в операторе path. Предположим, в командной строке введено имя PROG. Поиск начнется в каталоге C:\DOS, продолжится в корневом каталоге С:\, затем в C:\MASM\B1N и т. д., пока программа PROG не будет найдена. Если поиск окажется безуспешным, командный процессор COMMAND.COM выведет соответствующее сообщение. Команда set, как мы уже говорили, вводит переменную окружения и устанавливает ее значение. Обычно переменным присваиваются пути, имена программ и/или опции. Переменные окружения доступны всем исполняемым программам, в частности, на них можно ссылаться из командных или иначе пакетных^ (batch) файлов. Первая команда set в примере устанавливает переменную окружения для звуковой карты, вторая присваивает переменной INCLUDE значение пути C:\MASM \INCLUDE\. Заметим, что переменные записываются в память, зарезервированную командой shell в файле CONFIG.SYS (см. опцию е:2048 в примере 1.1). Команда loadhigh, или сокращенно lh загружает программу в блоки UMB (Upper Memory Block) верхней памяти, сформированные драйвером EMM386.EXE. Предпоследняя команда в примере — doskey — определяет макрокоманду go; после чего ввод слова GO в командной строке будет восприниматься как команда запуска Windows - C:\WINDOWS\WIN.EXE. Микропроцессор Основу компьютера составляет микросхема микропроцессора. Микропроцессор (МП), иначе называемый центральный процессор (ЦП) (Central Processing Unit — CPU), — это элемент, управляющий вычислительной системой. Управление памятью и системой ввода-вывода осуществляется посредством электрических сигналов, передаваемых по линиям соединений, которые называются шинами. Подавая сигналы на шину, микропроцессор выбирает порт ввода-вывода или ячейку памяти для обмена данными. Микропроцессор выполняет эти действия в соответствии с инструкциями, которые хранятся в памяти. 31 Командные или иначе пакетные файлы должны иметь расширение ВАТ (от BATch). — Ред. 60 Глава 1 На микропроцессор возложены следующие задачи: □ обмен данными с памятью и портами ввода-вывода; □ выполнение основных арифметических и логических операций; □ принятие решений — переключение между последовательностями инструкций по определенным признакам. В совокупности, выполнение этих простых задач позволяет выполнять вычисления любой сложности. Достоинство микропроцессора заключается в его способности выполнять за секунду сотни миллионов инструкций. Инструкции хранятся в оперативной памяти, что позволяет достаточно быстро изменять исполняемую программу. Напомним, что концепция хранимой программы была принята при разработке аналитической машины Бэббиджа. В табл. 1.3 приведены арифметические и логические операции микропроцессоров Intel. Эти элементарные операции позволяют решать весьма сложные задачи. Данные для операций, или операнды, находятся во внутренних регистрах процессора и/или в памяти. Размерность операндов — байт (8 бит), слово (16 бит) или двойное слово (32 бита). Заметим, что элементарные операции над двойными словами возможны только в 32-разрядных процессорах. Начиная с 180486, микросхема микропроцессора включает в себя сопроцессор, обеспечивающий выполнение сложных арифметических операций над числами с плавающей точкой. В компьютерах на базе i8086—i80386 арифметический сопроцессор не входил в микросхему процессора, а устанавливался как дополнительный компонент. Таблица 1.3. Элементарные арифметические и логические операции Операция Команда I I Операция Команда Сложение (Addition) ADD Логическое сложение OR Вычитание (Subtraction) SUB Логическая инверсия NOT Умножение (Multiplication) MUL Арифметическая инверсия NEG Деление (Division) DIV Сдвиг (Shift) SAR Логическое умножение AND Циклический сдвиг (Rotate) ROR Еще одна важная особенность микропроцессора заключается в его способности принимать решения по результатам операций. Например, микропроцессор может проверить число на равенство нулю, определить знак числа и т. п. Эти элементарные решения позволяют микропроцессору в ходе выполнения программы выбирать разные последовательности инструкций. В табл. 1.4 перечислены элементарные проверки, доступные микропроцессорам Intel. Таблица 1.4. Проверки, доступные микропроцессорам Intel Проверка Пояснение Нуля (Zero) Проверяется, равно ли число нулю Знака (Sign) Проверяется знак числа пиление в микропроцессоры и компьютеры 61 Таблица 1.4 (окончание) Проверка Пояснение Переноса (Carry) Проверяется, имеется ли перенос при сложении или заем при вычитании Четности (паритета) (Parity) Проверяется четное или нечетное количество битов, установленных в 1 Переполнения (Overflow) Проверяется переполнение, которое указывает на недопустимый результат после выполнения операции сложения или вычитания Шины Шиной называется группа проводников, объединяющих различные компоненты вычислительной системы. Шины служат для передачи адресов, данных и сигналов управления между микропроцессором и такими компонентами системы, как память и порты ввода-вывода. В микропроцессорных системах имеется три основные шины — шина адреса, данных и управления. Объединение компонентов системы (микропроцессора, ОЗУ (RAM), ПЗУ (ROM) и периферийных устройств) посредством шин показано на рис. 1.11. Рис. 1.11. Шины адреса, данных и управления в структуре вычислительной системы По шине адреса передается номер ячейки памяти или порта ввода-вывода. При обращении к порту адрес 16-разрядный (в диапазоне 0000Н—FFFFH), что позволяет адресовать 64К портов. Адрес при обращении к памяти зависит от версии микропроцессора. В системах на базе 8086/8088 адрес памяти 20-разрядный; адресное пространство составляет 1 Мбайт, в диапазоне 00000Н—FFFFFH. Для микропроцессоров 80286 и 80386SX адресуемая память составляет максимум 16 Мбайт, в диапазоне 0ОООООН—FFFFFFH. Для микропроцессоров 80386SL, 80386SLC и 80386ЕХ адресное пространство — 32 Мбайт, доступные адреса находятся в диапазоне 0000000Н— IFFFFFFH, разрядность шины адреса — 25 бит. В системах на базе 80386DX, 62 Глава 1 80486SX и 80486DX доступно максимум 4 Гбайта памяти (диапазон адресов — 00000000Н—FFFFFFFFH) посредством 32-разрядной шины адреса. Микропроцессор Pentium также располагает адресным пространством 4 Гбайт, но шина данных у него 64-разрядная, что позволяет обращаться одновременно к восьми смежным байтам. Процессоры от Pentium Pro до Pentium 4 используют 64-разрядную шину данных, а адресная шина у них, в зависимости от конфигурации, может быть 32-разрядной или 36-разрядной. В последнем случае адресное пространство памяти достигает 64 Гбайт в диапазоне адресов 000000000Н—FFFFFFFFFH. В табл. 1.5 приведены сведения о разрядности шин и размере адресного пространства памяти микропроцессоров Intel разных поколений. Таблица 1.5. Разрядность шин и размер адресного пространства памяти микропроцессоров Intel Микропроцессор Разрядность шины данных Разрядность шины адреса Размер адресного пространства памяти 8086 16 20 1 Мбайт 8088 8 20 1 Мбайт 80186 16 20 1 Мбайт 80188 8 20 1 Мбайт 80286 16 24 16 Мбайт 80386SX 16 24 16 Мбайт 80386DX 32 32 4 Гбайт 80386ЕХ 16 26 64 Мбайт 80486 32 32 4 Гбайт Pentium 64 32 4 Гбайт Pentium Overdrive 32 32 4 Гбайт Pentium Pro 64 32 4 Гбайт Pentium Pro 64 36 64 Гбайт Pentium II 64 32 4 Гбайт Pentium II, Pentium III, Pentium 4 64 36 64 Гбайт По шине данных выполняется передача данных между микропроцессором и памятью или портами ввода-вывода. Разрядность шины данных различна для разных поколений микропроцессоров — от 8 до 64 бит. Например, микропроцессор 8088 имеет 8-разрядную шину данных, что позволяет передавать только один байт за цикл. В 8086, 80286, 80386SL, 80386SX и 80386ЕХ может быть передано сразу 16 бит данных; в 80386DX, 80486SX и 80486DX — 32 бита; а в Pentium-Pentium 4 — 64 бита. Преимущества более широкой шины данных проявляются при работе с данными соответствующей разрядности. Например, доступ к 32-разрядному числу в памяти микропроцессор 8088 выполняет за 4 цикла шины, поскольку разрядность шины данных — всего лишь 8 бит. Процессор 80486, располагая 32-разрядной ши Введение в микропроцессоры и компьютеры 63 ной данных, может выполнить ту же операцию за один цикл. На рис. 1.12 показана физическая организация памяти в системах на базе микропроцессоров 8086—80486 и Pentium—Pentium 4. Обратите внимание, что в процессорах Pentium—Pentium 4 используется 64-разрядная шина данных. Шина управления служит для передачи сигналов, определяющих выбор памяти или выбор порта, чтение или запись. Следующие управляющие сигналы используются в большинстве компьютерных систем: сигнал чтения памяти — MRDC (Memory Read Control), сигнал записи в память — MWTC (Memory Write Control), сигнал чтения из порта — IORC (I/O Read Control), и сигнал записи в порт — IOWC (I/O Write Control). "Подчеркивание" сверху означает, что сигнал инверсный, т. е. активен, или, иначе говоря, вызывает срабатывание при напряжении, соответствующем уровню логического нуля. Например, если IOWC = 0, то микропроцессор записывает данные, передавая их по шине данных, в порт, адрес которого установлен на шине адреса. Старший (нечетный) байт Младший (четный) байт FFFFFF FFFFFE FFFFFD FFFFFC FFFFFB FFFFFA ◄ 8 бит ► ◄ 8 бит > 8 Мбайт 8 Мбайт 000005 000004 000003 000002 000001 000000 D15-D8 D7-D0 Микропроцессоры: ** 8086 (1 Мбайт), 80286, 80386SX, 80386SL (32 Мбайт) и 80386SLC (32 Мбайт) БайтЗ Байт 2 FFFFFFFF FFFFFFFE FFFFFFFB FFFFFFFA FFFFFFF7 FFFFFFF6 4 8 бит ► 1 Гбайт 4 —8 бит ► 1 Гбайт 0000000В ОООООООА 00000007 00000006 00000003 00000002 D31 - D24 D23-D16 Байт 1 БайтО FFFFFFFD FFFFFFFC FFFFFFF9 FFFFFFF8 FFFFFFF5 FFFFFFF4 ◄ 8 бит ► 1 Гбайт 4 8 бит ► 1 Гбайт 00000009 00000008 00000005 00000004 00000001 00000000 D15-D8 D7-D0 Микропроцессоры. 80386DX, 80386SX и 80486DX Рис. 1.12. Физическая организация памяти для различных поколений микропроцессоров Intel (см. продолжение) 64 Глава d 11 "" Байт 7 Байт 6 Байт 5 Байт 4 FFFFFFFF FFFFFFFE FFFFFFFD FFFFFFFC FFFFFFF7 FFFFFFF6 FFFFFFF5 FFFFFFF4 7 I FFFFFFEF FFFFFFEE . . .. FFFFFFED FFFFFFEC ( 4 8 бит ► <4 8 бит ► 4 8 бит ► 4 вбит— 512 Мбайт 512 Мбайт 512 Мбайт 512 Мбайт > 00000017 00000016 00000015 00000014 0000000F 0000000Е 0000000D ОООООООС / 00000007 00000006 00000005 000000041 J D63 - D56 D55 - D48 D47 - D40 D39 - D32 Байт 3 Байт 2 Байт 1 БайтО ' FFFFFFFB FFFFFFFA FFFFFFF9 FFFFFFF8 FFFFFFF3 FFFFFFF2 FFFFFFF1 FFFFFFFO FFFFFFEB FFFFFFEA FFFFFFE9 FFFFFFE8 4 вбит ► 4 8 бит > 4 вбит ► 4 вбит > 512 Мбайт 512 Мбайт 512 Мбайт 512 Мбайт j ! 00000013 00000012 00000011 00000010 0000000В ОООООООА 00000009 00000008 00000003 000000021 00000001 00000000 ! D31 - D24 D23-D16 D15-D8 D7-D0 I Микропроцессоры от Pentium до Pentium 4 Рис. 1.12. Окончание Чтобы прочитать содержимое ячейки памяти, микропроцессор выставляет ее адрес на шину адреса и затем посылает сигнал MRDC (чтение памяти), после чего данные из памяти передаются по шине данных в процессор. Чтение порта выполняется аналогичным образом. При записи в память или в порт действия выполняются в иной последовательности, но принцип остается тем же. 1.3. Системы счисления Программирование микропроцессорных систем предполагает наличие навыков работы с двоичными и шестнадцатеричными числами. В этом разделе приведены сведения о системах счисления, применяемых в компьютерах, а также рассмотрены преобразования между десятичными, двоичными и шестнадцатеричными числами. Цифры Чтобы выполнять преобразования между представлениями чисел в разных системах счисления, следует, прежде всего, представлять себе, какие цифры в них используются. Всем нам известно, что в десятичной системе счисления применяются цифры от 0 до 9. Первая цифра в любой системе счисления — это 0. Например, в двоичной в микропроцессоры и компьютеры 65 исГеме используются цифры 0 и 1, а в восьмеричной системе диапазон цифр от О с у Если основание системы счисления превышает 10, то для обозначения цифр ис-пОпьзуются также латинские буквы, начиная с А. Например, если основание рав-н0 12. то цифры обозначаются знаками 0—9, А (соответствует 10) и В (соответствует 1D- Заметим, что в системе с основанием 10 нет цифры для обозначения 10, так же как в восьмеричной системе не используется цифра 8. В компьютерах, как правило, применяются системы счисления по основанию 10 (десятичная), 2 (двоичная) и 16 (шестнадцатеричная). Ранее весьма популярной была восьмеричная система. Позиционные системы счисления Произвольные числа составляются из ограниченного набора цифр в соответствии с позиционной системой счисления. Еще в начальной школе нам объясняли, что для десятичной системы счисления крайняя цифра справа обозначает число единиц, цифра левее — число десятков, следующая цифра — число сотен, и т. д. Например, в десятичном числе 132 содержатся 2 единицы, 3 десятка и 1 сотня. Порядковый номер позиции определяет ее вес (заметим, что позиции нумеруются справа налево, начиная с 0). Позиция единиц (позиция номер 0) имеет вес 10°. т. е. 1; позиция десятков обладает весом 101, т. е. 10; а позиция сотен "весит” 102, т. с. 100. Позиция слева от точки — это всегда позиция единиц. (Точка между целой и дробной частями числа имеет смысл при любом основании системы; более узкое понятие десятичная точка применимо лишь к десятичной системе счисления.) Например, позиция слева от двоичной точки имеет вес 2°, т. е. 1; позиция слева от восьмеричной точки — 8°, т. с. вновь 1. Понятно, что в любой системе счисления слева от точки находится позиция единиц. Слева от позиции единиц находится позиция, вес которой равен основанию системы счисления; в десятичной системе это 101, т. е. 10. В двоичной системе это 21, или 2; в восьмеричной — 8’, или 8. Понятно, что значение 11 в десятичной записи не то же самое, что двоичное 11. Десятичное число 11 состоит из одного десятка и одной единицы и равняется 11 единицам Двоичное число 11 состоит из одной Двойки и одной единицы и равно трем единицам. В восьмеричной системе счисления запись 11 обозначает 9 единиц. Вес позиций справа от точки равен основанию системы счисления в отрицательной степени — это относится к любой системе счисления. Так, например, первая цифра справа от десятичной точки имеет вес 10”1, или 0.1, а в двоичной системе вес перкой цифры справа от точки (двоичной) равен 2-1, т. е. 0.5. Пример 1.3 иллюстрирует преобразование двоичного числа 110.101 (часто записывается также в виде 110.1012) в десятичное число. [ Пример 1.3. Преобразование двоичного числа 110.101 в десятичное Степень 22 21 2° 2’1 о-2 2~J Вес 4 2 1 0.5 0.25 0.125 Число 1 1 0 1 0 1 Десятичное 4 + 2 + 0 + 0.5 + 0 4- 0.125 = 6.625 Представление 3 Зак. 384 66 Глава] Значение 110.1012 в двоичной системе вычисляется как сумма 4 + 2 + 0.5 + 0.125 что составляет 6.625. Слагаемое с весом 1 (2°) в целую часть суммы не входит, по* скольку цифра в соответствующей (нулевой) позиции равна 0. По той же причине в дробную часть не входит слагаемое с весом 0.25 (2~2). В примере 1.4 показано преобразование шестеричного числа 25.26. Результат преоб* разования — десятичное число 17.333. i Пример 1.4. Преобразование шестеричного чйсла 25.2 в десятичное Степень 61 6° б'1 Вес 6 1 0.167 Число 2 5 2 Десятичное представление 12 + 5 + 0.333 = 17.333 Преобразование в десятичный формат Примеры 1.3 и 1.4 показывают, что для преобразования в десятичное представление числа, записанного в произвольной системе счисления, следует сложить произведения всех цифр числа на их вес. Еще один пример 1.5 показан для преобразования восьмеричного числа. Сначала записываем цифры исходного числа и для каждой цифры ее вес; затем вычисляем слагаемые, умножая каждую из цифр числа на соответствующий вес. В результате преобразования, числу 125.78 соответствует десятичное значение 85.875. Пример 1.5. Преобразование восьмеричногочисла 125,7^ вдесятичное Степень 82 81 8° 8”1 Вес 64 8 1 0.125 Число 1 2 5 7 Десятичное 64 + 16 + 5 + 0.875 = 85.875 представление Вес позиции, находящейся слева от позиции единиц в восьмеричном числе, равен 81 =1 х 8, или 8. Вес следующей позиции слева — 82 = 8 х 8, т. е. 64. Вес следующей цифры равен 83 = 64 х 8, или 512. Таким образом, вес позиции слева от текущей равен весу текущей позиции, умноженному на основание системы счисления, т. с. на 8, в данном случае. Вес позиции справа от текущей равен весу текущей позиции, поделенному на основание системы счисления. Например, в восьмеричном числе вес позиции справа от точки равен 1/8, или 0.125. Следующая позиция справа имеет вес 0.125/8, или 0.015625, или 1/64. В примере 1.6 показано преобразование двоичного числа 11011.0111. Результат преобразования — 27.4375. Вес позиции справа от двоичной точки равен 2"1, или 1/2; вес следующей позиции справа — 2“2, или 1/4, и т. д. Вес последней позиции в дробной части равен 2 » или 1/16, или 0.0625. Дробная часть составляет в сумме 7/16, или 0.4375. Число 7 в числителе дроби 7/16 соответствует коду 0111 в дробной части, а 16 в знаменателе _^^кропроцессоры и компьютеры 67 соответствует весу крайней правой позиции (1/16). Аналогично, дробная часть дроби может быть записана как 5/8, а число 0.001101 — в виде 13/64. числа он Vi г ^мер 1-6- Преобразование двоичного числа 11011.0111 в десятичное | 2" 23 степень 2 21 2° 2’1 2~2 2“3 2“4 16 8 вес 4 2 1 0.5 0.25 0.125 0.0625 1 1 ЧИСЛО 0 1 1 0 1 1 1 десятичное ±6 + 8 представле- 0 + 2 + 1 + 0 + 0.25 + 0.125 + 0.0625 = 27.4375 ние Пример 1.7 иллюстрирует преобразование шестнадцатеричных чисел, весьма распространенных в вычислительной технике, на примере числа 6А.СН (Н справа означает, что число шестнадцатеричное). i Пример 1.7. Преобразование шестнадцатеричного числа 6А.С в десятичное Степень 161 16° 16’1 Вес 16 1 0.0625 Число 6 А С Десятичное представление 96 + 10 + 0.75 = 106.75 Целая часть равна 6 х 16 + 10, дробная часть — 12/16, или 3/4. Результат преобразования — 106.75. Преобразование из десятичного формата Для преобразования целой части десятичного числа следует делить целую часть на основание требуемой системы счисления, а для преобразования дробной части — умножать. Преобразование целой части десятичного числа Для преобразования целой части делим число на основание системы счисления, вписывая в качестве цифр результата остатки от деления. Последовательность дей-^вий следующая: Разделить число на основание системы счисления. 2- Сохранить остаток (первый остаток — последняя значащая цифра, и наоборот). Повторять шаги 1 и 2, пока целая часть результата деления не станет равной нулю. Зу ПримеР’ преобразования числа 10 в двоичный формат, разделим его на 2. Ре-ци Ьтат первого деления равен 5, а остаток — 0. Первый остаток дает цифру в пози-единиц результата (0, в данном случае). Теперь разделим 5 на 2. Целая часть зииУЛЬтата Деления — 2, а остаток — 1. Остаток дает цифру в позиции слева от по-и единиц. Продолжаем деление до обнуления целой части результата деления. пы преобразования показаны в примере 1.8. Результат преобразования — 10102. 68 Глава 1 Пример 1.8. Преобразование десятичного числа 10 в двоичное 10/2 = 5 остаток = 0 5/2 = 2 остаток = 1 2/2=1 остаток = 0 1/2 = 0 остаток = 1 результат = 1010 Преобразование того же числа 10 в восьмеричный формат потребует всего лишь двух делений. Преобразование показано в примере 1.9, а результат его 128. Пример 1.9. Преобразование десятичного числа 10 в восьмеричное 10/8 = 1 1/8 = 0 остаток = 2 остаток = 1 результат = 12 Преобразование в шестнадцатеричный формат предполагает деление на 16, с получением остатка в диапазоне от 0 до 15. Остаткам в диапазоне 10—15 соответствуют шестнадцатеричные "цифры" A—F. Преобразуем число 109 (пример 1.10). После первого деления остаток равен 13, что записывается как D. Целая часть равна 6. После второго деления остаток равен 6, а целая часть — нулю. Преобразование закончено, результат — 6DH. :........................................................................................-£ = Пример 1.10. Преобразование десятичного числа 109 в шестнадцатеричное ;........................................................................................л 109/16 = 6 остаток = 13 (D) 6/16 = 0 остаток = 6 результат = 6D Преобразование дробной части десятичного числа Преобразование дробной части выполняется за счет умножения на основание системы счисления, например, на два при преобразовании в двоичный формат. Целая часть результата умножения представляет собой значащую цифру результата преобразования, а дробная часть снова умножается на основание системы счисления, пока не станет равной нулю. Заметим, что некоторые числа не могут быть преобразованы к конечной форме; их дробная часть никогда не станет равной нулю. Последовательность операций для преобразования дробной части десятичного числа следующая: 1. Умножить десятичную дробную часть на основание системы счисления. 2. Сохранить целую часть результата умножения, даже если она равна нулю, как значащую цифру. Заметим, что цифра, полученная первой, записывается справа от точки. 3. Повторять шаги 1 и 2, используя дробную часть, полученную в результате выполнения шага 2, в качестве исходных данных для шага 1, пока она не станет равной нулю. В примере 1.11 показано преобразование в двоичный формат десятичного числа 0.125. Обратите внимание, преобразование заканчивается, когда дробная часть ре Введение в микропроцессоры и компьютеры 69 зультата умножения становится равной нулю. Результат преобразования в данном примере — 0.0012. i Пример 1.11. Преобразование десятичного числа 0.125 в двоичное 0.125 х 2 = 0.25 целая часть = 0 0.25 х 2 = 0.5 целая часть = 0 0.5x2= 1.0 целая часть = 1 результат = 0.0012 Преобразование дробной части десятичного числа в произвольную систему счисления выполняется аналогично. Например, преобразование в восьмеричную систему счисления производится соответственно умножением на 8. К примеру, десятичное число 0.125 преобразуется за один цикл (пример 1.12) — после умножения 0.125 на 8 получаем результат 1.0 с нулем в дробной части. Таким образом, десятичное число 0.125 в восьмеричном формате записывается как 0.1. I Пример 1.12. Преобразование десятичного числа 0.125 в восьмеричное 0.125 х 8 = 1.0 целая часть = 1 результат = 0.1g Пример 1.13 иллюстрирует преобразование десятичного числа в шестнадцатеричный формат. Десятичное число 0.046875 преобразуется в шестнадцатеричное 0.0CH путем умножения на 16. | Пример 1.13. Преобразование десятичного числа 0.046875 в шестнадцатеричное 0.046875 х 16 = 0.75 целая часть = 0 •* 0.75 х 16 = 12.0 целая часть = 12 (С) результат = 0.0CH Шестнадцатеричные числа Шестнадцатеричные числа обычно используются в вычислительной технике для компактного представления двоичных чисел. Двоичные коды, соответствующие шестнадцатеричным цифрам, приведены в табл. 1.6. С использованием табл. 1.6 любое шестнадцатеричное значение может быть записано в виде тетрад двоичных цифр. Например, двоичный эквивалент шестнадцатеричного числа 2АС показан в примере 1.14. | Пример 1.14. Преобразование шестнадцатеричного числа 2АС в двоичное 2АС = 0010 1010 1100 Пример обратного преобразования показан в примере 1.15. 70 Глава i Пример 1.15. Преобразование двоичного числа в шестнадцатеричное ' 1000 ООН 1101 . 1110 = 83D.E Таблица 1.6. Двоичные коды шестнадцатеричных цифр Шестнадцатеричная цифра Двоичный код Шестнадцатеричная цифра Двоичный крд 0 0000 8 1000 ** 1 0001 9 1001 2 0010 А 1010 3 0011 В 1011 4 0100 С 1100 5 0101 D 1101 6 0110 Е 1110 7 0111 F 1111 Дополнительный код Инверсный и дополнительный коды используются в вычислительной технике для хранения отрицательных чисел (в настоящее время гораздо более распространен дополнительный код). Для получения инверсного кода исходное значение вычитается из числа, в котором все цифры максимальны, т. е. равны основанию системы счисления минус 1. Для двоичного числа инверсный код соответствует числу с поразрядной инверсией, т. е. полученного путем замены всех единиц нулями и наоборот. Далее приведен пример 1.16 получения инверсного кода для байта со значением 0100 1100. Исходное число вычитается из кода, целиком состоящего из единиц (основание системы счисления равное 2 минус 1) — 1111 1111. Результат — 1011 0011- Пример 1.16. Получение>1нверсногокодадвоигчного;чис^а.01001100 1111 1111 - 0100 1100 1011 0011 Аналогичным образом выполняется преобразование в инверсный код для значен ’ записанных в других системах счисления. Например, инверсный код для щестнаД теричного числа 5CD вычисляется путем вычитания его из числа, в котором цифры равны 15 (F) (основание системы счисления равное 16 минус 1). 71 едение 8 микРопР°ЦессоРы и компьютеры р иМеР ^0ЛУчение инверсного кода шестнадцатеричного числа 5CD 15 15 15 . 5 С—2_ инверсный код сам по себе практически не используется, из него может быть олучен дополнительный код, который и применяется в настоящее время для представления отрицательных чисел. Использовать с этой целью инверсный код, что было принято в ранних вычислительных системах, неудобно, поскольку число ноль может быть представлено двояко — последовательностью 0 (’’положительный" ноль) или последовательностью 1 ("отрицательный" ноль). В дополнительном коде, напротив число 0 представлено только последовательностью битов со значением 0. Чтобы получить дополнительный код, следует прибавить единицу к инверсному коду Далее показан пример 1.18 получения дополнительного кода числа 0100 1000. f пример 1.18. Получение дополнительного кода двоичного числа 0100 1000 1111 1111 - 0 1 0 0 1 0 0 0 10 11 0 111 + 0000 0001 10 11 10 0 0 (инверсный код) (дополнительный код) Для проверки результата просуммируем полученный дополнительный код 1011 0111 с исходным кодом 0100 1000. Получаем ноль (перенос из старшей позиции игнорируется), что и следовало ожидать (0100 1000 = +72, а 1011 0111 = -72). Аналогичный подход используется для получения дополнительного кода в произвольной системе счисления. Далее показан пример 1.19 подобного преобразования для шестнадцатеричного числа 345. Для проверки полученного результата можно сложить код 345 с его дополнительным кодом СВВ и, отбросив перенос в четвертую позицию, получить 000. 1$РИм®Р 1.19. Получение дополнительного кода шестнадцатеричного числа 345 | ...........................................................„.......... 15 15 ' 4 5 с В д (инверсный код) + Л_о 1 С В в (дополнительный код) 1*4. Форматы данных Ь^ГраммиР°вание на машинном языке предполагает знание форматов данных. разделе рассмотрены наиболее общие форматы данных (ASCII, BCD, дейст-ьные числа, знаковые и беззнаковые целые) и их использование в системах на 2 базе микропроцессоров Intel. Форматы данных специального назначения пока обсуждаем. ASCII-данные Стандартный код для обмена информацией — ASCII (American Standard Code fOf Information Interchange) — используется для представления буквенно-цифровых зна^ ков в памяти вычислительной системы. Стандартный код ASCII, представленный g табл. 1.7, занимает семь бит. Свободный старший бит байта с кодом ASCII иногда используют в качестве бита четности. При выводе на дисплей или принтер букв, цифр и знаков препинания этот бит равен 0, а при выводе символов псевдографики — установлен в 1. В общем случае, установка старшего бита включает расширенный набор ASCII-символов. Пример расширенного набора ASCII-символов кодов в диапазоне кодов 80Н—FFH приведен в табл. 1.8. В расширенном наборе ASCII-символов обычно представлены буквы греческого или местного алфавита, специальные математические знаки, символы псевдографики и т. п. Заметим, что содержание расширенного набора может быть различным для разных принтеров. В частности, набор, представленный в табл. 1.8, имеет отношение к конкретному принтеру — IBM ProPrinter. Управляющие ASCII-символы, приведенные в начале табл. 1.7, предназначены для выдачи команд периферийным устройствам, например, для очистки экрана, стирания символа, перевода строки и т. п. Для ввода управляющего символа с клавиатуры используется комбинация клавиш <Ог1>+<буква>. Например, код 01Н (SOH — Start Of Heading, начало заголовка) вводится нажатием комбинации клавиш <Ctrl>+<A>; код 02Н (STX — Start Of Text, начало текста) — комбинацией клавиш <Ctrl>+<B> и т. д. (Если ввести эти коды в режиме командной строки DOS, они будут отображены на экране в виде ЛА, ЛВ и т. д.) Ввод ASCII-кода CR (Carriage Return — возврат каретки) выполняется нажатием клавиши <Enter>. (Управляющий символ CR задает возврат курсора в начала строки.) Еще один часто встречающийся код LF (Line Feed — перевод строки) задает перемещение курсора на следующую строку. Использование табл. 1.7 и 1.8 поясним на следующем примере: найдем ASCII-кодЫ для символов "А" и "а". Символ "А" находится на пересечении строки 4х и столбца х! табл. 1.7. Объединяя названия строки и столбца, получаем, что код этой литеры — шестнадцатеричное число 41 или, иначе, 41Н. Символ "а" находится на пересечении строки 6х и столбца xl, т. е. его код равен 61Н. Заметим, что во многих приложениях Windows используется другая система кодировки алфавитно-цифровЫ* символов — Unicode. В этой кодировке символы представлены в виде 16-битны* значений. Коды в диапазоне 0000Н—00FFH совпадают со стандартным набор0 ASCII-кодов. Остальные коды (в диапазоне 0100Н—FFFFH) используются для Хр® нения специальных символов, с учетом всех национальных алфавитов, что позво ет тиражировать программное обеспечение по всему миру. Для определения данных ASCII в программе на языке ассемблера предназначен, директива db (Define Byte(s) — определить байт(ы)) или полностью совпадают ней директива byte. Примеры определения ASCII-данных при помощи директивы приведены в примере 1.20. xO x1 x2 x3 Таблица 1.7. Коды ASCII (первая половина кодовой таблицы) VS х4 х5 хб х7 х8 х9 хА хВ xC xD xE xF Ox NUL SOH STX ETX EOT ENQ АСК BEL BS нт LF VT FF CR SO SI съ tn 1x DLE DC1 DC2 DC3 DC4 NAK SYN ЕТВ CAN EMS SUB ESC FS GS RS US i 2x SP i # $ % & ( ) * + - / O о 3x 0 1 2 3 4 5 6 7 8 9 < = > ? "O о 4x @ A В C D Е F G Н I J К L M N 0 Ф о о 5x P Q R S Т и V W X Y Z [ \ ] A •§ 6x a b c d е f g h i j k I m П 0 X 7x P q r s t и V W X У z { I } о 1 б Таблица 1.8. Расширенные ASCII-коды для IBM ProPrinter 5: xO х1 х2 хЗ х4 х5 хб х7 х8 х9 хА хВ хС xD хЕ xF Ox О • V ♦ Ф Л • □ О * J3 а 1х ► ◄ I !! И § 1 —* «— L ▲ ▼ 8х С и ё а а а ё 9 ё ё ё т 1 i А А 9х Ё ае ZE о 6 о й й У 0 и 0 £ ¥ Pt f Ах а i 6 й п N а о с Г" 72 Уд i « » Вх 1 | d =1 dl и =1 =51 II Т1 JI Л J Сх L ± т F - + h IF IL 1г JL тг IF = JL 1Г X Dx JL т т IL L f= IF dF + J Г 1 1 1 Ex а ₽ г тт Z о М Y ф О О б «о е А Fx = ± > < [ J - □ • п 2 со 74 Глава j Пример 1.20. Определение ASCII-данных при помощи директивы db 0000 42 20 72 61 72 72 79 NAMES DB 'Barry B. Brey' 42 2Е 20 42 65 79 000D 57 68 65 72 65 MESS DB 'Where can it be? 20 63 61 6Е 20 69 74 20 62 65 3F 001D 57 68 61 74 20 WHAT DB 'What is on first 69 73 20 6F 6Е 20 66 69 72 73 74 2Е Обратите внимание, что цепочки символов заключены в одинарные кавычки; двойные кавычки использовать не следует. С левой стороны от директив db в примере I.20 приведены шестнадцатеричные значения для каждого из ASCII-кодов. В крайнем столбце слева показаны шестнадцатеричные адреса, с которых начинается распределение памяти для строк ASCII-символов. Например, строка what размещена в памяти с адреса 001D; по этому адресу хранится буква W (с кодом 57), за ней — буква h (с кодом 68), и т. д. Двоично-десятичные данные Двоично-десятичные числа, или BCD-числа (Binary Coded Decimals), хранятся в упакованной или в неупакованной форме. Упакованные BCD-данные содержат по паре десятичных цифр в каждом байте, в то время как один байт неупакованных BCD-данных содержит всего одну цифру. Значения BCD-данных ограничены диапазоном представления десятичных цифр 0—9, или 00002—10012. Неупакованные BCD-числа появляются в компьютере в результате нажатия на клавиатуре клавиш с цифрами. Для выполнения сложения и вычитания BCD-чиоел в центральном процессоре предусмотрены специальные команды.32 В табл. 1.9 показаны примеры представления десятичных чисел в BCD-формате. Поскольку простой и эффективный способ выполнения сложных вычислений с BCD-данными не найден, применение данных этого типа ограничено устройствами, производящими минимум арифметических действий. Таблица 1.9. Упакованные и неупакованные BCD-числа Десятичное число Упакованное BCD-число Неупакованное BCD-число 12 0001 0010 0000 0001 0000 0010 623 0000 0110 0010 0011 0000 0110 0000 0010 0000 0011 910 0000 1001 0001 0000 0000 1001 0000 0001 0000 0000 больнК’** 32 Арифметический сопроцессор позволяет ускорить работу с упакованными BCD-числами размерности. — Пер. 75 в микропроцессоры и компьютеры ------------------------------ иМере 121 показано, как использовать язык ассемблера для задания упакован-0 неупакованных BCD-чисел. При задании числа по частям следует помнить, нЬ,Хяанные, определенные в начале, являются младшими разрядами числа, и наобо-ч1"0 таким образом, для хранения чисел используется способ хранения, начиная с Р^-щего байта. Часто для такого способа применяется термин обратная запись слое, показывает, что байты слова хранятся в обратном порядке по сравнению с К°иДаеМЬ,м’ Например, чтобы задать неупакованное BCD-число 83, сначала следует °* еделить байт со значением а затем байт со значением 8. Упакованные BCD-° иные задают шестнадцатеричными числами; при этом рекомендуется дописывать справа в конце этих чисел букву Н, чтобы ассемблер не воспринял число как деся-тичное- Таймер 1.21* Задание упакованных и неупакованных BCD-чисел ; Неупакованные BCD-числа оооо 03 04 05 NUMB1 DB 3,4,5 ; число 543 0003 07 08 NUMB2 DB / ; Упакованные 7,8 BCD-числа . ; число 87 0005 37 34 NUMB3 DB 37Н,34Н ; число 3437 0007 03 45 NUMB 4 DB 3,45Н ; число 4503 Байты Двоичное число, хранящееся в байте (8 битах), может рассматриваться как беззнаковое или знаковое целое число, что иллюстрирует рис. I.13. Разница — в различном весе старшего бита. Для беззнакового целого числа вес старшего бита равен 128, а для знакового — —128. Когда речь идет о знаковых данных, именно старший бит определяет знак числа. Например, байт с кодом 80Н, если трактовать его как беззнаковое число, означает 128 в десятичном представлении; если же рассматривать его как число со знаком, это —128. Диапазон беззнаковых целых чисел, заданных байтом, составляет ООН—FFH (0—255). Предельные значения знаковых целых соот-ветственно -128 и +127. Веса разрядов Знаковый байт Рис. 1.13. Веса разрядов знаковых и беззнаковых 8-разрядных целых чисел 76 Отрицательные значения хранятся в дополнительном коде. Например, чтобы зада-w код числа —8, следует найти дополнительный код для +8. Дополнительный код жет быть получен из инверсного кода, как показано в примере 1.22. Пример 1.22. Представление отрицательного числа -8 в дополнительном коде 8 00001000 11110 111 1 (инверсный код) -8 = 11111000 (дополнительный код) Более простой способ заключается в следующем. Ищите справа налево позицию со значением 1. Биты, оставшиеся слева от этой позиции, следует проинвертировать (остальные — оставить без изменений). Пример 1.23 иллюстрирует эту технологию с таким же числом, как и в предыдущем примере. Пример 1.23. Представление отрицательного числа -8 в дополнительном коде +8 = 00001000 10 0 0 1111 -8 = 1111 1000 (правая часть числа до бита со значением 1 включительно) (результат инверсии левой части числа) В программах на языке ассемблера для сохранения байтов данных в памяти предусмотрена директива db. Пример 1.24 показывает, каким образом с помощью ассемблера можно сохранять в памяти различные виды восьмибитных чисел. Следует отметить, что шестнадцатеричные числа в программе завершаются буквой Н, а десятичные числа записывают как есть, т. е. без какого-либо специального обозначения. Пример 1.24. Применение директивы db 0000 ГЕ ; Беззнаковые байты DATA1 DB 254 ; десятичное 254 0001 87 DATA2 DB 87Н ; шестнадцатеричное 87 0002 47 DATA3 DB 71 ; десятичное 71 ; Знаковые байты 0003 9С DATA4 DB -100 ; десятичное -100 0004 64 DATA5 DB + 100 ; десятичное + 100 0005 ЕЕ DATA 6 DB -1 ; десятичное -1 0006 38 DATA7 DB 56 ; десятичное 56 Слова Слова, или иначе шестнадцатиразрядные данные, хранятся в паре смежных байт-Младший байт слова всегда сохраняется в ячейке памяти с младшим адресом, 77 uiAe в микропроцессоры и компьютеры ий байт соответственно в следующей — старшей ячейке. Этот метод, приня-системах на базе микропроцессоров Intel, называется прямым порядком байтов fl»1# endian). Противоположный вариант хранения многобайтных чисел — обратный (ДО > к байтов (big endian) — в микропроцессорах Intel не используется. В этом ва- старшая (наиболее значимая) часть числа хранится в младшем байте. Формат ^браТН°Г0 порядка байтов применяется в системах на базе микропроцессоров Motor°la- На Рис формат представления 1.14, а показаны веса позиций 16-битного слова. Рис. 1.14, б иллюстрирует 1234Н в смежных байтах по адресам 3000Н и 3001Н. числа а) Беззнаковое слово Старший байт Младший байт б) Содержимое байтов по адресам ЗОООН и 3001Н при хранении слова 1234Н Рис. 1.14. Формат хранения 16-битного числа в регистре (а) и в двух смежных байтах памяти (б) азница между знаковыми и беззнаковыми 16-битными величинами, как и в случае 'битных чисел, заключается в использовании старшего бита. Если число беззнако-в°е, то старший бит — значащий, с наибольшим весом. Если число знаковое, то ^РШий бит задает знак числа, а его вес равен -32 768. Для представления отрица-Тельных чисел используется дополнительный код. задания знаковых и беззнаковых слов в программе на языке ассемблера предна-аЧена директива dw (или идентичная ей директива word). Пример задания 16-бит-Ь1х Данных приведен в примере 1.25. 78 Листинг 1.25. Задание 16-битных данных ; Беззнаковые слова 0000 0002 0004 09F0 8 7 АС 02С6 DATA1 DATA2 DATA3 DW DW DW 2544 87АСН 710 ; десятичное 2544 ; шестнадцатеричное 87АС ; десятичное 710 ; Знаковые слова 0006 СВА8 DATA4 DW -13400 ; десятичное -13400 0008 00С6 DATA5 DW +198 ; десятичное +198 000А FFFF DATA6 DW -1 ; десятичное -1 Двойные слова Числа размерностью 32 бита хранятся в двойном слове — в четырех смежных байтах. В 16-разрядных микропроцессорах данные такой размерности получаются в результате умножения 16-разрядных слов; также в двойное слово записывается делимое перед выполнением операции деления (если делитель 16-разрядный). В процессорах от i80386 до Pentium 4 разрядность внутренних регистров и размерность операндов команд расширена до 32. Рис. 1.15, а иллюстрирует хранение 32-разрядного числа в памяти; на рис 1.15, б показаны веса двоичных позиций 32-разрядного числа. Веса разрядов а) Беззнаковое двойное слово 001ОЗН 00102Н 00101Н 001ООН 000FFH Старший байт Младший байт б) Содержимое байтов по адресам 001 ООН и 001 ОЗН при хранении двойного слова 12345678Н Рис. 1.15. Формат хранения 32-разрядного числа в регистре (а) и в четырех смежных байтах памяти (6) 79 е^ие в микропроцессоры и компьютеры 32-разрядное число хранится в памяти, его наименее значимая часть находит-К^байте по наименьшему адресу, а наиболее значимая часть — в старшем байте, сЯ 0 тВетствии с форматом прямого порядка байтов (little endian). Например, если ц с°° 12345678Н хранится в памяти по адресам 001 ООН—00103Н, то в байте по адре-ч1<^)100Н записано 78Н, в байте по адресу 00101Н — 56Н, по адресу 00102Н — 34Н, V аДРесу 00103Н - 12Н* 3 задания двойных слов используется директива ассемблера dd. Вместо нее можно ^ользовать также директиву dword. Задание знаковых и беззнаковых 32-разрядных ИСцНЫх посредством директивы dd приведено в примере 1.26. .............................................................. йКимер -26- Использование директивы ю для задания 32-разрядных данных ; Беззнаковые двойные слова 0000 0003Е1С0 DATA1 DD 254400 ; десятичное 254400 0004 87АС1234 DATA2 DD 87АС1234Н ; шестнадцатеричное 87АС1234 0008 00000046 DATA3 DD 70 ; десятичное 70 ; Знаковые двойные слова ооос FFEB8058 DATA4 DD -1343400 ; десятичное -1343400 0010 000000С6 DATA5 DD +198 ; десятичное +198 0014 FFFFFFFF DATA6 DWORD -1 ; десятичное -1 В принципе, мы можем задать целое значение сколь угодно большой размерности. Рассмотренное нами определение данных в виде 8-, 16- и 32-разрядных знаковых и беззнаковых чисел является стандартным, но это не значит, что в памяти нельзя задать, например, 128-байтное целое значение. Для определения данных нестандартной размерности обычно используют директиву db. Например, 24-разрядное число 123456Н может быть задано директивой db 5бн,34н,12н — в соответствии с форматом прямого порядка байтов (little endian). Действительные числа Действительное число, или число с плавающей точкой, состоит из мантиссы и поряд-На рис. 1.16 приведены форматы действительных чисел одинарной и двойной точности, занимающих в памяти 4 или 8 байт соответственно. Варианты, приведенные на рис. 1.16, соответствуют версии 10.0 стандарта IEEE-4 3, в котором зафиксированы форматы действительных чисел и минимальный абор операций, выполняемых арифметическими сопроцессорами персональных °Мпьютеров. Действительное число однократной точности на рис. 1.16, а содержит еДующие поля: знаковый бит, 8-битный порядок и 24-битную дробную часть ц антиссу). На рис. 1.16, б показан формат действительных чисел двойной точности. Роцессоры Pentium—Pentium 4, располагающие 64-разрядной шиной данных, спо-803* выполнять ДОСТУП к таким данным в два раза быстрее, чем процессоры — Institute of Electrical and Electronic Egineers. 80 Гпава ч 31 30 23 22 0 Знак Смещенный порядок Мантисса а) 63 62 52 51 О Знак Смещенный порядок Мантисса б) Рис. 1.16. Действительные числа одинарной (а) и двойной точности (6) Сложив число битов для представления действительного числа одинарной точности, получим 33. На самом деле мантисса хранится в 23 битах, поскольку содержит подразумеваемый или, иначе, скрытый разряд. В сумме получаем 32 бита, что соответствует 4 байтам. Скрытый бит — это первый бит нормализованного действительного числа. При нормализации числа его порядок подбирается таким, чтобы мантисса была больше или равна I и меньше 2. Например, десятичное число 12 в двоичном формате равно И002, а после нормализации l.l х 23. Единица справа от точки не хранится, поэтому мы и считаем, что мантисса 24-битная (хотя в памяти она занимает 23 бита). Примеры машинного представления действительных чисел одинарной точности приведены в табл. !.Ю. Таблица 1.10. Машинное представление действительных чисел одинарной точности Число Код Нормализованное представление Знак Смещенный порядок Мантисса + 12 1100 1.1 х23 0 10000010 1000000 00000000 00000000 : -12 1100 -1.1 х23 1 10000010 1000000 00000000 00000000 +100 1100100 1.1001 х2в 0 10000101 1001000 00000000 00000000 -1.75 1.11 -1.11 х 2° 1 01111111 1100000 00000000 00000000 +0.25 .01 1.0 х2'2 0 01111101 0000000 00000000 00000000 +0.0 0 0 0 00000000 0000000 00000000 00000000 Порядок двоичного числа с плавающей точкой хранится в смешенном виде и назЫ* вается смещенным порядком. Это означает, что к порядку прибавлена постоянная составляющая — смещение. Значение смещения равно 127 (7FH) для действительны* чисел одинарной точности и 1023 (3FFH) для действительных чисел двойной точно* сти. В предыдущем примере двоичный порядок, равный 3, в числе с одинарно точностью хранится как сумма 127 + 3 = 130 (82Н), а в числе с двойной точностЫО записывается как 1026 (402Н). 81 0 микропроцессоры и компьютеры орЫе значения, не допускающие нормализации, кодируются особым образом. НеК°наГ1ример, число 0.0, код которого состоит из одних нулей. Еще один при-^т°’ бесконечность (infinity), которая обозначается единицами в поле смещенного мер и нулями в поле мантиссы (с помощью знакового бита различают положи-vio и отрицательную бесконечности). YgjibHy ассемблера позволяет определить действительные числа одинарной и двойной ости. Число одинарной точности занимает 32 бита, и для его задания использу-Т°Ч директива dd или dq. Число двойной точности имеет размерность 64 бита и ^Дпеляется директивой dq, которая резервирует 8-байтные последовательности, есто dd и dq можно использовать идентичные директивы real4 и reals. Действи-пьное число расширенной точности определяется директивой realio. Пример 1.27 люстрирует задание действительных чисел. Г пример 1.27. Задание данных с плавающей точкой ; Действительные числа одинарной точности 0000 3F9DF3B6 NUMB1 DD 1.234 ; 1.234 0004 С1ВВЗЗЗЗ NUMB 2 DD -23.4 ; -23.4 0008 43D20000 NUMB3 REAL 4 4.2Е2 ; 420 ооос 3F9DF3B6 NUMB4 REAL 4 1.234 f ; Действительные числа двойной точности 0010 405ED9999999999A NUMB 5 DQ 123.4 ;123.4 0018 С1ВВЗЗЗЗЗЗЗЗЗЗЗЗ NUMB 6 REAL8 -23.4 ;-23.4 0028 405ED9999999999A NUMB 7 REAL 8 123.4 ; Действительное число расширенной точности 0030 4005 F6CCCCCCCCCCCCCD NUMB 8 REAL10 123.4 Итоги О Эпоха механических вычислительных устройств началась с изобретения счетов в 500 г. до н. э. В 1642 г. Блез Паскаль изобрел механический калькулятор. Первый механический компьютер под названием "аналитическая машина" спроектирован в 1823 г. Чарльзом Бэббиджем, но изготовлен не был — по причине слишком высоких требований к точности деталей. Первая электронная вычислительная машина создана Конрадом Цузе во время т°рой мировой войны. Этот компьютер, под названием Z3, применялся в пробировании летательных аппаратов для нужд вермахта. □ п 1еРвый компьютер на электронных лампах был создан в Англии в 1943 г. и Применялся для раскрытия секретных кодов германской шифровальной машины нигма. Первая электронная вычислительная система под названием "Колосс" °здана Тьюрингом; главный ее недостаток — фиксированная программа. Первая программируемая электронная вычислительная система ENIAC (Electrodes Numerical Integrator and Calculator) разработана в 1946 г. в университете шта-m Пенсильвания. 82 Глава 1 О Первый язык программирования высокого уровня Flow-Matic был разработан для компьютера UN 1 VAC I в начале 50-х. Автор — Грейс Хоппер. В дальнейшем по образу и подобию Flow-Matic были созданы такие известные языки, как Fortran и CoboL О Первый в мире микропроцессор Intel 4004 представлял собой 4-разрядный программируемый однокристальный микроконтроллер с 45 инструкциями и 4096 ячейками памяти. □ Первые 16-разрядные микропроцессоры, созданные фирмой Intel, — 8086/8088. В дальнейшем были выпущены микропроцессоры 80286, 80386, 80486, Pentium, Pentium Pro, Pentium II, Pentium III и Pentium 4. В 80386 разрядность процессора была расширена до 32, а в процессоре Itanium она доведена до 64 бит. В каждом новом поколении процессоров Intel их архитектура усовершенствуется для достижения более высокой производительности. □ Персональные компьютеры на базе микропроцессоров включают в себя подсистему памяти, содержащую область транзитных программ (ТРА), называемую иначе стандартной памятью, системную область или, иначе, верхнюю память и расширенную память. В область ТРА загружаются на выполнение прикладные программы, там же хранятся программы операционной системы и драйверы. Системная область занята блоками памяти для дисковых операций, видеопамятью и ROM BIOS. Расширенная память доступна в персональных компьютерах класса АТ, на процессорах начиная с Intel 80286. □ Процессоры 8086/8088 могут адресовать максимум 1 Мбайт памяти в диапазоне адресов 00000Н—FFFFFH. Процессоры 80286 и 80386SX способны адресовать уже 16 Мбайт в диапазоне 000000Н—FFFFFFH. Процессор 80386SL адресует 32 Мбайт памяти по адресам 0000000Н—1 FFFFFFH. Адресное пространство процессоров 80386DX и выше расширено до 4 Гбайт (максимальный адрес — FFFFFFFFH). Кроме того, процессоры от Pentium Pro до Pentium 4 могут использовать 36-разрядные адреса, что позволяет расширить адресное пространство до 64 Гбайт (в диапазоне адресов 000000000Н—FFFFFFFFFH). □ Во всех версиях микропроцессоров Intel от 8086—80486 до Pentium—Pentium 4 адресное пространство портов ввода-вывода составляет 64 Кбайт, в диапазоне адресов 0000Н—FFFFH. Порты по адресам 0000Н—03FFH зарезервированы для системных устройств персонального компьютера. □ Большинство персональных компьютеров оснащено операционной системой MS-DOS (Microsoft) или PC-DOS (IBM). Операционная система обеспечивает работу компьютерной системы, включая периферийные устройства общего назначения. □ Микропроцессор в вычислительной системе играет роль центрального элемента управления. Микропроцессор организует передачу данных, обеспечивает выполнение элементарных арифметических и логических операций, а также принимает простейшие решения. Микропроцессор выполняет сложные операции, заданные программами, которые хранятся в памяти вычислительной системы. □ Во всех вычислительных системах имеются три шины для организации обмена данными между процессором, памятью и портами ввода-вывода. Адрес порта или ячейки памяти передается по шине адреса. Данные между микропроцессо Введение в микропроцессоры и компьютеры 83 ром и памятью или периферийными устройствами передаются по шине данных. Шина управления используется для инициирования записи и чтения портов ввода-вывода и памяти посредством сигналов IORC (I/O Read Control — чтение порта), IOWC (I/O Write Control — запись в порт), MRDC (Memory ReaD Control — чтение ячейки памяти) и MWTC (Memory WriTe Control — запись в ячейку памяти). □ Число, заданное в произвольной системе счисления, преобразуется в десятичное число за счет оценки весов каждой позиции числа. Вес позиции слева от точки в любой системе счисления равен единице. Следующая позиция слева имеет вес, равный основанию системы счисления. Вес последующих позиций определяется как результат умножения веса предыдущей позиции на значение основания системы счисления. Вес позиции справа от точки определяется посредством деления на значение основания системы счисления. □ Преобразование десятичного числа в любую другую систему счисления выполняется за счет деления на значение основания системы счисления. Преобразование дробной части десятичного числа выполняется посредством умножения на значение основания системы счисления. □ Шестнадцатеричные данные применяются в вычислительной технике, в основном, для сокращения записи двоичных чисел. □ Код ASCII используется для хранения печатных литер — букв, цифр, знаков препинания. Восьмой бит кода используется для расширения стандартного 7-битного набора ASCII до 256 символов. Код возврата каретки, вырабатываемый клавиатурой при нажатии клавиши <Enter>, дает команду на перемещение курсора к левому краю строки. Код LF (Line Feed) задает перемещение курсора на следующую строку. □ Двоично-десятичные числа (BCD) используются в компьютерных системах для хранения десятичных чисел. Двоично-десятичньТе числа могут быть представлены в двух формах — упакованной (по две цифры в байте) и неупакованной (по одной цифре в байте). □ Двоичные данные хранятся в виде байта (8 бит), слова (16 бит) или двойного слова (32 бита). Могут быть знаковыми или беззнаковыми. Знаковые отрицательные данные хранятся в дополнительном коде. Данные размерностью более 8 бит хранятся в формате прямого порядка байтов (little endian), при котором наименее значимая часть числа размещается в байте с наименьшим адресом. □ Числа с плавающей точкой используются в компьютерных системах для хранения чисел с дробной частью. Число с плавающей точкой состоит из знака, мантиссы и порядка или, точнее, приведенного порядка. □ В ассемблере имеются директивы для задания байтов — db или byte, для задания слов — dw или word, для задания двойных слов — DD или DWORD; и для задания 8-байтных значений — dq или qword. □ В примере 1.28 показаны варианты возможного использования директив ассемблера для задания чисел размерностью байт, слово и двойное слово, а также директив для задания ASCII-строк и действительных чисел. 84 Глава 1 ; ASCII-данные 0000 54 68 69 73 20 69 MES1 DB 'This is a character string in ASCII' 73 20 61 20 63 68 61 72 61 63 74 65 72 20 73 74 72 69 6E 67 20 69 6E 20 41 53 43 49 49 0023 002D 002Е 002F 53 6F 20 69 73 20 MES2 ; Байты DATA1 DATA2 DATA3 DB DB DB DB 'So is 23 -34 34Н this' 74 68 17 DE 34 69 73 ; десятичное 23 ; десятичное -34 ; шестнадцатеричное 34 ; Слова 0030 1000 DATA4 DW 1000Н ; шестнадцатеричное 1000 0032 FF9C DATA5 DW -100 ; десятичное -100 0034 ооос DATA6 DW +12 ; десятичное +12 ; Двойные слова 0036 00001000 DATA7 DD 1000Н ; шестнадцатеричное 1000 003А FFFFFED4 DATA8 DD -300 ; десятичное -300 003Е 00012345 DATA9 DD 12345Н ; шестнадцатеричное 12345 ; Действительные числа 0042 4015C28F DATA10 REAL4 2.34 ; 2.34 0046 C00CCCCD DATA11 REAL4 -2.2 ; -2.2 004А 4059133333333333 DATA12 REAL8 100.3 ; 100.3 Контрольные вопросы и задания 1. Кто автор аналитической машины? 2. В 1890 г. при переписи населения США был применен новый носитель информации — перфокарта. Кто ее изобрел? 3. Кто является основателем корпорации IBM? 4. Кто создал первую электронную вычислительную машину? 5. С какой целью был разработан первый электронный компьютер? 6. Как назывался первый программируемый компьютер общего назначения? 7. Кто является создателем первого в мире микропроцессора? 8. Кто, кроме Бэббиджа, участвовал в разработке аналитической машины? 9. Кто автор первого языка программирования высокого уровня Flow-Matic? 10. В чем заключается принципиальная особенность машины фон Неймана? 11. С какого 8-разрядного микропроцессора началась эпоха микропроцессоров? 12. Каков объем продаж микропроцессора 8085, представленного фирмой Intel в 1977 г.? Введение в микропроцессоры и компьютеры 85 13. В каком из микропроцессоров фирмы Intel адресное пространство было расширено до 1 Мбайт? 14. Сколько байт памяти доступно микропроцессору 80386SL? 15. Сколько памяти доступно микропроцессору 80486? 16. В каком году фирма Intel представила микропроцессор Pentium? 17. В каком году был выпущен процессор Pentium Pro? 18. Когда появился микропроцессор Pentium 4? 19. Какой из микропроцессоров Intel может адресовать 64 Гбайт памяти? 20. Что означает аббревиатура MIPs? 21. Что означает аббревиатура CISC? 22. Какие две цифры можно закодировать одним битом? 23. Чему равно приставка К (кило) в вычислительной технике? 24. Сколько Кбайт в одном Мбайте? 25. Сколько Мбайт в одном Гбайте? 26. Сколько страниц текста можно сохранить в памяти объемом 4 Гбайт? 27. Какие две области находятся в памяти, доступной процессору в реальном режиме его работы? 28. Сколько памяти отводится под ТРА? 29. Сколько занимает системная область памяти или, иначе, верхняя память? 30. Сколько байт памяти адресует микропроцессор 8086? 31. Сколько байт памяти адресует микропроцессор Pentium 4? 32. Какой микропроцессор способен адресовать 4 Гбайт памяти? 33. Как называется область памяти за пределами памяти, доступной в реальном режиме работы процессора? 34. Для чего предназначена базовая система ввода-вывода (BIOS)? 35. Для чего предназначена операционная система DOS? 36. В чем разница между компьютерными системами класса XT и АТ? 37. Что такое локальная шина VESA? 38. Какова разрядность интерфейсных карт, поддерживаемых шиной ISA? 39. Что означает аббревиатура USB? 40. Что означает аббревиатура AGP? 41. Что означает аббревиатура XMS? 42. Что означает аббревиатура EMS? 43. Что означает аббревиатура TSR? 44. В каких областях памяти могут находиться драйверы? 45. В каких ситуациях используются TSR-программы? 46. Для чего предназначен файл CONFIG.SYS? 47. Каково назначение файла AUTOEXEC.BAT? 48. Какую информацию обрабатывает программа COMMAND.COM? 49. Каков объем адресного пространства системы ввода-вывода? 50. Где находится область высокой памяти (НМА)? 51. В каком файле могут встретиться операторы DEVICE и DEVICEHIGH? 52. Где находятся блоки верхней памяти (UMB), используемые MS-DOS? 86 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. Где располагается видео-BIOS? Нарисуйте типичную блок-схему компьютерной системы. Для чего предназначен микропроцессор в компьютерной системе? Какие шины используются в типичной компьютерной системе? По какой шине передается адрес порта и ячейки памяти? Какой управляющий сигнал инициирует чтение памяти? Для чего предназначен сигнал IORC ? Какую операцию выполняет микропроцессор, когда сигнал MRDC имеет значение 0? Для чего предназначены следующие директивы: a) DB б) DQ В) DW Г) DD Преобразуйте следующие двоичные числа в десятичный формат: а) 1101.01 б) 111001.0011 в) 01011.0101 г) 11.0001 Преобразуйте в десятичный формат следующие восьмеричные числа: а) 234.5 б) 12.3 в) 7767.07 г) 123.45 д) 72.72 Преобразуйте в десятичный формат следующие шестнадцатеричные числа: а) АЗ.З б) 129.С в) AC.DC г) FAB.3 д) BB8.0D Преобразуйте следующие целые десятичные числа в двоичный, восьмеричный и в шесТ' надцатеричный форматы: а) 23 б) 107 в) 1238 г) 92 Д) 173 Преобразуйте следующие десятичные числа в двоичный, восьмеричный и в шестнаДИ31*’ ричный форматы: а) 0.625 б) .00390625 в) .62890625 87 8 микРопР°ЦессоРы и компьютеры г) 0.75 л)*375 ЗаПи1ПИтс следующие шестнадцатеричные числа в двоичном формате: *’ ,рз б) AD4 в) 34 AD Г) BD32 д) 234-3 Запишите следующие двоичные числа в шестнадцатеричном формате: ' а) Ц00 0010 6) 0001 0000 1111 1101 В) 1011 1100 г) 0001 0000 д) юоо 1011 1010 (9 Вычислите инверсный код для следующих двоичных чисел: а) 1000 1000 6)0101 1010 в) 0111 0111 г) 1000 0000 70. Получите дополнительный код для следующих двоичных чисел: а) 1000 0001 б) 1010 1100 в) 1010 1111 г) 1000 0000 71. Запишите на ассемблере пример задания байта, слона и двойного слова с произвольными их значениями. 22. Запишите следующие последовательности символов в коде ASCII: a) FROG б) Аге в) Water г) Well 73- Какой ASCII -код у клавиши <Enter> и что она обозначает? ' Запишите директиву задания данных для хранения строки 'What time is it?'. Преобразуйте следующие десятичные числа в двоичные знаковые байты: а) +32 6) -12 ») +100 ’6. г) -92 Преобразуйте следующие десятичные числа в двоичные слова со знаком: а) +1000 6) -120 ®) +800 г> -3212 88 77. 78. Запишите директиву задания одного элемента данных со значением -34. Задайте следующие слова в памяти, используя вместо директивы DW директиву db (ка*д слово следует задавать парой байт): а) 1234Н б) А122Н в) В100Н 79. В чем разница между форматами обратного порядка байтов (big endian) фирмы Motorola и прямого порядка байтов (little endian) Intel при хранении данных размерностью больщ. байта? 80. 81. Запишите директиву задания элемента данных с шестнадцатеричным значением 123А. Преобразуйте следующие десятичные числа в форматы упакованных и неупакованных BCD-чисел: a) 102 6)44 в) 301 г) 1000 82. Преобразуйте следующие двоичные числа в знаковые десятичные: а) 10000000 б) 00110011 в) 10010010 г) 10001001 83. Преобразуйте следующие упакованные BCD-числа в десятичные: а) 10001001 б) 00001001 в) 00110010 г) 00000001 84. Преобразуйте следующие десятичные числа в действительные числа одинарной точности: а) +1.5 б) -10.625 в) +100.25 г) -1200 85. Преобразуйте следующие действительные числа одинарной точности в десятичные числа: а) 0 10000000 11000000000000000000000 б) 1 01111111 00000000000000000000000 в) 0 10000010 10010000000000000000000 86. Найдя дополнительную информацию в Internet, составьте краткое сообщение о следу10' щих изобретателях: • Чарльз Бэббидж (Charles Babbage) • Конрад Цузе (Konrad Zuse) • Жозеж Жаккар (Joseph Jacquard) • Герман Холлерит (Herman Hollerith) 89 ..е в микропроцессоры и компьютеры ------------- ----------------------- чдЯ дополнительную информацию в Internet, составьте краткое сообщение о следую- 87. А*1* языках программирования: щи*' Кобол (Cobol) Алгол (Algol) фортран (Fortran) Паскаль (Pascal) Найдя дополнительную информацию в Internet, составьте краткое сообщение об особен- 88 ностях микропроцессора Itanium. ГЛАВА 2 Микропроцессор и его архитектура у Введение В этой главе мы рассмотрим программную модель микропроцессоров Intel и принд. тые в них механизмы адресации памяти. Методы адресации представлены для реального и защищенного режимов. В реальном режиме доступна память по адресам 00000Н—FFFFFH (1 Мбайт в начале адресного пространства); возможности реального режима одинаковы для всех версий микропроцессоров Intel. В защищенном режиме, начиная с микропроцессора 80286 адресное пространство расширено до 16 Мбайт для 80286, до 4 Гбайт для 80386— Pentium и 4/64 Гбайт для Pentium Pro—Pentium 4. Темы главы В этой главе мы рассмотрим: □ функции и назначение программно-доступных регистров микропроцессоров 8086—80486 и Pentium—Pentium 4; □ регистр флагов микропроцессора и назначение флагов; □ доступ к памяти в реальном режиме; □ доступ к памяти в защищенном режиме; □ программно-недоступные регистры микропроцессоров 80286—Pentium 4; □ страничную организацию памяти. 2.1. Внутренняя архитектура микропроцессора Знакомство с архитектурой микропроцессора — необходимый предварительный этап в освоении системы команд и разработке первых программ. Предметы рассмотрение в этом разделе — программно-доступная часть внутренней архитектуры микропр0 цессоров 8086—Pentium 4 и назначение их регистров. Программная модель микропроцессора Программная модель микропроцессора представляет собой программно-^ часть его внутренней архитектуры. В нее входят, в частности, программно-^ 91 ifpenecc°P и его архитектура регистры, которые могут быть указаны в качестве операндов Прочие регистры, доступные лишь косвенно, относятся к категории про-^доступных. Рассмотрение этих регистров представлено далее в этой главе. гр^Н°^ с микропроцессора 80286, программно-недоступные регистры применяют-ИачйН управления памятью в защищенном режиме. Сегментные регистры Код Данные Дополнительные данные Стек Рис. 2.1. Программная модель микропроцессоров Intel р^фаммная модель микропроцессоров 8086—Pentium 4 показана на рис. 2.1. Для иих версий микропроцессоров Intel (8086, 8088 и 80286) характерна 16-битная 92 Г* архитектура с набором регистров, показанных на рис. 2.1. В процессорах 8038* Pentium 4 архитектура 32-битная. Эти архитектуры (16- и 32-битная) совместив снизу вверх. Затененные области на рис. 2.1 обозначают те элементы архитектур которые свойственны микропроцессорам 80386—Pentium 4, но отсутствуют в 16-613} ных микропроцессорах 8086—80286. В программную модель входят 8-, 16- и 32-битные регистры. К 8-битным относят*. АН, AL, ВН, BL, CH, CL, DH и DL — так они обозначаются в языке ассемблер при указании их в качестве операндов инструкций. Пример — команда add al д? которая прибавляет 8-битное число в регистре АН к 8-битному числу в регистре ai (при этом изменяется только содержимое AL). К 16-битным регистрам относят*. АХ, ВХ, СХ, DX, SP, BP, DI, SI, IP, FLAGS, CS, DS, ES, SS, FS и GS. Приме! команды с использованием этих регистров: add dx,cx. Эта команда складывает 16-битные данные, хранящиеся в регистрах СХ и DX, помещая‘результат в DX (со. держимое СХ при этом не изменяется). Расширенные 32-битные регистры — ЕДУ ЕВХ, ЕСХ, EDX, ESP, EBP, EDI, ESI, EIP и EFLAGS. Расширенные регистры, а также 16-битные регистры FS и GS доступны для процессоров начиная с 80386. Пример команды с расширенными регистрами: add есх,евх. Регистры разделяются на специализированные регистры и регистры общего назначения. К регистрам общего назначения относятся ЕАХ, ЕВХ, ЕСХ, EDX, EBP, EDI и ESI. Они используются для хранения данных различной размерности (байт, слов или двойных слов), их назначение определяется исключительно логикой программы. Регистры общего назначения Рассмотрим регистры общего назначения и особенности их применения. □ ЕАХ (accumulator — аккумулятор) ЕАХ адресуется как 32-битный (ЕАХ), 16-битный (АХ) или как 8-битный регистр (АН и AL)1. При записи в 8- или 16-битный регистр остальная часть регистра ЕАХ остается без изменений. Регистр-аккумулятор EAX/AX/AL используется в качестве обязательного операнда таких инструкций, как умножение, деление, двоично-десятичная коррекция и т. д. Хотя в этих командах аккумулятор используется специальным образом, в остальных случаях он является типичным регистром общего назначения. В процессорах 80386—Pentium 4 допускается косвенная адресация памяти через регистр ЕАХ. □ ЕВХ (base index — указатель базы) ЕВХ адресуется как ЕВХ, ВХ, BL или ВН. Регистр ВХ во всех поколениях микропроцессоров Intel допускает применение в качестве указателя. В процессора* от 80386 и выше регистр ЕВХ также может быть использован для косвенной аД* ресации памяти. □ ЕСХ (count — счетчик) ЕСХ-регистр общего назначения, но в некоторых инструкциях играет роль счет чика. В микропроцессорах 80386—Pentium 4 может применяться для косвенн адресации. В качестве счетчика используется строковыми инструкциями с пр6 1 АН и AL обозначают, соответственно, старший и младший байты регистра АХ. — Пер. 93 d о о о ^nniieccop и его архитектура ~~ ксами повторения rep/repe/repne, инструкциями сдвига и циклического сдви-напримеР» loop/loopd. При сдвигах и циклических сдвигах в регистре CL на-га’ тсЯ число сдвигов; счетчик повторов строковых инструкций с префиксами х°вТорения хранится в СХ, а команды циклов ведут счет либо в СХ, либо в ЕСХ. ЕрХ (data - данные2) ерХ-регистр общего назначения, но дополнительно используется для сохране-ния части результата умножения и, при делении, для хранения части делимого. В микропроцессоре 80386 и выше допускает применение в качестве указателя при адресации к памяти. gpp (base pointer — указатель базы3) регистр ЕВР адресуется как ВР и ЕВР; в любом из этих вариантов может быть использован в качестве указателя базы. EDI (destination index — указатель приемника) регистр EDI адресуется как EDI и DI; в строковых командах используется в качестве указателя операнда-приемника. ESI (source index — указатель источника) Регистр адресуется как ESI или SI; в строковых командах адресует операнд-источник. Специализированные регистры К специализированным регистрам относятся регистры EIP, ESP, EFLAGS, а также сегментные регистры — CS, DS, ES, SS, FS и GS. О EIP (instruction pointer — указатель инструкции) Регистр адресует следующую инструкцию в области памяти, определенной в качестве сегмента кода. В реальном режиме указатель инструкции занимает младшее слово EIP — регистр IP; целиком регистр EIP используется в защищенном режиме процессоров 80386—Pentium 4. Указатель инструкции может быть изменен командой перехода или вызова подпрограммы. & ESP (stack pointer — указатель стека) Регистр ESP адресует область памяти, определенную в качестве стека. Стек хранит данные от адреса, заданного в ESP (подробности обсудим позднее, при изучении инструкций для работы со стеком). Регистр ESP целиком используется в защищенном режиме процессоров 80386—Pentium 4, а младшая его часть (регистр SP) — в реальном режиме. eflags (регистр флагов) Регистр характеризует состояние микропроцессора и управляет его настройками. На рис. 2.2 показано содержимое регистра флага для всех версий микропроцес < р негИстр EDX/DX также называют “расширителем аккумулятора” — в командах деления и умноже-j он используется в паре с ЕАХ/АХ. — Пер. Меется в виду "база" стека — точка отсчета, которую устанавливают перед операциями над дан-’Ми в стеке. — Пер. 94 Гпава 2 соров Intel. Обратите внимание, что в процессорах от 8086/8088 до Pentium 4 флаги совместимы снизу вверх. В 8086—80286 флаги хранятся в 16-битном регистре FLAGS; начиная с микропроцессора 80386 применяется расширенный (extended) 32-битный регистр флагов — EFLAGS. Рис. 2.2. Регистры EFLAGS и FLAGS для микропроцессоров i80x86—Pentium 4 Состояние пяти флагов справа на рис. 2.2 и флага переполнения изменяется при выполнении большинства арифметических и логических инструкций. Флаги никогда не изменяют свое значение при передаче данных и при выполнении команд передачи управления. Некоторые флаги используются для настройки операций микропроцессора. Ниже приведен перечень флагов с их краткой характеристикой (подробности — по мере изучения системы команд). □ С (carry — перенос) Флаг С содержит значение переноса после операции сложения или заема после вычитания. Часто используется как признак ошибки при выполнении функций операционной системы (см. Приложение 1) или пользовательских процедур. □ Р (parity — паритет) Флаг сброшен в 0, если результат операции содержит нечетное число бит, установленных в 1; иначе (если число единичных бит результата операции четное), флаг Р установлен в 1. Например, если число содержит три единицы, то паритет нечетный, и флаг Р = 0. Если число равно 0 (все биты сброшены в 0), то паритет четный, и Р = 1. Флаг Р был введен в первых микропроцессорах для поддержки коммуникационных приложений — для формирования бита паритета при передаче и контроля ошибок паритета при приеме. Формирование и контроль паритета в современных устройствах приемопередачи встроенный, поэтому флаг Р используется сейчас довольно редко. □ A (auxiliary carry — промежуточный перенос) Флаг содержит значение переноса из третьего бита в четвертый (так называемый полуперенос) при сложении, или значение заема из четвертого бита при вычитании. Значение флага А проверяется при выполнении инструкций daa и das для коррекции значения в AL после сложения или вычитания двоично-десятичных чисел. Значение этого флага на выполнение других инструкций не влияет. Микропроцессор и его архитектура 95 О Z (zero — ноль) Флаг Z устанавливается в 1, если результат равен 0; сбрасывается в 0, если результат отличен от нуля. О S (sign — знак) Флаг содержит копию знакового бита результата арифметической или логической операции. Если S = I, знак отрицательный (число меньше нуля); если S = 0, то знак положительный (число меньше или равно нулю). □ TF (trap flag — флаг ловушки4) Флаг обеспечивает аппаратную поддержку пошаговой отладки (например, в отладчике CodeView). Когда режим трассировки установлен (TF = 1), микропроцессор прерывает выполнение программы после каждой инструкции. О IF (internipt flag — флаг прерывания) Флаг разрешает проверку внешнего запроса на прерывание по входу INTR (interrupt request). При IF = 1 проверка входа INTR разрешена; если же IF = 0, то состояние INTR не контролируется микропроцессором. Установка флага IF в 1 выполняется инструкцией sti (set I flag), сброс — командой сы (clear I flag). □ D (direction — направление) Флаг определяет режим автоматического изменения (увеличение или уменьшение) регистров DI и/или SI при выполнении строковых инструкций. Если D = 1, значения этих регистров автоматически уменьшается, при D = 0 — увеличивается. Установка флага D выполняется командой std (set direction); команда cld (clear direction) обнуляет флаг D. □ О (overflow — переполнение) Флаг отражает переполнение при сложении и вычитании знаковых чисел. Переполнение означает, что результат превысил возможности машины. Например, результат сложения 8-битных значений 7FH (+127) и 01Н равен 80Н (-128). Флаг О устанавливается в 1, поскольку' эта величина, полученная в результате 8-битного сложения, не может быть представлена в формате 8-битного числа со знаком. □ IOPL (I/O privilege level — уровень привилегий ввода-вывода) Флаг используется в защищенном режиме, где определяет уровень привилегий ввода-вывода текущей задачи. Если текущий уровень привилегий выше уровня, указанного в поле IOPL, то ввод-вывод выполняется беспрепятственно. Если IOPL ниже текущего уровня привилегий, генерируется прерывание, приостанав-. ливающее выполнение программы. Заметим, что IOPL = 00 соответствует высшему уровню привилегий, a IOPL =11 — низшему. □ NT (nested task — вложенная задача) Флаг NT установлен в 1, если текущая задача является вложенной по отношению к другой задаче. 4 Также называется флагом трассировки. — Пер. м----------------------------------------------------------------------0*2^ □ RF (resume — возобновление) Флаг используется при отладке для возобновления программы после выполнена следующей инструкции. 7 □ VM (virtual mode — режим виртуальной машины) Флаг определяет режим виртуальной DOS-машины в рамках защищенного жима. Каждой виртуальной машине выделяется блок памяти размером 1 Мбайь из пространства памяти защищенною режима, что позволяет операционной теме выполнять несколько DOS-программ. □ AC (alignment check — контроль выравнивания) Флаг АС разрешает прерывания при доступе к словам или двойным словам, цр выровненным по границам слова или двойного слова соответственно. В микро., процессоре 80486SX этот флаг использовался для синхронизации встроенного сопроцессора 80487SX. П VIF (virtual interrupt flag — виртуальный флаг прерывания) Флаг VIF копия флага IF в микропроцессорах Pentium—Pentium 4. □ VIP (virtual internipt pending — виртуальный флаг задержки прерывания) Флаг предоставляет информацию о прерывании для процессоров Pentium-Pentium 4; используется в многозадачных операционных системах совместно с флагом VIF. □ ID (identification — идентификация) Если значение этого флага может быть изменено программным путем, то процессор поддерживает инструкцию cpuid (Pentium—Pentium 4). Инструкция cpuid дает такие сведения о микропроцессоре, как номер версии и код производителя. Сегментные регистры Сегментные регистры, в сочетании с другими регистрами микропроцессора, используются при генерировании адреса памяти. В различных версиях микропроцессоров число сегментных регистров составляет 4 или 6. Содержимое сегментных регистров в реальном и защищенном режимах используется различным образом (подробнее этот вопрос мы обсудим чуть позже в данной главе). Ниже приведен список сегментных регистров с указанием их назначения и особенностей. □ CS (code — код) Сегмент кода представляет собой область памяти, в которой содержатся иН^ рукции программы. Сегментный регистр CS определяет стартовый адрес этой области памяти. В реальном режиме CS указывает непосредственно на сегмент кода — область размером 64 Кбайт. В защищенном режиме CS указывает на ДесК* риптор, в котором хранится описание сегмента кода, включая начальный адрсс размер сегмента. Размер сегмента кода в процессорах 8088—80286 ограните 64 Кбайт, но в защищенном режиме 32-битных процессоров может достига 4 Гбайт. □ DS (data — данные) Сегмент данных представляет собой область памяти для хранения данных ПР^ граммы. Адрес данных определяется сочетанием сегментного адреса в регистр* 97 d ^nnueccop и его архитектура -------- и смешения, значение которого находится либо в самой инструкции, либо в трС-указателе. Размер сегмента данных в процессорах 8088—80286 не пре-1Ш^еТ Кбайт, для 32-битных процессоров ограничен 4 Гбайт. gS (extra дополнительные данные) р гистр оказывает местоположение операнда-приемника при выполнении строевых инструкций. 0 SS (Stack - стек) регистр определяет область памяти для системного стека. Адрес вершины стека образуется сочетанием значений SS и ESP/SP. Регистр ЕВР/ВР, в паре с SS, применяется для доступа к данным, расположенным в любой точке сегмента стека. □ FS и GS Дополнительные сегментные регистры, предназначенные для поддержки добавочных сегментов данных; доступны в процессорах 80386—Pentium 4. 2.2. Адресация памяти в реальном режиме Микропроцессорам 80286—Pentium 4 доступны два режима функционирования — реальный и защищенный. Процессоры 8086/8088, напротив, работают только в реальном режиме. В этом разделе мы подробно рассмотрим реальный режим адресации памяти. Реальный режим позволяет микропроцессору, даже если это Pentium 4, адресовать только 1 Мбайт памяти. Операционная система DOS рассчитана на реальный режим; соответственно программы, написанные для 8086/8088, могут работать на процессорах 80286—Pentium 4 в реальном режиме без изменения программного кода. (Заметим, что совместимость программного обеспечения снизу вверх определяет, наряду с другими факторами, успех микропроцессоров Intel.) Все версии микропроцессоров Intel включаются в работу именно в реальном режиме, как при включении питания, так и при повторном запуске. Сегменты и смещения В реальном режиме адрес памяти представляет собой комбинацию сегментного ад-реса и смещения. Сегментный адрес, заданный одним из сегментных регистров, определяет начало сегмента памяти объемом 64 Кбайт. Смещение задает положение Ячейки памяти внутри сегмента. Рис. 2.3 иллюстрирует вычисление адреса памяти в Реальном режиме — по значениям сегментного адреса и смешения. Сегмент на РИс- 2.3 занимает адреса 10000Н— 1FFFFH (всего 64 Кбайт). Поскольку сегмент начинается с адреса 10000Н, а смещение составляет F000H, то адрес ячейки памяти Равен 1F000H. Напомним, что значение смещения определяет расстояние в байтах т Начала сегмента. в ^Ратите внимание, что начало сегмента на рис. 2.3 расположено по адресу 10000Н, То время как сегментный регистр содержит 1000Н. В реальном режиме при вычис-нии адреса сегмента к значению сегментного регистра микропроцессор добавляет Рава ОН. Так формируется 20-битный адрес памяти, определяющий начало сег-еНта. Расширение адреса до 20 бит позволяет адресовать 1 Мбайт памяти. Напри-еР, если сегментный регистр содержит 1200Н, то посредством этого регистра дос- 4 Зак 3N4 98 Гпава 2 тупна память размером 64 Кбайт с адреса 12000Н. Если значение сегментного регистра равно 1201Н, он адресует сегмент памяти с адреса 12010Н. Поскольку значение сегментного регистра дополняется ОН, в реальном режиме сегменты выровнены по 16-байтным границам. Промежуток в 16 байт между соседними сегментами называется параграфом. Рис. 2.3. Механизм адресации памяти в реальном режиме Поскольку в реальном режиме сегмент имеет фиксированную длину 64 Кбайт, то конечный адрес сегмента равен сумме начального адреса и FFFFH. Например, если сегментный регистр содержит 3000Н, то первый адрес в сегменте равен 30000Н, а последний — 30000Н + FFFFH, т. е. 3FFFFH. В табл. 2.1 показаны несколько значений сегментного регистра и соответствующие им адреса границ сегмента в памяти. Таблица 2.1. Примеры значений сегмента и его границ Значение сегментного регистра Начальный адрес Конечный адрес 2000Н 20000Н 2FFFFH 2001Н 20010Н 3000FH 21 ООН 21000Н 30FFFH AB00H AB000H BAFFFH 1234Н 12340Н 2233FH Микропроцессор и его архитектура 99 При формировании адреса памяти значение смещения, как часть адреса, прибавляется к стартовому адресу сегмента. Например, если сегментный регистр содержит 1000Н, а смещение составляет 2000Н, то микропроцессор обратится к памяти по адресу 12000Н. Составляющие адреса — сегмент и смещение — часто записывают парами через двоеточие. Например, 1000:2000 означает сегмент 1000Н и смещение 2000Н. В микропроцессорах 80386—Pentium 4, а также в некоторых версиях процессора 80286 наличие сегмента FFFFH позволяет адресовать в реальном режиме помимо 1 Мбайта еще одну область памяти объемом 64 Кбайт минус 16 байт. Это так называемая высокая память, которая находится в диапазоне адресов 0FFFF0H—10FFEFH п доступна программам реального режима при установке драйвера HIM ЕМ.SYS. Если сегментный адрес равен FFFFH, то при добавлении смещения микропроцессор устанавливает активный уровень на адресной линии А20. Например, при сочетании сегмента и смещения FFFF:4000, результирующий адрес составляет FFFF0H + 4000Н = 103FF0H. Обратите внимание, что в адресе 103FF0H бит 20 установлен в 1. Если управление линией А20 не поддерживается, то бит 20 адреса не передается, и микропроцессор обращается к ячейке по адресу 03FF0H. В некоторых методах адресации смещение задается суммой значений регистров и/или постоянной величины, которая может превысить предельную длину сегмента — FFFFH. Например, если сегментный адрес равен 4000Н, а смещение определяется суммой составляющих F000H и 3000Н, то процессор обратится к ячейке по адресу 42000Н, а не по адресу 52000Н. Дело в том, что результат сложения F000H и 3000Н составляет не 12000Н, а всего 2000Н, поскольку ограничен 16 битами. Перенос при сложении отбрасывается — на определение адреса памяти он не влияет. В итоге генерируется адрес, соответствующий сегменту и смещению 4000:2000, т. е. 42000Н. Сочетания сегментов и смещений, действующие по умолчанию Каждый из сегментных регистров связан по умолчанию с определенными источниками смещений. Правила, устанавливающие соответствие между сегментными регистрами и источниками смещений, действуют как в реальном, так и в защищенном режиме. Например, сегментный регистр кода всегда используется в паре с регистром указателя инструкции — для доступа к следующей исполняемой инструкции. Выбор между парами регистров CS:IP и CS:EIP определяется режимом микропроцессора. Сегментный регистр CS определяет начало сегмента кода, а указатель инструкции E1P/IP задает смещение внутри кодового сегмента. Например, если в реальном режиме CS = 1400Н, a IP = 1200Н, то микропроцессор считывает инструкцию из памяти по адресу 14000Н + 1200Н = 15200Н. Для доступа к стеку применяются пары регистров SS:SP (SS:ESP) и SS:BP (SS.EBP). Например, если SS = 2000Н, a BP = 3000Н, то при использовании ВР в качестве указателя микропроцессор обратится к памяти по адресу 23000Н. Заметим, что в реальном режиме в качестве смещения используются только младшие 16 бит расширенного регистра. Поэтому в процессорах 80386—Pentium 4 при работе в реальном 100 j режиме не следует задавать значения смещений в регистрах-указателях больщ FFFFH. В противном случае система остановится5. Возможные сочетания сегментов и 16-битных смещений, действующие по умодц^ нию, приведены в табл. 2.2. В табл. 2.3 приведены аналогичные данные дд* 32-битных смещений6. Обратите внимание, что процессоры 80386—Pentium 4 располагают большим числом сочетаний сегментов и источников смещений по сравнению с 8086—80286. Таблица 2.2. Сочетания сегментов и 16-битных смещений, действующие по умолчанию Сегмент Смещение Назначение адреса CS IP Адрес инструкции SS SP или ВР Адрес стека DS ВХ, DI, SI, 8- или 16-битное число Адрес данных ES DI (для строковой инструкции) Адрес приемника строковой команды Таблица 2.3. Сочетания сегментов и 32-битных смещений, по умолчанию Сегмент Смещение Назначение адреса CS EIP Адрес инструкции SS ESP или ЕВР Адрес стека DS ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, 8- или 32-битное число Адрес данных ES EDI (для строковой инструкции) Адрес приемника строковой команды Микропроцессоры 8086—80286 располагают четырьмя сегментными регистрами, а процессоры от 80386 и выше — шестью. Количество сегментных регистров ограничивает число текущих сегментов программы. На рис. 2.4 показан пример расположения в памяти четырех сегментов. Заметим, что текущие сегменты могут пересекаться друг с другом; обычно это происходит, если программе требуется часть сегмента размером меньше 64 Кбайт. Сегменты можно представить себе окнами, которые обеспечивают доступ к данным или инструкциям и могут перемещаться в памяти. Заметим также, что число сегментов в программе может превышать число сегментов, поддерживаемых микропроцессором; но в каждый момент времени Д°с' тупны только четыре или шесть сегментов, в зависимости от версии микропроцессора. 5 В реальном режиме при значении смещения больше 0FFFFH генерируется исключение °б защиты. Поскольку в DOS 6.22 это исключение не обрабатывается надлежащим образом, систе "повисает" без каких-либо сообщений. — Пер. мИХ 6 Сегментные регистры FS и GS здесь не указаны, т. к. источник смещения по умолчанию ДЛЯ и не определен. — Пер. npoUeccoP и его архитектура 101 Память -| 4 9 О О I ES -| 3 4 О О | SS j~ 2 О О О | CS 1 О О О | DS Рис. 2.4. Пример расположения сегментов в памяти Предположим, что прикладная программа требует 1000Н байт памяти для инструкций, 190Н байт для данных, 200Н байт для стека, а дополнительный сегмент данных не нужен. Программа загружается в подходящую по размеру область в ТРА над Драйверами и другими программами, уже находящимися в ТРА. Загрузка выполняйся специальной программой в составе DOS. Расположение прикладной программы в памяти после загрузки показано на рис. 2.5. Видно, что сегменты пересекаются МеХцу собой, поскольку длина каждого из них меньше 64 Кбайт. Возможность перемещения программы в памяти ^еханизм адресации памяти посредством сегментов и смещений, хотя и кажется ^Ишне сложным, упрощает распределение памяти при загрузке программ. Кроме Го, благодаря этой схеме адресации, программы, написанные для работы в реаль-°м режиме, могут работать так же и в защищенном режиме. Код и данные могут ,Ть помещены в произвольные области памяти без изменений в программе, что °3&оляе7 использовать одно и то же программное обеспечение на машинах с раз-и конфигурацией памяти. ^Оскольку данные в пределах сегмента адресуются смещением, сегмент может быть Умещен в любую область адресного пространства без коррекции смещений. Пе-К1еЩение выполняется следующим образом: программа копируется, как единый 102 Пересечение сегментов Память Рис. 2.5. Пример расположения сегментов кода, данных и стека прикладной программы блок памяти, целиком в новую область, после чего корректируются значения сегментных регистров. Если смещение некоторой инструкции от начала сегмента составляет 4 байта, то после перемещения программы расстояние этой инструкции от начала сегмента остается таким же — 4 байта. Все, что требуется после копирования программы в новую область, — подправить значения сегментных регистров. В отсутствие сегментов переместить программу, не исправляя ее код, было бы невозможно. В результате для разных конфигураций памяти пришлось бы поддерживать несколько разных версий программы7. 7 Разработка перемещаемых программ возможна даже в этой ситуации, хотя требует более развиты^ методов адресации, не поддерживаемых процессорами Intel. Например, при разработке драйверов операционной системе RT-11 для компьютеров PDP-11 (фирмы DEC) применялись специальна приемы для замены абсолютных смещений относительными, когда адрес операнда задается К** расстояние от операнда до инструкции. В результате драйверы для RT-1I допускали размешен в любой области памяти в пределах 64 Кбайт. — Пер. 103 саиии в -объекта^ адреса. -тифииирует л teccop и его архитектура -------------- 2 з ВвеДение в защищенный режим нныи режим адресации памяти (в процессорах от 80286 и выше) открывает 3^и к данным и коду за пределами памяти, ограниченной 1 Мбайтом. При адре-достУп^ заШИ1ценном режиме смещение по-прежнему задает положение адресуемого .j сегменте. Основное отличие от реального режима — отказ от сегментного Теперь в сегментном регистре хранится значение селектора, который иден-- — дескриптор, заданный в таблице дескрипторов. Дескриптор описывает ^^дожение сегмента в памяти, его размер, а также права доступа к сегменту. По-^льку сегментный регистр и смещение по-прежнему используются для доступа к памяти, инструкции процессора в защищенном режиме не отличаются от инструкций реального режима. Поэтому многие программы, написанные в расчете на реальный режим, работают без изменений и в защищенном режиме. Разница между режимами заключается в разной интерпретации значения сегментного регистра. Еще одна особенность защищенного режима состоит в том, что в процессорах 80386— Pentium 4 смещение может быть задано 32-битным числом, что позволяет адресовать данные в сегменте размером до 4 Гбайт8. Селекторы и дескрипторы Селектор, заданный в сегментном регистре, определяет выбор одного из 8192 дескрипторов, хранящихся в глобальной или в локальной таблице дескрипторов. Дескриптор содержит информацию о расположении и длине сегмента, а также о правах доступа к сегменту. В итоге, сегментный регистр по-прежнему определяет выбор сегмента памяти, но косвенно, в отличие от реального режима, где выбор прямой. Например, значение CS = 0008Н в реальном режиме определяет сегмент кода по адресу 00080Н. В защищенном режиме при таком значении регистра CS соответствующий сегмент кода может находиться в любой области адресного пространства. Для задания дескрипторов предусмотрены две таблицы дескрипторов', в одной содержатся глобальные дескрипторы, в другой — локальные. В таблице глобальных Дескрипторов хранятся определения сегментов, доступные всем программам; напротив, локальные дескрипторы используются только одним приложением. Глобальные дескрипторы называют также системными, а локальные дескрипторы — дескрипторами приложения. Таблицы дескрипторов содержат максимум по 8192 дескрипторов; таким образом общее число дескрипторов, одновременно доступных приложению, не пРевышает 16384. Это число определяет максимальное количество сегментов в про-ирамме (поскольку каждый дескриптор содержит описание одного сегмента памяти). ра рис. 2.6 показан формат дескриптора для процессоров от 80286 азмерность дескриптора — 8 байт; таким образом, объем таблицы Лобальной или локальной) может достигать максимум 64 Кбайт. скриптора в процессоре 80286 имеет некоторые особенности, они вместимости с процессорами 80386—Pentium 4. до Pentium 4. дескрипторов Хотя формат не нарушают 8 °зможность применять в качестве указателей расширенные регистры есть и в Ме - Пер. реальном режи- 104 Глава? Базовый адрес, входящий в состав дескриптора, определяет положение сегмента 3 памяти. Для микропроцессора 80286 базовый адрес 24-битный, что ограничивает адресное пространство 16 Мбайт. Заметим, что выравнивать сегменты по граница^ параграфов в защищенном режиме не требуется. В процессорах 80386 и выше используется 32-битный базовый адрес, что позволяет располагать сегмент с любой точки адресного пространства 4 Гбайт. Обратите внимание, что старшие 16 бит базового адреса в дескрипторе процессора 80286 содержат 0. Тем самым обеспечивается совместимость снизу вверх базовых адресов дескрипторов процессора 80286 и процессоров 80386—Pentium 4. (Адресное пространство объемом 64 Гбайт в процессорах Pentium Pro—Pentium 4 рассматривается в главах 18 и 19.) Дескриптор для 80286 Дескриптор для 80386 - Pentium 4 7 00000000 00000000 6 7 База (В31-В24) G D 0 А V Предел (L1O4.16) 6 5 Права доступа База (В23-В16) 4 5 Права доступа База (В23-В16) 4 3 База (В15-ВО) 2 3 База (В15-В0) 2 1 Предел (L15-L0) 0 1 Предел (L15-L0) 0 Рис. 2.6. Форматы дескрипторов для микропроцессоров 80286 и 80386—Pentium 4 Предел сегмента (segment limit) в дескрипторе задает размер сегмента и, в совокупности с базовым адресом, определяет верхнюю границу сегмента в памяти. Например, если сегмент начинается с адреса F00000H и заканчивается по адресу F000FFH, то базовый адрес сегмента равен F00000H, а предел (limit) — FFH. Предел для 80286 задается 16-битной величиной, а для 80386—Pentium 4 — 20-битной. Длина сегмента в процессоре 80286 ограничена значениями 1 байт и 64 Кбайт. В процессорах 80386 и выше размер сегмента находится в пределах от 1 байта до 1 Мбайта или от 4 Кбайт до 4 Гбайт. В процессорах 80386—Pentium 4 дескриптор содержит дополнительный бит гранулярности (granularity bit) или иначе бит дробности (бит G). Если G = 0, то поле предела задает длину сегмента в байтах — от 00000Н до FFFFFH. Если G = 1, то единице в поле предела соответствует 4 Кбайт адресного пространства (т. е. к значению предела добавляется справа хххН, где хххН — любое значение от 000Н до FFFH). Таким образом, при G = 1 размер сегмента находится в диапазоне от ОООООхххН до FFFFFxxxH байт, т. е. от 4 Кбайт до 4 Гбайт (шаг изменения предела — 4 Кбайт). То, что длина сегмента в процессоре 80286 ограничена 64 Кбайтами, объясняется 16-битной архитектурой этого процессора — поэтому и смещение ограничено 16 битами. В процессорах от 80386 и выше используется 32-битная архитектура, И смещение может быть задано 32 битами. Смещение, заданное 32 битами, позволяет адресовать данные в сегменте длиной 4 Гбайта, в то время как 16-битное смешение ограничивает длину сегмента 64 Кбайтами. Приведем два примера вычисления границ сегмента (стартового адреса Start и конечного адреса End) по базовому адресу (Base) и пределу (Limit). Полагаем, 4110 Base = ЮООООООН, a Limit = 001 FFH. Сначала рассчитаем значения Start и End случая G = 0. ^рпцесс°Р и его архитектура 105 ..... .. Вычисление границ сегмента для случая, когда G = О ................................-.................... U start = ЮООООООН Base G * 0 оа<=р + Limit = ЮООООООН + 001FFH = 100001FFH End * Base ob приведем расчет для G = 1, подставляя на место хххН максимальное значе- Пример 2.2. Вычисление границ сегмента для случая, когда G 3 1 Base = Start = ЮООООООН G = г EHd = Base + Limit = ЮООООООН + OOlFFxxxH = 101FFFFFH Бит AV в дескрипторах процессоров 80386 и выше используется некоторыми операционными системами как признак доступности сегмента (AV = I означает, что сегмент доступен). Бит D в процессорах 80386—Pentium 4 определяет разрядность доступа к регистрам и к памяти (и в защищенном, и в реальном режиме). Если D = 0, то инструкции — 16-битные, совместимые с микропроцессорами 8086—80286. Это означает, что в инструкциях при доступе к памяти используется по умолчанию 16-битное смещение, а при обращении к регистрам выполняется доступ к их младшим 16-битным составляющим. Этот режим называется режимом 16-битных инструкций. Если D = 1, то инструкции — 32-битные. По умолчанию в режиме 32-бит-ных инструкций смещения и регистры считаются величинами 32-битными. Заметим, что размерность регистра и смещения, действующие по умолчанию, могут быть временно изменены как в режиме 16-битных инструкций, так и в режиме 32-битных инструкций. Операционные системы MS-DOS, PC-DOS и Windows 3.1 рассчитаны на режим 16-битных инструкций. Режим 32-битных инструкций доступен лишь в защищенном режиме и применяется в таких операционных системах, как Windows NT, Windows 95, Windows 98 и OS/2. Подробнее о режимах 16- и 32-битных инструкций см. в главах 3 и 4. Байт прав доступа, приведенный на рис. 2.7, контролирует доступ к сегменту в защищенном режиме. Этот байт описывает способ функционирования сегмента в системе. Если сегмент содержит данные, то для него определено допустимое направле-Ние изменения размера. Если размер сегмента выходит за заданные пределы, генерируется исключение общей защиты. Для сегмента данных может быть также Установлена защита от записи. Контроль сегментов кода выполняется аналогичным Разом. При установленном флаге защиты кодовый сегмент не допускает даже чте-Ия’ что позволяет скрыть программный код от взлома. *ыбоР дескриптора из таблицы дескрипторов определяется содержимым сегментно-Регистра. На рис. 2.8 показано содержимое сегментного регистра в защищенном ^име. Сегментный регистр содержит 13-битное поле Индекс (Index), бит выбора ^Лицы дескрипторов (TI) и поле уровня запрашиваемых привилегий (RPL— 81g?ested Privilege Level). Поле Индекс (Index) в составе селектора выбирает один из cjt ДескРипторов из таблицы. Выбор таблицы определяет бит выбора таблицы дебиторов (TI): если TI = 0, то дескриптор извлекается из таблицы глобальных Крипторов, а если TI = 1, то используется локальная дескрипторная таблица. За- 106 Гпава 2 прошиваемый уровень привилегий (RPL — Requested Privilege Level) определяет привилегии сегмента. Высший уровень привилегий соответствует RPL = 00, а низший — Н. Если запрашиваемый уровень привилегий не ниже (по приоритету) уровня, установленного байтом прав доступа, то доступ разрешен. Например, если запрашиваемый уровень привилегий равен 10, а в байте прав доступа уровень привилегий сегмента равен II, то доступ разрешен, поскольку уровень 10 имеет более высокие привилегии по сравнению с уровнем II. Уровни привилегий в многопользовательских системах позволяют контролировать действия пользовательских программ. 7 6 5 4 3 2 1 0 Р = 1 Сегмент содержит правильные базу и предел Рис. 2.7. Байт прав доступа в микропроцессорах 80286—Pentium 4 Селектор I---------------------------------------------------- 15 3 2 1 0 Индекс Tl RPL I у L___> Запрашиваемый уровень привилегий 00 - наивысший, а 11 - низший ________TI = 0 - выбор глобальной таблицы дескрипторов TI = 1 - выбор локальной таблицы дескрипторов -----------------------» Индекс (Index) - поле выбора дескриптора из соответствующей таблицы дескрипторов Рис. 2.8. Содержимое сегментного регистра в защищенном режиме Микропроцессор и его архитектура 107 На рис. 2.9 показано, как посредством сегментного регистра, содержащего селектор, выбирается дескриптор в глобальной таблице дескрипторов. Напомним, что каждый элемент таблицы глобальных дескрипторов определяет один сегмент в памяти. Регистр DS на рис. 2.9 содержит число 0008Н, что задает выбор дескриптора номер 1 из глобальной таблицы дескрипторов, при запрашиваемом уровне привилегий 00. В дескрипторе номер 1 задан базовый адрес ООЮООООН, а предел равен 000FFH. Таким образом, в примере на рис. 2.9 значение DS = 0008Н определяет сегмент памяти в диапазоне адресов 00100000Н—001000FFH. Заметим, что дескриптор номер 0 (нуль-дескриптор) зарезервирован и не используется для доступа к памяти. Глобальная таблица Рис. 2.9. Использование регистра DS при выборе дескриптора из глобальной таблицы дескрипторов 108 Главам Программно-недоступные регистры Как мы уже говорили, глобальные и локальные дескрипторные таблицы располагаются в памяти микропроцессорной системы. Адресация этих таблиц в микропроцессорах 80286, 80386, 80486, Pentium, Pentium Pro и Pentium 4 выполняется посредством программно-недоступных регистров. На рис. 2.10 показаны программнонедоступные регистры процессоров 80286—Pentium 4, используемые в защищенном режиме. Сегментные регистры Кэш дескрипторов CS Базовый адрес Предел Доступ DS ES SS FS GS 1 i TR Базовый адрес Предал Доступ LDTR GDTR Адреса таблиц дескрипторов Программно-недоступно Базовый адрес Предел IDTR Рис. 2.10. Программно-недоступные регистры микропроцессоров 80286—Pentium 4 В каждом из сегментных регистров имеется программно-недоступная часть, исполь-* зуемая микропроцессором в защищенном режиме. При каждом изменении видимойJ части сегментного регистра в невидимую часть загружается базовый адрес, предел и! права доступа. При записи в сегментный регистр нового значения микропроцессор; считывает дескриптор из таблицы дескрипторов в программно-недоступную часть сегментного регистра. Сохраненный таким образом дескриптор управляет доступом j к сегменту памяти — до тех пор, пока значение в регистре сегмента вновь не изме-; нится. Кэширование дескриптора позволяет выполнять доступ к памяти без постоянного обращения к таблице дескрипторов. Базовый адрес и предел глобальной дескрипторной таблицы хранятся в регистре GDTR (global descriptor table register). В регистре IDTR (internipt descriptor table' register) хранятся базовый адрес и предел таблицы дескрипторов прерываний. Пре-! дел задается 16-битной величиной, что ограничивает размер таблиц в 64 Кбайт. За-; полнение глобальной таблицы дескрипторов (GDT — global descriptor table) и загрузка ее адреса и предела в регистре GDTR — необходимые операции перед входом в защищенный режим; подобным же образом должны быть инициализированы таблица дескрипторов прерываний и регистр IDTR. Информация о расположении локальной таблицы дескрипторов (LTD — local descriptor table) содержится в глобальной таблице дескрипторов: один из дескрипторов глобальной таблицы адресует локальную таблицу. Доступ к локальной таблице дескрипторов открывается при записи в регистр LDTR (local descriptor table register) селекто Микропроцессор и его архитектура 109 ра глобальной таблицы. В невидимую часть регистра LDTR записывается информация из глобальной таблицы дескрипторов — базовый адрес, предел и права доступа локальной таблицы дескрипторов. В регистре задачи TR (task register) хранится селектор, адресующий дескриптор с определением задачи. Задача чаще всего представляет собой процедуру или прикладную программу. Ее дескриптор хранится в глобальной таблице дескрипторов, что позволяет контролировать уровни привилегий. Регистр задач используется для переключения контекста в многозадачных системах — с незначительной задержкой, поскольку переключение выполняется аппаратно. 2.4. Страничная организация памяти Механизм страничной организации памяти в микропроцессорах 80386—Pentium 4 позволяет обращаться к любой ячейке физической памяти посредством произвольного линейного адреса. Линейным адресом называется адрес, который генерируется исполняемой программой. При включении механизма страничной организации памяти линейный адрес аппаратно преобразуется в физический адрес, что позволяет перераспределять в памяти программу, рассчитанную на функционирование в определенных линейных адресах. Также страничный механизм позволяет отображать линейные адреса на те области физического адресного пространства, где память вообще отсутствует. Пример такого отображения — блоки верхней памяти при установке драйвера EMM386.EXE. Программа EMM386.EXE отображает расширенную (Extended) память на верхнюю память (UMA) в области между видео-BIOS и системным BIOS. Отображение выполняется блоками по 4 Кбайта. Заметим, что в отсутствие страничного механизма отображения памяти доступ к верхней памяти в реальном режиме был бы невозможен. Регистры страничной организации памяти В работе механизма страничного преобразования адресов участвуют управляющие регистры микропроцессора. На рис. 2.11 показано содержимое управляющих регистров CRO—CR3. Эти регистры доступны только в микропроцессорах 80386—Pentium 4. Еще один управляющий регистр CR4 был введен в Pentium в связи с расширениями базовой архитектуры в этом микропроцессоре. В частности, в Pentium появилась возможность увеличить размер страницы до 4 Мбайт — при установке в 1 бита 4 регистра CR4 (подробности см. в главах 18 и 19). Из управляющих регистров в страничном преобразовании наиболее существенную роль играют CR0 и CR3. Крайний левый бит регистра CR0 (бит PG) включает механизм преобразования страниц. Если бит PG сброшен в 0, то линейный адрес, сгенерированный программой, используется — без преобразования — в качестве физического адреса. Если PG установлен в 1, то линейный адрес преобразуется в физический адрес посредством страничного механизма. Заметим, что страничный механизм функционирует как в защищенном, так и в реальном режиме работы процессора. Регистр CR3 содержит базовый адрес каталога страниц и, дополнительно, биты PCD и PWT. Биты PCD и PWT управляют одноименными выводами микропроцессора. 110 Гпава 2 Если PCD = I, то вывод PCD устанавливается в I на один цикл шины в тот момент, когда страничное преобразование не выполняется. Это позволяет внешним устройствам работать с кэш-памятью второго уровня. (Напомним, что кэш L2 представляет собой внешнюю высокопроизводительную память, которая выполняет функцию буфера между микропроцессором и внешней DRAM-памятью.) Бит PWT и одноименный вывод PVVT используются подобным же образом, также для управления кэш-памятью. Базовый адрес каталога страниц определяет его расположение в памяти. Заметим, что микропроцессор добавляет к базовому адресу справа 000Н, поэтому каталог страниц размещается по границе 4 Кбайт. Каталог страниц содержит 1024 записей по 4 байта. Каждая запись адресует таблицу страниц из 1024 элементов. Только для Pentium, Pentium Pro, Pentium II, Pentium III и Pentium 4 Рис. 2.11. Структура управляющих регистров микропроцессора Линейный адрес, сгенерированный программой, разделяется на три части; две из них определяют доступ к элементу каталога страниц и к элементу таблицы страниц, а третья задает смещение в странице. Формат линейного адреса показан на рис. 2.12. Десять бит слева адресуют элемент каталога страниц. Например, при значении линейного адреса в диапазоне 00000000Н—003FFFFFH выбирается первый элемент каталога страниц. Каждый элемент каталога страниц задает отображение 4 Мбайт памяти. Элемент каталога указывает на таблицу страниц; индекс элемента таблицы страниц задан в следующих 10 битах линейного адреса (биты 12—21). Например, адрес 00000000Н—00000FFFH определяет выбор нулевого элемента в каталоге страниц и нулевой записи в таблице страниц. Обратите внимание, что изменение на 1 индекса элемента в таблице страниц соответствует изменению линейного адреса на 4 Кбайт. Смещение, заданное младшей частью линейного адреса (биты 0—11), адресует байт в пределах страницы размером 4 Кбайт. Например, если элемент таблицы Микропроцессор и его архитектура 111 страниц на рис. 2.12, б является нулевым элементом и содержит 00100000Н, то линейный адрес из диапазона 00000000H—00000FFFH преобразуется в физический адрес от 00100000Н до 00100FFFH. В результате, когда программа обращается к памяти по адресу 00000000Н—0000FFFH, микропроцессор выполняет доступ к ячейкам из диапазона адресов 00100000Н—00100FFFH. Каталог Таблица страниц Смещение Рис. 2.12. Формат линейного адреса (а), формат элементов каталога страниц и таблиц страниц (б) Поскольку отображение памяти предполагает доступ к каталогу страниц и к таблице страниц, которые сами расположены в памяти, был введен буфер ассоциативной трансляции — TLB (Translation Look-Aside Buffer). В микропроцессоре 80486 буфер TLB сохраняет информацию о последних 32 отображениях страниц. Если программа повторно обращается к области памяти, информация о которой сохранена в TLB, то считывать элементы каталога страниц и таблицы страниц из памяти не требуется. Это ускоряет выполнение программы. Процессоры Pentium, Pentium Pro, Pentium П, Pentium III и Pentium 4 содержат раздельные буферы TLB — для кэша инструкции и для кэша данных. Каталог страниц и таблицы страниц На рис. 2.13 показаны фрагмент каталога страниц, несколько таблиц страниц и страниц памяти. Каталог страниц существует в единственном экземпляре и содержит 1024 двойных слов для адресации до 1024 таблиц страниц. Каталог страниц и каждая таблица страниц занимают по 4 Кбайта. Например, для страничного преобразования 4 Гбайт памяти требуются 4 Кбайта памяти для каталога страниц и 4 Мбайта для таблиц страниц (т. е. 1024 таблицы по 4 Кбайт). Операционная система DOS при установке драйвера EMM386.EXE использует таблицы страниц для отображения памяти в промежутке между адресами С8000Н и EFFFFH блоков верхней памяти. Это позволяет обращаться к расширенной (Extended) памяти через области верхней памяти, доступные приложениям DOS. 00003FFC 00003FF8 00003FF4 00003FF0 00003328 00003324 00003320 00003008 00003004 00003000 0000200С 00002008 00002004 ---- 00002000 Нулевая таблица страниц 00110FFF 00110FFE 00110002 00110001 00110000 00000FFF 00000FFE 00000002 00000001 00000000 Каталог страниц Страница 00000Н Рис. 2.14. Каталог страниц, нулевая таблица страниц и две страницы памяти 113 рессор и его архитектура ------- ---- жим, что ПРИ наличии драйвера EMM386.EXE требуется отобразить ли-С8000Н—EFFFFH на физические адреса 110000—138000Н, не затра-неЙНЫе гальную память. Схема отображения для этого случая приведена на гИ0аЯ Л Заметим, что страница, расположенная по адресам 000С8000—000С9000, рис- ^ажаеТСЯ на Ml 10000—00110FFF. ° еденном примере каталог страниц содержит четыре элемента. Напомним, что В пРиВ эЛементу каталога соответствует 4 Мбайт физической памяти. В данном каЖД0 отображения потребуется четыре таблицы страниц по 1024 элементов. cJI^4afoM накладные расходы составят 16 Кбайт для четырех таблиц страниц и ® байт для каталога страниц. бпажение страниц применяется также в операционной системе Windows. На-р Windows 3.11 поддерживает страничный механизм, но только для 16 Мбайт и^мяти. В микропроцессорах Pentium—Pentium 4 имеется возможность выбрать дли-п ^границы равной либо 4 Кбайта, либо 4 Мбайта. Программная поддержка страниц размерностью 4 Мбайта пока не реализована, но в будущем, с появлением более мошных микропроцессоров, несомненно, будет введена. Итоги □ В программную модель микропроцессоров 8086—80286 входят 8- и 16-битные регистры. Программная модель микропроцессоров 80386—Pentium 4 дополнена 32-битными расширенными регистрами и парой 16-битных сегментных регистров FS и GS. ---- □ В группу 8-битных регистров входят АН, AL, ВН, BL, CH, CL, DH и DL; 16-битные регистры — АХ, ВХ, СХ, DX, SP, BP, DI и SI; сегментные {^гист-ры — CS, DS, ES, SS, FS и GS. Расширенные 32-битные регистры — ЕАХ, ЕВХ, ЕСХ, EDX, ESP, EBP, EDI и ESI. К регистрам также относятся указатель инструкции IP/EIP и регистр флагов FLAGS/EFLAGS. О В реальном режиме адрес памяти образуется сочетанием адреса сегмента и смещения. Начальный адрес сегмента определяется 16-битным значением в сегментном регистре, умноженным на 16. Смещение представляет собой 16-битное число, которое прибавляется к 20-битному адресу начала сегмента. Доступ к инструкциям в сегменте кода определяется сочетанием значений регистров CS (содержит адрес сегмента кода) и 1P/EIP (содержит смещение). Адрес данных определяется сочетанием регистра сегмента данных DS и смещения, заданного либо непосредственно в команде, либо в регистре-указателе. В качестве указателей данных в микропроцессорах 8086—Pentium 4 могут быть Использованы 16-битные регистры ВХ, D1 и SL В микропроцессорах 80386— Pentium 4 в этом качестве могут применяться также 32-битные регистры ЕАХ, ЕВХ, ЕСХ, EDX, EDI и ESI. Защищенный режим микропроцессоров 80286—Pentium 4 открывает доступ к адресному пространству за пределами стандартной памяти 1 Мбайт. Адрес расширенной памяти в защищенном режиме определяется сочетанием сегмента и сМещения, как в реальном режиме. Но в защищенном режиме сегментный адрес хРанится не в сегментном регистре, а в дескрипторе, на который указывает сег-Ментный регистр. □ Дескриптор содержит информацию о базовом адресе, пределе и правах доступ^ Базовый адрес определяет начало сегмента; предел задает размер сегмента. Байто правами доступа определяет допустимые способы доступа к сегменту из граммы. Размерность базового адреса в микропроцессоре 80286 составляем 24 бита, что позволяет адресовать сегменты в пределах 16 Мбайт. В процессору от 80386 и выше адресное пространство расширено до 4 Гбайт за счет использования 32-битного базового адреса. В процессоре 80286 предел задается 16-бим-ным, а в процессорах 80386—Pentium 4 20-битным числом. В результате, размер сегмента в 80286 ограничен 64 Кбайтами, но в последующих поколениях процессоров может достигать 1 Мбайт (при G = 0) или 4 Гбайт (при G = 1). □ Сегментный регистр содержит три поля. Крайнее поле слева размерностью 13 бит определяет выбор одного из 8192 элементов таблицы дескрипторов. Установка бита выбора таблицы дескрипторов (TI) определяет выбор таблицы дескрипторов: при TI = 0 используется глобальная таблица, при TI = 1 — локальная. Два бита справа задают запрашиваемый уровень привилегий при доступе к сегменту. □ Программно-недоступные регистры в микропроцессорах 80286—Pentium 4 используются для доступа к таблицам дескрипторов. Каждый сегментный регистр содержит невидимую часть, в которую записываются из дескриптора базовый адрес, предел и права доступа. Кэширование дескриптора в невидимой части сегментного регистра позволяет обращаться к памяти без повторного чтения таблицы дескрипторов, пока содержимое сегментного регистра не изменится. □ Размер страницы памяти составляет 4 Кбайт. Линейный адрес, генерируемый программой, может быть отображен на любой физический адрес посредством страничного механизма, реализованного в микропроцессорах 80386—Pentium 4. □ Страничное преобразование контролируется регистрами управления CR0-CR3. Бит PG регистра CR0 включает страничное преобразование, а регистр CR3 адресует каталог страниц. Каталог страниц содержит до 1024 указателей на таблицы страниц. Таблица страниц, в свою очередь, содержит 1024 записей о физических адресах страниц памяти. □ Введение буфера опережающей трансляции адресов (TLB), с информацией о последних 32 отображениях страниц, повышает производительность страничного преобразования. Контрольные вопросы 1. Какие регистры процессора называются программно-доступными? 2. Какова размерность регистров, доступных в микропроцессоре 80286 наряду с 8-битныМИ регистрами? 3. В каких микропроцессорах имеются расширенные регистры? 4. Как обозначается расширенный вариант регистра ВХ? 5. Какой регистр используется, по умолчанию, в качестве счетчика при выполнении некого рых инструкций? 6. Для чего предназначен регистр IP/EIP? 7. Какие арифметические операции воздействуют на флаг переноса? 115 8. 9. 10- |2-|3. |4. о0цессоР^го аРХИТ?-К™?-_________________________________________ - pt ли переполнение при сложении знаковых байтов FFH и 01Н? ЛпОИЗОИД „ 1 И паритет У числа с тРемя единичными битами — четный или нечетный? Флаг разРсшаст контр°ль вх°ла intr? К“к мцкропроиессоры располагают сегментным регистром FS? К^^его предназначен сегментный регистр в реальном режиме работы микропроцессора? реального режима вычислите границы сегментов, сегментные адреса которых равны: а) Ю00Н б) 1234Н в) 2300Н Г) E000H д) AB00H Вычислите адрес очередной инструкции в реальном режиме для следующих значений регистровой пары CS.IP. а) CS = Ю00Н, б) CS = 2000Н, в) CS = 23ООН, г) CS = 1А00Н, д) CS = 3456Н, Чему равен максимально доступный объем памяти в реальном режиме? Какие регистры задают смешение операнда-приемника строковых инструкций? Какие 32-битные регистры микропроцессора Pentium 4 могут применяться в качестве указателей данных в сегменте данных? 1Р= 2000 Н IP = 1000Н IP = 1А00Н IP = ВОООН 1Р = ABCDH 15. 16. 17. 18. Какие регистры используются для задания сегмента и смешения при доступе к стеку? 19. Какой сегментный регистр используются для доступа к данным при задании регистра ВР в качестве указателя? 20. Вычислите адреса для реального режима процессора 80286 при следующих значениях сегмента и смещения: 21. 22. 23. 24. a) DS = 1000Н, DI = 2000Н б) DS = 2000Н, SI = 1002Н в) SS = 2300Н, BP = 3200Н г) DS = A000H, ВХ = 1000Н 4) SS = 2900Н, SP = 3A00H Вычислите для процессора Pentium 4 адрес памяти при следующем сочетании регистров: а) DS = 2000Н, EAX = ООООЗОООН б) DS = 1А00Н, ЕСХ = 00002000Н в) DS = C000H, ESI = 0000A000H г) SS = 8000Н, ESP = 00009000Н 4) DS = I239H, EDX = 0000А900Н 8028б^КИМ адресам РазРсшен доступ к памяти в защищенном режиме микропроцессора PentKaKHM ^Р603^1 разрешен доступ к памяти в защищенном режиме микропроцессора cr*iium 4 9 Ка кУ*о информацию содержит сегментный регистр в защищенном режиме? 116 GjaaJ 25. Какова емкость глобальной таблицы дескрипторов? | 26. Предположим, что в дескрипторе для процессора 80286 задан базовый адрес А00000Ц, I предел (limit) 1000Н. Вычислите границы сегмента, адресуемого этим дескриптором. Т1. Предположим, что в дескрипторе для процессора 80486 базовый адрес равен 0IOOOOOqu предел — 0FFFFH, а бит G = 0. Чему равны начальный и конечный адреса сегмента, // ресуемого этим дескриптором? ’ । 28. Предположим, что в дескрипторе для Pentium 4 базовый адрес равен 00280000Н, предел 00010Н, а бит G = 1. Вычислите границы сегмента, адресуемого этим дескриптором? 29. Если в защищенном режиме значение регистра DS = 0020Н, какой дескриптор он выб^ рает из глобальной таблицы дескрипторов? 30. Чему равен запрашиваемый уровень привилегий, если в защищенном режиме значецш регистра DS = 01 ОЗН? 31. Если в защищенном режиме значение регистра DS = 0105Н, то какой дескриптор и щ какой таблицы он выбирает? Чему равен запрашиваемый уровень привилегий? 32. Назовите максимальный размер таблицы глобальных дескрипторов для микропроцессора Pentium 4? 33. Составьте дескриптор, который задает расположение сегмента в диапазоне адресов 210000Н—21001FH. Сегмент следует определить как сегмент кода, который может быть прочитан, а дескриптор соответствует микропроцессору 80286. 34. Составьте дескриптор, определяющий сегмент памяти, расположенный по адресам 03000000H--05FFFFFFH. Этот сегмент памяти является сегментом данных, который увеличивается вверх в адресном пространстве системы памяти и может быть записан, а деск* риптор соответствует микропроцессору 80386. 35. Какой регистр определяет местоположение глобальной таблицы дескрипторов? 36. Как определяется положение локальной таблицы дескрипторов? 37. Что произойдет при загрузке нового значения в сегментный регистр, если микропроцес-сор работает в защищенном режиме? 38. Какие программно-недоступные регистры вам известны? 39. Для чего предназначен регистр GDTR? 40. Каков размер страницы памяти? 41. Какой регистр используется для включения страничного преобразования адресов в микропроцессорах 80386, 80486, Pentium, Pentium Pro и Pentium 4? 42. Сколько 32-битных адресов хранится в каталоге страниц? 43. Чему равен размер памяти, отображаемой одним элементом каталога страниц? 44. К каким элементам каталога страниц и таблицы страниц произойдет обращение при нерировании линейного адреса 00200000Н? 45. Какое значение следует поместить в таблицу страниц для трансляции линейного аДР®^ в диапазоне 20000000Н—30000000Н? 46. Что хранится в буфере TLB? 47. Найдите в сети Internet (например, на сайте корпорации Intel) дополнительную информ цию о буфере TLB. г л а£а 3_______ Методы адресации Введение 'ЭЛдективное программирование невозможно без знания методов адресации, приме-мых к той ,,ли ин°й инструкции. В этой главе мы рассмотрим методы адресации анных на примере инструкции передачи данных — mov. Эта инструкция пересылает данные между двумя регистрами или между регистром и памятью. В процессорах 8086—80286 инструкция mov позволяет копировать байты и слова; в процессорах 80386—Pentium 4 она обеспечивает также передачу двойных слов. На примере команд call и jump мы рассмотрим адресацию инструкций и продемонстрируем, каким образом можно изменить последовательность выполнения программы. Методы адресации данных, реализованные в процессорах 8086—80286, следующие: регистровая, непосредственная, прямая, регистровая косвенная, базово-индексная, регистровая со смещением и базово-индексная со смещением. Процессоры 80386— Pentium 4 поддерживают также индексную адресацию данных с масштабированием. Для адресации инструкций в процессорах 8086—Pentium 4 имеется три метода адресации инструкций: относительная, прямая и косвенная. Адресация данных в стеке обсуждается на примере команд push и ?ор. Темы главы этой главе обсуждаются следующие вопросы: О О О □ □ □ О О Функционирование каждого из методов адресации данных; применение методов адресации данных в операторах языка ассемблера; Действие методов адресации инструкций; использование методов адресации инструкций в операторах ассемблера; Выбор наиболее подходящего метода адресации; Различия между адресацией данных в реальном и в защищенном режиме; Последовательность действий при записи данных в стек и при чтении данных из стека; РазмеШение структур данных в памяти и их использование в программах. ^4. Методы адресации данных В ^СТВе основы для объяснения методов адресации данных мы примем инструк-как наиболее распространенную и к тому же допускающую всевозможные методы адресации. На рис. 3.1 показан пример инструкции mov с указанием операн дов и направления передачи данных. В начале команды записана мнемоника затем перечислены операнды. Операнд-источник задан справа, операнд-при^ц $ ник — слева1. Запись источника и приемника в таком порядке может поначалу пока?. заться неудобным — направление слева направо привычнее2. Приемник и источц35 обязательно разделяются запятой. Заметим, что только инструкция movs копировать данные из памяти в память за одну команду. позволяв MOV АХ.ВХ 1 и. я Приемник Источник Рис. 3.1. Инструкция MOV. ее операнды и направление передачи данных Команда mov ах,вх на рис. 3.1 передает 16-битное содержимое источника — регистра’ ВХ — в приемник — регистр АХ. Источник при этом не изменяется, а приемни^4 напротив, изменяется всегда3. Заметим, что команды передачи данных не воздействуют на флаги. На рис. 3.2 показаны всевозможные сочетания методов адресации данных при использовании команды mov. Заметим, что приведенные здесь методы адресации дан-1 ных действительны для всех версий микропроцессоров Intel, кроме индексной адресации с масштабированием, впервые появившейся в 80386. Методы адресации данных, рассмотренные на примеры инструкции mov, следующие. □ Регистровая адресация Передает копию байта или слова из регистра-источника или из памяти в регистр-приемник или в память. Например, инструкция mov cx,dx копирует 16-битнде содержимое регистра DX в регистр СХ. В процессорах 80386—Pentium 4 возможна передача также двойных слов. Например: инструкция mov ecx,edx копирует 32-битное содержимое регистра EDX в регистр ЕСХ. □ Непосредственная адресация Передает непосредственное значение в формате байта или слова в регистр-приемник или в память. Например, инструкция mov al,22h копирует байтовое значение 22Н в регистр AL. В процессорах 80386—Pentium 4 возможна также пе-редача непосредственных данных в формате двойного слова. Например, рукция mov евх, 12345678Н копирует 32-битную константу 12345678Н в 32-битнЫ” регистр ЕВХ. 1 В дальнейшем операнд-источник и операнд-приемник называются просто источником и прием11 ком. — Пер. 2 В ассемблере для VAX-11 (фирмы DEC) сначала указывается источник, а потом приемник ких преимуществ в этом нет — любой вариант вскоре становится привычным и кажется венно возможным. — Лер. 3 Исключения — команды TEST и СМР, которые никогда не изменяют значение приемника. 119 адресации Пример MOV АХ.ВХ р^р°вая «иная MOV СН.ЗАН НепосР^и Прямая MOV [1234Н],АХ Косвенная MOV (BXJ.CL бвЭОв0-индексная MOV [BX+SI],BP Косвенная MOV СЦВХ+4] со смещением Базово-индексная MOV ARRAY[BX+SI],DX со смещением Базово-индексная MOV [ЕВХ+2 х ESI],АХ с масштабированием Рис. 3.2. Методы адресации данных в процессорах 8086—Pentium 4 □ Прямая адресация Пересылает байт или слово между памятью и регистром. Передача данных между двумя операндами в памяти не поддерживается, за исключением инструкции movs. Например, инструкция mov cx,list копирует 16-битное содержимое операнда в памяти, обозначенного именем list, в регистр СХ. В процессорах 80386—Pentium 4 допускается передача двойного слова. Например, инструкция tov esi,list копирует 32-битное число, размещенное в четырех смежных байтах памяти по адресу, обозначенному именем list, в регистр ESI. Регистровая косвенная адресация Передает байт или слово между регистром и ячейкой памяти, адрес которой за-^ан содержимым индексного или базового регистра. Индексные и базовые реги-в процессорах 8086—80286 — это BP, ВХ, DI и SL Например, инструкция v ах, [вх] копирует в регистр АХ 16-битное число из сегмента данных; смеще-р е в сегменте данных задано базовым регистром ВХ. В процессорах 80386— entiuni 4 возможна передача 8-, 16- и 32-битных значений, а смещение может 1ть задано любым из регистров EAX, ЕВХ, ЕСХ, EDX, EBP, EDI и ESI. На-м иМер, инструкция mov al, [есх] загружает в регистр AL значение байта из сег-(J НТа Данных, смещение которого задано содержимым регистра ЕСХ. ^ово-индексная адресация ^РеДает байт иди слово между регистром и ячейкой памяти, смещение которой ч,1сдяется как сумма значений базового регистра (ВР или ВХ) и индексного 120 Гпава 3 регистра (DI или SI). Например, инструкция mov [bx+di],cl копирует из регистра CL байт в сегмент данных по смещению, заданному суммой значений ВХ и DL В процессорах 80386—Pentium 4 допустимы любые сочетания регистров ЕАХ, ЕВХ, ЕСХ, EDX, EBP, EDI и ESI. Например, инструкция mov [eax+ebx],cl передает байт из регистра CL в сегмент данных по смещению, вычисляемому сложе* нием содержимого регистров ЕАХ и ЕВХ. □ Регистровая косвенная адресация со смещением Передает байт или слово между регистром и ячейкой памяти, смещение которой равно сумме некоторого смещения, указанного в команде, и индексного или базового регистра4. Например, инструкция mov ах, [вх+4] загружает в регистр АХ значение из сегмента данных со смещением ВХ + 4; а инструкция mov ах, array[вх] записывает в АХ число из сегмента данных, смещение которого равно сумме константы array и содержимого регистра ВХ. В процессорах 80386 и выше разрешается также применять для этой цели расширенный регистр. Например, инструкция mov ах, [ЕСХ+4] загружает в регистр АХ значение из сегмента; данных, используя в качестве смещения сумму содержимого регистра ЕСХ и1 константы 4. Инструкция mov ах,array[евх] записывает в регистр АХ число, смещение которого в сегменте данных равно сумме содержимого регистра ЕВХ ц константы ARRAY. □ Базово-индексная адресация со смещением Передает байт или слово между регистром и ячейкой памяти, смещение которой, определяется суммой базового регистра, индексного регистра и константного смещения. Пример — инструкции mov ах,array[bx+di] и mov ах,[bx+di+4], кото-' рые загружают в регистр ах значение из сегмента данных. В первой инструкции смещение задано суммой константы array, значений регистров ВХ и DI, а во второй — суммой ВХ, DI и 4. Пример для процессоров 80386—Pentium 4 — инструкция mov eax, array [евх+есх], которая загружает в регистр ЕАХ двойное слово, расположенное в сегменте данных по смещению, равному сумме константы array, значений регистров ЕВХ и ЕСХ. □ Индексная адресация с масштабированием Доступна только для процессоров 80386—Pentium 4. Значение второго регистра из пары регистров, задающих смещение, умножается на масштабный коэффициент 2, 4 или 8. Например, инструкция mov edx, [еах+4*евх] загружает в регистр EDX значение из сегмента данных, смещение которого определяется результатом вычисления выражения евх * 4 + еах. Масштабирование упрощает доступ к массивам слов, двойных и 8-байтовых слов — при использовании коэффициентов 2, 4 и 8 соответственно. По умолчанию коэффициент равен 1; указывать это значение в явном виде не запрещено, но смысла не имеет. Например, в инструкции mov al, [евх+есх] масштабный коэффициент равен 1 (по умолчанию); эта инструкция может быть также представлена в виде mov al, [ebx+i*ecx] . Еще один пример использования индексной адресации с масштабированием — это инст- 4 В англоязычной литературе по вычислительной технике смещение в сегменте обозначается словом offset, а постоянная составляющая смещения при косвенной адресации — как displacement. Эти понятия по сложившейся традиции переводятся одинаково — как "смещение". — Пер. Методы адресации 121 рукция mov al, [2*евх], в которой адрес памяти задан одним регистром с масштабным коэффициентом 2. регистровая адресация регистровая адресация, обозначаемая именем регистра, применяется в программах наиболее часто. Микропроцессор содержит следующие программно доступные регистры: 8-битные регистры АН, AL, ВН, BL, CH, CL, DH и DL, 16-битные регистры АХ, ВХ, СХ, DX, SP, BP, SI и DI, и, начиная с процессора 80386, расширенные 32-битные регистры ЕАХ, ЕВХ, ЕСХ, EDX, ESP, EBP, EDI и ESI. Команды mov, push и pop допускают также использование 16-битных сегментных регистров CS, ES, DS, SS, FS и GS. Подчеркнем, что размерность регистров источника и приемника должна быть одинаковой. Нельзя, например, в качестве источника указывать 8-битный регистр, а в качестве приемника — 16- или 32-битный регистр. Примеры недопустимого сочетания размерностей — инструкции mov ах, al и mov eax,al. Заметим, что в некоторых инструкциях операнды разной размерности допустимы, как, например, в shl dx,cl. Эти исключения мы рассмотрим при обсуждении системы команд. В табл. 3.1 приведены примеры сочетаний регистровых операндов для инструкции копирования. Все возможные комбинации мы демонстрировать не будем — их очень много. Например, только 8-битные регистры в инструкции mov образуют 64 сочетания. Обратите внимание, что передача данных между сегментными регистрами не поддерживается. Также запрещена прямая (по команде mov) запись в регистр сегмента кода — регистр cs в паре с ip/eip определяет адрес следующей инструкции, и запись в него приведен к непредсказуемому результату. Таблица 3.1. Примеры инструкций с регистровой адресацией Инструкция Размерность Действие MOV AL,BL Байт Копирует BL в AL MOV CH,CL Байт Копирует CL в СН MOV AX,CX Слово Копирует СХ в АХ MOV SP,BP Слово Копирует ВР в SP MOV DS,AX Слово Копирует АХ в DS MOV SI,DI Слово Копирует DI в SI MOV BX,ES Слово Копирует ES в ВХ MOV ECX,EBX Двойное слово Копирует ЕВХ в ЕСХ MOV ESP,EDX Двойное слово Копирует EDX в ESP MOV ES,DS — Недопустимая инструкция — копирование сегментного регистра в сегментный регистр запрещено MOV BL,DX — Инструкция недопустима — операнды имеют разную размерность MOV CS,AX — Недопустимая инструкция — сегментный регистр кода не может быть приемником 122 Гпава 3 На рис. 3.3 показано выполнение инструкции mov вх,сх. Обратите внимание, что содержимое регистра-источника не изменяется, в то время как регистр-приемник получает новое значение. Инструкция копирует число 1234Н из регистра СХ в регистр ВХ. В результате прежнее содержимое (76AFH) регистра ВХ стирается, но содержимое регистра СХ остается прежним. Заметим, что приемник, будь то регистр или данные в памяти, изменяется при выполнении всех инструкций, кроме смр и test. Также отметим, что инструкция mov вх,сх не воздействует на старшие 16 бит регистра ЕВХ. Рис. 3.3. Выполнение инструкции mov вх,сх на момент перед изменением регистра вх В примере 3.1 приведена последовательность инструкций, выполняющих копирование регистров различной размерности. При выполнении последней инструкции (mov cs,ax), если она не вызовет ошибку при трансляции, контроль над программой будет потерян, поскольку при изменении cs следующая инструкция будет прочитана из другого сегмента кода. . ' ц Пример 3.1. Копирование содержимого регистров разной размерности 0000 8В СЗ MOV АХ, BX ; копирует содержимое ВХ в AX 0002 8А СЕ MOV CL, DH ; копирует содержимое DH в CL 0004 8А CD MOV CL, CH ; копирует содержимое СН в CL 0006 66I8B C3 MOV ЕАХ :,ebx ; копирует содержимое ЕВХ в ЕАХ 0009 66I8B D8 MOV ЕВХ :,EAX ; копирует ЕАХ в ЕВХ, ЕСХ и EDX 000С 66|8В С8 MOV ЕСХ :,EAX 000F 66|8В DO MOV EDX :,EAX 0012 8С С8 MOV AX, cs ; копирует CS в DS 0014 8Е D8 MOV DS, AX 0016 8Е С8 MOV CS, AX ; ошибка Непосредственная адресация Непосредственная адресация означает, что данные заданы непосредственно в коде инструкции (следуют за кодом операции). При непосредственной адресации значения данных неизменны, в отличие от переменных значений регистров при регистровой адресации. Непосредственные данные имеют размерность байта, слова и, Методы адресации 123 в процессорах 80386—Pentium 4, двойного слова. Инструкция mov с непосредственным операндом передает копию непосредственных данных в регистр или ячейку памяти. На рис. 3.4 показано действие инструкции mov eax,13456Н, которая записывает константу 13456Н из кода инструкции в регистр ЕАХ. 13456Н*- Рис. 3.4. Действие инструкции MOV ЕАХ, 3456Н Программный код MOV ЕАХ.13456Н В некоторых ассемблерах для обозначения непосредственных данных используется литера #5. Пример: mov ах,#3456н. В ассемблерах Intel ASM, Microsoft MASM и Borland TASM непосредственные данные обозначаются без литеры #, например MOV АХ,3456Н. Ассемблер допускает задание непосредственного операнда в различных системах счисления. Константы в шестнадцатеричном формате заканчиваются буквой Н, а если такая константа начинается с буквы A—F, то перед ней ставится цифра 0. Например, шестнадцатеричное число F2 на языке ассемблера записывается как 0F2H. В некоторых ассемблерах шестнадцатеричные константы начинаются с 'h; пример— mov ах,#'Ы234. Десятичные константы записывают в общепринятом стиле (пример — инструкция mov al, юо). Символ ASCII задается числовым кодом или буквой в кавычках. Пример — инструкция mov вн,'А', которая копирует ASCII-символ А (41Н) в регистр ВН. Двоичные константы записываются в виде двоичного числа с буквой В в конце (или У в некоторых ассёмблерах). В табл. 3.2 приведены примеры инструкции mov с непосредственной адресацией. Таблица 3.2. Примеры инструкции mov с непосредственной адресацией Инструкция Размерность Действие MOV BL,44 Байт Копирует десятичное число 44 (2СН) в BL MOV АХ,44Н Слово Копирует 0044Н в АХ MOV SI,0 Слово Копирует 0000Н в SI MOV CH,100 Байт Копирует десятичное число 100 (64Н) в СН MOV AL,'A' Байт Копирует ASCII-символ А в AL MOV AX,'AB' Слово Копирует пару ASCII-символов ВАвв АХ 5 Например, в ассемблерах фирмы Hewlett-Packard. 6 Это нс ошибка — пара ASCII-кодов, заданная в качестве непосредственного операнда, хранится в обратном порядке (ВА). 124 Гпава 3 [ Таблица 3.2 (окончание) Инструкция Размерность Действие MOV CL,11001110В Байт Копирует двоичное значение 11001110 в CL MOV ЕВХ,12340000Н Двойное слово Копирует 12340000Н в ЕВХ MOV ESI,12 Двойное слово Копирует десятичное число 12 в ESI MOV EAX,100Y Двойное слово Копирует двоичное число 100 в ЕАХ В примере 3.2 приведена небольшая программа с вариантами непосредственной адресации. Первые инструкции записывают 0000Н в 16-битные регистры АХ, ВХ и СХ. Последующие инструкции используют регистровую адресацию для копирования содержимого АХ в регистры SI, DI и ВР. Текст в примере 3.2 представляет собой 1 законченную программу, с указанием модели памяти. Директива .model tiny предписывает ассемблеру помещать программу в один сегмент кода. Директива .code обозначает начало сегмента кода; директива .startup указывает точку входа в i программу; оператор .exit задает завершение программы и выход в DOS. Директива end отмечает конец файла программы. Программа транслируется ассемблером MASM, либо совместимой с ним версией TASM; ход ее выполнения можно проконтролировать отладчиком CodeView (CV). Ввод и редактирование текста программы выполняются, например, с помощью редактора EDIT (в составе DOS) или Programmer’s WorkBench (PWB). Заметим, что TINY-программы транслируются в исполняемые программы формата СОМ. Пример 3.2. Программа с применением непосредственной адресации 1 .MODEL TINY ; задает односегментную модель памяти 0000 .CODE .STARTUP ; начало сегмента кода ; отмечает начало программы 0100 В8 0000 MOV AX,0 ; помещает 0000Н в АХ 0103 ВВ 0000 MOV BX,0000H ; помещает 0000Н в ВХ 0106 В9 0000 MOV CX, 0 ; помещает 0000Н в СХ 0109 8В F0 MOV SI,AX ; копирует АХ в SI 010В 8В F8 MOV DI,AX ; копирует АХ в DI 010D 8В Е8 MOV BP,AX .EXIT END ; копирует АХ в ВР ; выход в DOS ; конец файла Операторы языка ассемблера состоят из четырех частей или полей, показанных в примере 3.3. Оператор начинается с метки, которая обозначает текущий адрес программы в символическом виде. Метка начинается буквой или одним из символов @, $, или ? и содержит не более 35 символов. Метка вводится для символического обозначения адреса памяти, например, при определении данных. Следующее поле в операторе ассемблера предназначено для мнемоники инструкции; за мнемоникой находится поле операндов. Например, в операторе mov al, bl слово mov — мнемоника, a al и bl — операнды. Заметим, что число операндов зависит от инструкции и может изменяться от нуля до трех. Крайнее поле справа предназначено для записи комментария — от точки с запятой до конца'строки. Методы адресации 125 Пример 3.3. Формат операторов ассемблера Матка Мнемоника Операнды Комментарии DATA1 DB 23Н ; определить DATA1 как байт co ; значением 23H DATA2 DW 1000Н ; определить DATA2 как слово со ; значением 10ООН START: MOV AL, BL ; копирует BL в AL MOV BH,AL ; копирует AL в ВН MOV CX,200 ; копирует десятичное число 200 в СХ Листинг, формируемый при трансляции программы в файле с расширением .LST, выглядит так, как показано в примере 3.2. В крайней колонке слева приведены шестнадцатеричные значения смещений инструкций или данных, вычисленные ассемблером. Число или ряд чисел справа от смещения соответствуют машинному коду инструкции или данных. Например, смещение инструкции mov ах, о в примере 3.2 равно 0100Н, а машинный код — В8 оооо. Байт в8 соответствует коду операции, а 16-битное значение 0000 — непосредственному операнду 0. Прямая адресация данных Прямая адресация данных поддерживается в большинстве инструкций. Адрес данных в памяти при прямой адресации задается константным смешением в символическом или в числовом виде. Для инструкций с двумя операндами прямая адресация кодируется двояко. Первая форма кода применяется при передаче данных между памятью и регистром-аккумулятором (al/ax/eax); вторая форма — при прочих сочетаниях операндов. В любом случае адрес данных в памяти образуется совокупностью значений сегментного регистра и смещения, заданного в инструкции. Прямая адресация при обмене данными с аккумулятором Этот вариант предполагает, применительно к инструкции mov, передачу данных между памятью и регистром AL, АХ или ЕАХ. Инструкция mov в этом случае кодируется тремя байтами. В процессорах 80386—Pentium 4 коду инструкции может предшествовать префикс размерности регистра. Рассмотрим пример. Инструкция mov al, data загружает в регистр AL данные, расположенные в сегменте данных по смещению data. Имя data обозначает величину смещения в символическом виде. Предположим, значение data равно 1234Н. Тогда инструкция mov al, data может быть записана как mov al, [1234Н]. Операнд [1234Н] обозначает ячейку памяти по смещению 1234Н. В некоторых ассемблерах при задании смещения в числовой форме требуется уточнить сегмент — mov al,ds: [1234Н]. Действие этой инструкции (запись байта, расположенного в сегменте данных по смещению 11234Н, в регистр AL) показано на рис. 3.5. В реальном режиме исполнительный адрес образуется сочетанием смещения 1234Н и сегментного адреса 1000Н. Примеры прямой адресации при обмене данными с аккумулятором приведены в табл. 3.3. Инструкции с операндом-аккумулятором применяются довольно часто, 126 Гпава 3 поэтому для них предусмотрен 3-байтный вариант кода7. Инструкции для обмена данными между памятью и остальными регистрами кодируются четырьмя байтами. Рис. 3.5. Выполнение инструкции MOV AL, [1234Н] при DS = 1000Н Таблица 3.3. Примеры прямой адресации для обмена данными с регистром EAX/AX/AL Инструкция Размерность Действие MOV AL,NUMBER Байт Копирует в AL байт из сегмента данных по смещению NUMBER MOV AX,COW Слово Копирует в АХ слово из сегмента данных по смещению cow MOV EAX,WATER* Двойное слово Копирует в ЕАХ двойное слово из сегмента данных по смещению water MOV NEWS,AL Байт Копирует AL в сегмент данных по смещению news MOV THERE,AX Слово Копирует АХ в сегмент данных по смещению there MOV HOME,EAX* Двойное слово Копирует ЕАХ в сегмент данных по смещению номе MOV ES: [2000 H] , AL Байт Копирует AL в дополнительный сегмент данных по смещению 2000Н Общий случай прямой адресации В общем случае инструкция для обмена данными между памятью (при прямой адресации) и регистром кодируется четырьмя байтами (в процессорах 80386—Pentium 4 размер кода может достигать семи байт — при 32-битном смещении и 32-битном регистре). Вместе с тем, этот вариант кодировки наиболее гибкий, поскольку предусматривает все сочетания операндов. 7 В микропроцессорах 80386—Pentium 4 передача данных между регистром ЕАХ и памятью (при прямой адресации) может кодироваться большим числом байт. Методы адресации 127 Сравним инструкцию MOV CL,DS: [1234Н] С инструкцией MOV AL,DS:[1234Н], рассмотренной в предыдущем разделе. Обе выполняют практически одну и ту же операцию, только регистры-приемники у них разные (CL и AL). Кодируются они тоже по-разному: команда mov al,ds: [1234Н] занимает три байта, а инструкция mov cl,ds: [1234Н] — четыре, что подтверждает пример 3.4. Пример 3.4. Варианты размера кода инструкции mov при прямой адресации 0000 АО 1234 R MOV AL,DS:[1234Н] 0003 8А 0Е 1234 R MOV CL,DS:[1234H] Примеры инструкций с длиной кода более трех байт (при прямой адресации) приведены в табл. 3.4. Таблица 3.4. Примеры прямой адресации в общей форме Инструкция Размерность Действие MOV CH,DOG Байт Копирует в СН байт из сегмента данных, расположенный по смещению dog MOV CH,[1000H]8 Байт Копирует в СН байт из сегмента данных, расположенный по смещению 1000Н MOV ES,DATA6 Слово Копирует в ES слово из сегмента данных, расположенное по смещению DATA6 MOV DATA7,BP Слово Копирует ВР в сегмент данных по смещению DATA7 MOV NUMBER,SP Слово Копирует SP в сегмент данных по смещению number MOV DATA1,EAX Двойное слово Копирует ЕАХ в сегмент данных по смещению datai MOV EDI,SUMI Двойное слово Копирует в EDI двойное слово, расположенное в сегменте данных по смещению sumi Вариант программы с прямой адресацией данных показан в примере 3.5. Начало сегмента данных обозначено директивой .data. Модель памяти small позволяет определить один сегмент данных и один сегмент кода. Программа в модели small транслируется в исполняемый модуль формата EXE. Обратите внимание, что директивы задания данных db и dw записаны в сегменте данных (между операторами .data и .code). Оператор .startup теперь не только определяет точку входа в программу, но также загружает адрес сегмента данных в регистр DS. Пример 3.5. Программа с прямой адресацией данных .MODEL SMALL ; выбор SMALL-модели памяти .DATA ; начало сегмента данных 0000 10 DATA1 DB ЮН ; определить байт ЮН с адресом DATA1 8 Смещения в числовом виде используются довольно редко. 128 Гпава 3 0001 оо 0002 0000 0004 АААА DATA2 DATA3 DATA4 DB DW DW 0 0 0AAAAH ; поместить 9 в байт DATA2 ; поместить 0 в слово DATA3 ; поместить АЛДАН в DATA4 0000 .CODE ; начало сегмента кода .STARTUP ; начало программы 0017 АО 0000 R MOV AL,DATA1 ; скопировать DATA1 е AL 001А 8А 26 0001 R MOV AH,DATA2 ; скопировать DATA2 ь АН 001Е АЗ 0002 R MOV DATA3,AX ; сохранить АХ в DATA3 0021 8В 1Е 0004 R MOV BX, DATA 4 ; загрузить в ВХ значение из DATA4 .EXIT END ; выход в DOS ; конец файла Регистровая косвенная адресация Регистровая косвенная адресация позволяет обращаться к элементу данных, расположенному по произвольному смещению, заданному содержимым одного из регистров ВР, ВХ, DI и S1. Например, если регистр ВХ содержит число ЮООН, то команда mov ах, [вх] запишет в регистр АХ 16-битное значение, хранящееся в сегменте данных по смещению ЮООН. В предположении, что микропроцессор работает в реальном режиме и значение регистра DS = 01 ООН, эта инструкция обратится к паре байтов по адресам 2000Н и 2001Н, как показано на рис. 3.6. Заметим, что байт, расположенный по адресу 2000Н, копируется в регистр AL, а в регистр АН записывается байт, находящийся по адресу 2001Н. Скобки [ ] на языке ассемблера обозначают косвенную адресацию. Обратите внимание, что базовый адрес сегмента данных при значении регистра DS = 0100Н равен 01000Н. 00002002 00002001 00002000 00001002 00001001 00001000 Рис. 3.6. Действие команды mov ах, [вх] при вх = ЮООН и DS = 01 ООН Методы адресации 129 В процессорах 80386—Pentium 4 в дополнение к регистрам ВР, ВХ, DI и SI для косвенной адресации могут использоваться все расширенные регистры, кроме ESP. Примеры инструкций с косвенной адресацией приведены в табл. 3.5. Таблица 3.5. Примеры инструкций с косвенной адресацией Инструкция Размерность Действие MOV СХ,[ВХ] Слово Копирует в СХ слово, расположенное в сегменте данных по смещению, заданному в ВХ MOV [BP],DL* В 9 Байт Копирует DL в сегмент стека по смещению, заданному вВР MOV [DI],BH Байт Копирует ВН сегмент данных по смещению, заданному в DI MOV [DI],[BX] Ошибка— передача данных между ячейками памяти поддерживается только для строковых инструкций MOV AL,[EDX] Байт Копирует в AL байт из сегмента данных, смещение которого задано регистром EDX MOV ЕСХ,[EBX] Двойное слово Копирует в ЕСХ двойное слово из сегмента данных, смещение которого задано в ЕВХ Сегмент данных используется по умолчанию, если смещение задано регистром вх, di или si. Если указатель памяти задан регистром вр, то по умолчанию адресуется сегмент стека. В процессорах 80386 и выше регистр ЕВР по умолчанию адресует данные в сегменте стека, а при использовании в качестве указателей регистры ЕЛХ, ЕВХ, ЕСХ, EDX, EDI и ESI по умолчанию адресуется сегмент данных. Например, инструкция mov еах, [евх] загружает в регистр ЕАХ двойное слово из сегмента данных; смещение в сегменте данных задано содержимым ЕВХ. При адресации памяти через 32-битный регистр его значение в реально^ режиме не должно превышать 0000FFFFH. В защищенном режиме допускается любое смещение в пределах границ сегмента. В определенных ситуациях при косвенной адресации необходимо уточнять размерность данных посредством специальной ассемблерной директивы byte ptr, word ptr пли dword ptr. Пример, когда уточнение не нужно, — байтовая инструкция mov al, [Di]10. Напротив, в инструкции mov [Di],юн нет сведений о том, на что указывает DI (на байт, на слово или на двойное слово11)? Запись инструкции в виде mov byte ptr [di],юн явно указывает размерность операнда, адресуемого регистром DI, — байт. Инструкция, записанная в виде mov dword ptr [di],ioh, работает с двойными словами, что определено директивой dword ptr. Заметим, что директивы 4 При косвенной адресации через регистр ВР/ЕВР используется, но умолчанию, сегмент стека. В остальных случаях подразумевается сегмент данных. 10 Уточнять размерность [DI] не требуется, т. к. она должна соответствовать размерности второго операнда — AL. — Пер. 11 Число ЮН помещается и в байт, и в слово, и в двойное слово — отсюда неопределенность. Если бы число было больше 0FFFFH, оно помещалось бы только в двойном слове, и размерноеib команды нс оставляла бы сомнений. — Пер. 5 Зак 384 130 Гпава 3 byte ptr, word ptr и dword ptr необходимы, в основном, только при сочетании косвенной адресации с непосредственными данными. Косвенная адресация дает возможность поэлементной обработки табличных данных в памяти. Предположим, требуется сформировать таблицу с 50 значениями, прочитанными из памяти по адресу 0000:046С, где находится счетчик системного времени. На рис. 3.7 показана таблица и регистр-указатель ВХ для доступа к ее элементам. Для решения задачи требуется сначала загрузить начальный адрес таблицы в регистр ВХ — командой mov с непосредственной адресацией. Затем, используя регистр ВХ, один за другим сформировать элементы таблицы. Рис. 3.7. Массив из 50 байт, косвенно адресуемый регистром ВХ Программа, приведенная в примере 3.6, начинается с загрузки в регистр ВХ начального смещения таблицы и установки счетчика СХ = 50. В инструкции mov вх, offset table директива offset означает, что операнд представляет собой не содержимое table, а смещение table. Если бы инструкция была записана в виде mov вх, table, то в регистр ВХ было бы скопировано первое слово массива table. Напротив, команда mov вх, offset table запишет в регистр ВХ смещение массива table. Встретив в команде директиву offset, ассемблер вычисляет смещение и подставляет его в виде непосредственного операнда. Пример 3.6. Программа с косвенной адресацией через регистр 0000 0000 0032 | [ 0000 .MODEL SMALL .DATA ; выбор модели памяти SMALL ; начало сегмента данных ; задание массива из 50 байт TABLE DW 50 dup ) (?) 0000 .CODE ; начало сегмента кода .STARTUP ; начало программы Методы адресации 131 0017 В8 0000 001А 8Е СО MOV MOV AX, 0 ES,AX запись 0 в ES 001С ВВ 0000 R MOV BX,OFFSET TABLE; смещение таблицы 001F В9 0032 MOV CX, 50 счетчик := 50 0022 AGAIN: 3022 26:А1 046С MOV AX,ES:[046CH] ; прочитать показания часов 0026 89 07 MOV [BX],AX сохранить их в таблице 0028 43 ADD BX,2 увеличить указатель ВХ 0029 Е2 F7 LOOP AGAIN повторять 50 раз .EXIT ; выход в DOS END ; конец файла После инициализации счетчика и указателя программа входит в цикл до обнуления регистра СХ. В цикле выполняется чтение слова из дополнительного сегмента данных по смещению 46СН (инструкцией mov ax,es: [04бсн]) и запись прочитанного значения в главный сегмент данных по смешению, заданному содержимым регистра ВХ. Затем ВХ увеличивается на 2 (в результате, он адресует следующее двухбайтное слово таблицы), и выполняется инструкция loop. Эта инструкция вычитает I из регистра СХ, и если после этого СХ не равен нулю, то выполняет переход на метку again. Если же значение регистра СХ после уменьшения становится равным нулю, то переход не выполняется, и программа продолжается со следующего оператора (.exit). Значения, записанные этой программой в массив table, скорее всего, будут одинаковы, поскольку системное время изменяется с относительно невысокой частотой — 18,2 Гц. Для проверки работы программы воспользуйтесь отладчиком, например, CodeView. Вызов CodeView выполняется командой cv file.exe. Вызов CodeView с опцией /50 включает 50-строчный текстовый режим дисплея, а ключ /s позволяет отлаживать приложения, использующие видеорежимы с высоким разрешением. Например, для отладки программы TEST.COM в 50-строчном режиме, в командной строке DOS введите cv /50 test.com. Для отладки программы в Programmer’s WorkBench воспользуйтесь пунктом DEBUG меню RUN. Базово-индексная адресация Положение данных в памяти при базово-индексной адресации определяется содержимым регистров, что напоминает косвенную регистровую адресацию. В процессорах 8086—80286 при базово-индексной адресации используется один базовый (ВР или ВХ) и один индексный регистр (DI или S1). В базовом регистре обычно находится смещение начала массива, а в индексном — позиция элемента в массиве. Напомним, что при использовании регистра ВР для косвенной адресации памяти исполнительный адрес образуется сочетанием значений ВР и SS. В процессорах 80386—Pentium 4 допустима любая комбинация 32-битных регистров без участия ESP. Например, в инструкции mov dl, [еах+евх] регистр ЕАХ выступает в роли базового регистра, а ЕВХ — в роли индексного. При использовании ЕВР выполняется доступ к сегменту стека. Рис. 3.8 иллюстрирует адресацию данных при выполнении инструкции mov dx, [bx+di] в реальном режиме. Поскольку в этом примере ВХ = 1000Н, D1 = 00ЮН, 132 Гпава 3 a DS = 01 ООН, в регистр-приемник (DX) записывается слово, расположенное по адресу 020ЮН. Рис. 3.8. Действие базово-индексной адресации при выполнении инструкции mov dx, [bx+di ] Таблица 3.6. Примеры инструкций с базово-индексной адресацией Инструкция Размерность Действие MOV СХ, [BX+DI] Слово Копирует в СХ слово из сегмента данных по смещению, равному сумме ВХ и DI MOV CH, [BP+SI] Байт Копирует в СН байт, находящийся в сегменте стека по смещению, равному сумме ВР и SI MOV [BX+SI],SP Слово Копирует SP в сегмент данных по смещению, равному сумме ВХ и SI MOV [BP+DI],AH Байт Копирует АН в сегмент стека по смещению, равному сумме содержимого регистров ВР и DI MOV CL,[EDX+EDI] Байт Копирует в CL байт, расположенный в сегменте данных по смещению, равному сумме EDX и EDI MOV [EAX+EBX],ECX Двойное слово Копирует ЕСХ в сегмент данных по смещению, равному сумме ЕАХ и ЕВХ В табл. 3.6 приведены примеры инструкций с базово-индексной адресацией. Заметим, что в ассемблере фирмы Intel принято обозначать этот метод адресации в виде (BXHDT) (вместо (bx+di]). Инструкция mov dx, (bx+dij в этом ассемблере выглядит Методы адресации 133 как mov dxz [вх] [Di]. Команда mov di,[bx+di] при трансляции ассемблером Intel не вызовет ошибки, но будет работать неправильно. В большинстве ассемблеров, включая Microsoft MASM, допускаются обе формы. Базово-индексная адресация применяется, главным образом, для доступа к элементам массива в памяти. Предположим, требуется выполнить поэлементный доступ к массиву array в сегменте данных. Формируем в базовом регистре ВХ адрес начала массива, а в индексном регистре DI — смещение текущего элемента от начала массива. Адресация элемента массива регистрами ВХ и DI показана на рис. 3.9. ARRAY + 5 ARRAY + 4 ARRAY + 3 ARRAY + 2 ARRAY + 1 ARRAY Рис. 3.9. Пример базово-индексной адресации Программа в примере 3.7 копирует содержимое элемента массива с номером ЮН в элемент номер 20Н. Номер элемента загружается в регистр DI. Копируемый элемент массива проинициализирован числом 29Н, для -проверки результата выполнения программы. Пример 3.7. Программа с базово-индексной адресацией 0000 .MODEL SMALL .DATA ; выбор модели памяти SMALL ; начало сегмента данных 0000 0010 [ ARRAY 00 1 DB 16 DUP (?) ; начало определения массива ARRAY 0010 ООП 29 001Е J I 00 1 DB 29H DB 30 DUP (?) ; элемент ARRAY с номером ЮН 0000 J .CODE .STARTUP ; начало сегмента кода ; начало программы 0017 001А ВВ BF 0000 R 0010 MOV BX,OFFSET MOV DI,10H ARRAY; смещение ARRAY ; смещение элемента с номером ЮН 134 з 001D 8А 01 MOV AL,[BX+DI] ; прочитать этот элемент в AL 001F BF 0020 MOV DI,20H ; вычислить адрес элемента номер 2ОН 0022 88 01 MOV [BX+DI],AL ; скопировать AL в этот элемент .EXIT ; выход в DOS END ; конец файла Регистровая косвенная адресация со смещением Этот метод адресации похож на базово-индексный, т. к. смещение данных в памяти формируется суммой двух значений. При регистровой косвенной адресации адрес составляется из константного смещения и содержимого одного регистра — базового или индексного (ВР, ВХ, DI или SI). На рис. ЗЛО показано действие инструкции mov ах, [вх+юоон] при ВХ = 01 ООН и DS = 0200Н. В регистр АХ копируется слово из сегмента данных, находящееся по смещению 0100Н + 1000Н = 1100Н. При значении регистра DS = 0200Н линейный адрес равен 02000Н + 01100Н = 03100Н. Рис. 3.10. Действие инструкции MOV АХ, [ВХ+ЮООН] при ВХ = 01 ООН и DS = 0200Н Если смещение задано регистром ВХ, DI или SI, то доступ выполняется к сегменту данных, а если регистром ВР, то к сегменту стека. В процессорах 80386—Pentium смещение может быть 32-битным числом, а регистр — любым расширенным регистром, кроме ESP. Напомним, что в реальном режиме размер сегмента ограничен 64 Кбайтами. В табл. 3.7 приведены примеры использования регистровой косвенно адресации со смещением в командах. Константа, прибавляемая к содержимому регистра при формировании смещении» может быть положительной, как в инструкции mov al, [di+2], или как, например, в команде mov al, [si-1]. Константа смещения ука:-------- скобок ( ] или перед ними, как в инструкции mov al, data [Di]. КомаН MOV AL,DATA[Di+3] также допустима (здесь заданы две константы — одна внутри сК отрицательно ыняется внутр11 135 а перед скобками). В микропроцессорах 8086—80286 суммарное значение боК и 0 и ограничено диапазоном 16-битных знаковых чисел — от —32768 (8000Н) cMeLlid?767 (7FFFH); в процессорах 80386—Pentium 4 значение смещения лежит в ДО +32v ОТ -2 147483648 (80000000Н) до +2 147483647 (7FFFFFFFH). дре^аХ Таблица 3.7. Примеры регистровой косвенной адресации со смещением '^РУ*иия Размерность Действие Слово Копирует в АХ слово из сегмента данных, расположенное по смещению DI + 100Н Ц0У ARHAYISIbBL Байт Копирует BL в сегмент данных по смещению ARRAY + SI MOV LIST [SH 2], CL Байт Копирует CL в сегмент данных по смещению, равному сумме list, SI и 2 MOV DI,SFT_TT[BX) Слово Копирует в DI слово из сегмента данных, расположенное по смещению set_it + ВХ MOV DI, [EAX+10H] Слово Копирует в DI слово из сегмента данных, расположенное по смещению ЕАХ + ЮН MOV ARRAY[EBX] , EAX Двойное слово Пересылает значение ЕАХ в сегмент данных по смещению, равному сумме имени array и содержимого ЕВХ Применение регистровой косвенной адресации со смещением для доступа к элементам массива иллюстрирует рис. 3.11 на примере, рассмотренном для базовоиндексной адресации. Ссылка на элемент массива формируется как сумма константы array и индексного регистра DI. ARRAY + 6 ARRAY + 5 ARRAY + 4 ARRAY + 3 ARRAY + 2 ARRAY + 1 ARRAY Рис. 3.11. Доступ к элементам массива array с использованием регистровой косвенной адресации со смещением 136 Гпава 3 Программа в примере 3.8 демонстрирует применение этого метода адресации для передачи данных между элементами массива с номерами ЮН и 20Н. Обратите внимание на сходство программ в примерах 3.7 и 3.8. Различны лишь способы задания начального адреса массива. В программе из примера 3.7 для этого используется регистр ВХ, а в примере 3.8 — константа array. Пример 3.8. Программа, использующая косвенную адресацию со смещением .MODEL SMALL ; выбор модели памяти SMALL 0000 .DATA ; начало сегмента данных 0000 0010 [ ARRAY DB 16 DUP (?) 00 J 0010 29 DB 29H ООП 001E [ DB 30 DUP (?) 00 ] 0000 .CODE .STARTUP ; начало определения массива ARRAY ; элемент ARRAY с номером ЮН ; начало сегмента кода ; начало программы 0017 BF 0010 MOV DI ДОН ‘ смещение элемента с номером ЮН 001А ЬА 85 0000 R MOV AL,ARRAY[DI] ; ; прочитать этот элемент в AL 001Е BF 0020 MOV DI,20H ; : смещение элемента с номером 20Н 0021 88 85 0000 R MOV ARRAY (DI], AL ; ? скопировать AL в этот элемев IT .EXIT END ; выход в DOS ; конец файла Базово-индексная адресация со смещением Этот метод адресации используется для обработки двумерных массивов и представляет собой, по существу, базово-индексную адресацию с добавлением константы смещения. Базово-индексная адресация со смещением — самый сложный метод адресации в процессорах 8086—80286. Действие этого метода, применительно к инструкции mov ах, [bx+si+iooh], показано на рис. 3.12. Смещение в сегменте данных равно сумме константы 100Н и содержимого регистров ВХ и SL При значении регистров ВХ = 0020Н, SI = 0010Н и DS = ЮООН линейный адрес равен Ю130Н. Примеры команд с использованием метода базово-индексной адресации со смещением приведены в табл. 3.8. Следует отметить, что этот сложный метод адресации используется в программах относительно редко. Таблица 3.8. Примеры использования базово-индексной адресации со смещением Инструкция Размерность Действие MOV DH,[BX+DI+2ОН] Байт Копирует в DH из сегмента данных байт, смещение которого равно сумме ВХ, DI и 20Н Методы адресации 137 Таблица 3.8 (окончание) Инструкция Размерность Действие MOV АХ,FILE[BX+DI] Слово Копирует в АХ слово из сегмента данных по смещению file + ВХ + DI MOV LIST[BP+DI],CL Байт Копирует CL в стек по смещению, равному сумме list, ВР и DI MOV LIST[BP+S1+4],DH Байт Копирует DH в сегмент стека по смещению, равному сумме list, ВР, SI и 4 MOV EAX,FILE[ЕВХ+ЕСХ+2J Двойное слово Копирует в ЕАХ двойное слово из сегмента данных, по смещению file + ЕВХ + ЕСХ + 2 ЕАХ ЕВХ ЕСХ EDX ESP ЕВР ESI 01 ООН DSX10H Рис. 3.12. Пример базово-индексной адресации со смещением для команды MOV АХ, [BX+SI+100H] при DS = 1000Н Предположим, что в памяти задан массив записей, каждая из которых содержит набор элементов. Имя массива — file. Для доступа к элементам используем три смещения (как показано на рис. 3.13): □ смещение массива относительно начала сегмента данных — задано константой file; О смещение записи от начала массива — формируем в базовом регистре; О смещение элемента — формируем в индексном регистре. Программа в примере 3.9 передает содержимое элемента 0 записи А в элемент 2 записи С, используя базово-индексную адресацию со смещением. В этом примере массив file содержит четыре записи по 10 элементов в каждой. Обратите внимание 138 на оператор this КИ — FILE И RECA. byte; с его помощью мы определили по одному адресу две Память REC (Запись С) REC (Запись В) REC (Запись А) Рис. 3.13. Применение базово-индексной адресации со смещением для доступа к элементам записей rec массива FILE Пример 3.9. Программа, использующая базово-индексную адресацию со смещением^ .MODEL SMALL ; выбор модели памяти SMALL 0000 .DATA ; начало сегмента данных 0000 = 0000 FILE EQU THIS BYTE ; назвать этот байт именем FILE 0000 000А [ RECA DB 10 DUP (?) 00 1 ; зарезервировать 10 байт под RECA 000А 000А [ J RECB DB 10 DUP (?) 00 1 ; зарезервировать 10 байт под RECB 0014 000А [ J RECC DB 10 DUP (?) 00 ; зарезервировать 10 байт под RECC 001Е 000А [ ] RECD DB 10 DUP (?) 00 ; зарезервировать 10 байт под RECD 0000 .CODE .STARTUP ; начало сегмента кода ; начало программы адресации 139 ool7 qO1a QO1P 00?4 0027 BB BF 8A BB BF 88 OOOC R oooo 31 0000 R 0014 R 0002 81 0000 R MOV BX,OFFSET RECA; смещение RECA MOV DI, 0 смещение элемента с номером 0 MOV AL,FILE[BX+DI]; прочитать данные MOV BX,OFFSET RECC; смещение RECC MOV DI, 2 смещение элемента с номером 2 MOV FILE[BX+DI],AL; сохранить данные .EXIT END ; выход в DOS ; конец файла разово-индексная адресация с масштабированием разово-индексная адресация с масштабированием доступна только в процессорах 80386—Pentium 4. В этом методе адресации смещение задается парой 32-битных регистров (базового и индексного). Содержимое второго регистра (индексного) умножается на масштабный коэффициент I, 2, 4 или 8. Масштабный коэффициент со значением I используется по умолчанию, и указывать его в инструкции на языке ассемблера не обязательно, например — mov al, [евх+есх] . Масштабный коэффициент 2 применяется для адресации элементов массива слов, коэффициент 4 — для обработки массива двойных слов, а коэффициент 8 — для доступа к элементам массива 8-байтовых данных. Рассмотрим, например, инструкцию mov ах,[edi+2*ecxj. В ней масштабный коэффициент равен 2; перед сложением с EDI содержимое ЕСХ умножается на 2, полученный результат определяет смещение при доступе к памяти. Значение ЕСХ = 00000000Н адресует элемент массива слов с индексом 0, при ЕСХ = 00000001Н доступ выполняется к элементу с индексом I, и т. д. Примеры использования индексной адресации с масштабированием в инструкциях приведены в табл. 3.9. Эти примеры дают представление о том, сколь велико число сочетаний регистров в данном методе адресации. Следует отметить, что базовый регистр можно опустить, как, например, в команде mov eax, [4*edij. Таблица 3.9. Примеры использования индексной адресации с масштабированием Инструкция Размерность Действие 1407 ЕАХ, [ЕВХ+4*ЕСХ] fEAX+2*EDI+100H] ,СХ Двойное слово Слово Копирует в ЕАХ двойное слово из сегмента данных, расположенное по смещению 4 * ЕСХ + ЕВХ Копирует СХ в сегмент данных по смещению, равному сумме регистра ЕАХ, смещения 100Н и двукратного значения регистра EDI [EBP+2*EDI-2] МОу ь •array[4*ЕСХ] Байт Двойное слово Копирует из сегмента стека в AL байт, смещение которого равно сумме ЕВР, -2 и удвоенного значения EDI Копирует в ЕАХ двойное слово из сегмента данных, расположенное по смещению ARRAY + 4 * ЕСХ 140 В примере З.Ю приведен листинг программы обработки массива слов list. Смев пне list загружается в регистр ЕВХ инструкцией mov евх,offset list. Для Доступ^ элементам массива используется масштабный коэффициент 2; индекс элемеиЛ формируется в регистре ЕСХ. Программа записывает число 2 в элементы с инде сом 2, 4 и 7. Директива .386 в начале программы разрешает транслятору использо^ вать возможности микропроцессора 80386. Вместо директивы .386 может быть зада на директива .486 или .586 — для включения расширений, свойственных процессов 80486 или Pentium—Pentium 4, соответственно. При трансляции программ для DQj директива .386, .486 или .586 записывается после директивы .model. Если зад^ подобную директиву перед .model, транслятор сгенерирует инструкции для 32-битного режима, несовместимого с DOS. Пример 3.10. Программа, использующая индексную адресацию с масштабированием .......................................................................J3I .MODEL SMALL ; выбор модели памяти SMALL .386 ; использовать возможности 80386 0000 .DATA ; начало сегмента данных 0000 0000 0001 0002 LIST DW 0,1,2,3,4 ; определить массив LIST 0003 0004 000А 0005 0006 0007 DW 5,6,7,8,9 0008 0009 0000 .CODE ; начало сегмента кода .STARTUP ; начало программы 0010 66| ВВ 00000000 R MOV ЕВХ,OFFSET LIST; смещение массива LIST 0016 661 В9 00000002 MOV ЕСХ,2 прочитать элемент номер 2 001С 67& 8В 04 4В MOV АХ,[ЕВХ+2*ЕСХ] 0020 661 В9 00000004 MOV ЕСХ, 4 записать в элемент номер 4 0026 67& 89 04 4В MOV [ЕВХ+2*ЕСХ],АХ 002А 66| В9 00000007 MOV ЕСХ,7 сохранить в элементе номер 7 0030 67& 89 04 4В MOV [ЕВХ+2*ЕСХ],АХ .EXIT ; выход в DOS END ; конец файла 3.2. Структуры данных Структуры данных определяют способ хранения разнородных данных. СтрУ*1?!^ данных в языке ассемблера — это шаблон для определения данных. Определи # этого шаблона начинается директивой struc с именем структуры и заканчив оператором ends. В примере 3.11 приведен листинг определения структуры и мирования данных на ее основе. Пример 3.11. Определение структуры info и данных на ее основе ; Определение структуры данных INFO STRUC 0057 ^ппесации /4/ NAMES DB 32 DUP (?) ; 32 байта для имени ”"20 I 00 1 J f STREET DB 32 DUP (?) ; 32 байта для названия i улицы 00 0040 0010 J [ 00 CITY DB 16 DUP (?) ; 16 байт для названия города 0050 0°02 ] [ 00 STATE DB 2 DUP (?) ; 2 । байта для названия штата 0052 0005 ] [ 00 ZIP DB 5 DUP (?) ; 5 । байт для zip-кода INFO ENDS NAME1 INFO <'Bob Smith'z' 123 Main Street'Wanda'OH'44444'> 42 6F 62 20 53 6D 69 74 68 ООП ( 00 ) 31 32 33 20 4D 61 69 6E 20 53 74 72 65 65 74 0011 [ 00 ] 57 61 6E 64 61 000B [ 00 ] 48 34 34 34 34 34 NAME2 INFO <'Steve Doe'z'222 Mouse Lane'z'Miller'z'PA'z'18100'> 53 74 65 76 65 20 44 6F 65 0017 [ 00 ] 32 32 20 4D J 75 73 65 20 4C 61 6E 65 0012 ( 00 69 6C 6C 65 142 ОООА [ 00 J 50 41 31 38 31 30 30 ООАЕ NAME3 INFO <'Jim Dover'303 Main Street','Orender','CA','90000'> 42 65 6E 20 44 6F 76 65 72 0017 [ 00 ] 33 30 33 20 4D 61 69 6E 20 53 74 72 65 65 74 0011 [ 00 ] 4F 72 65 6E 64 65 72 0009 [ 00 ] 43 41 39 30 30 30 30 Струклура info, определенная в примере 3.11, предназначена для хранения сведений об адресе и состоит из пяти полей. Первое поле (32 байта) отведено для имени и фамилии; zip-код хранится в пятом поле (5 байт). Во втором поле (32 байта) хранится название улицы, в третьем (16 байт) — название города, в четвертом (2 байта) — аббревиатура штата. Данным, определяемым на основе шаблона структуры, могут быть присвоены начальные значения. Начальные значения записываются внутри скобок < >, как показано в примере 3.11. Доступ к полям структуры требует указания имени структуры вместе с названием поля, как показано в примере 3.12. Например, поле STREET В структуре NAME2 доступно как NAME2. street. В начале этого имени указано название структуры, а затем — имя поля. Еще один пример — имя NAME3.CITY. Оно обозначает адрес данных с названием города в составе структуры NAME3. Пример 3.12. Доступ к элементам структуры 0000 В9 0020 0003 ВО 00 0005 BE 0000 ; Очистка MOV MOV R MOV REP поля имени и фамилии в структуре NAME1 СХ, 32 AL, 0 SI, OFFSET STOSB NAME1.NAMES 0008 F3/AA ; Очистка названия улицы в структуре NAME2 000А В9 0020 MOV СХ, 32 000D ВО 00 MOV AL, 0 143 001° 0013 BE 0°77 R F3/aa MOV REP ; Очистка SI,OFFSET NAME2.STREET STOSB zip-кода в NAME3 od5 0018 001A OOlD B9 0005 BO 00 bE 0100 R рЗ/АА MOV CXZ5 MOV AL,0 MOV SI,OFFSET NAME3.ZIP REP STOSB Программ3’ показанная в примере Hr ______ хтлтлг! ПП1Р ЯППАГЯ n стих лпограмма, показанная в примере 3.12, очищает три элемента данных: поле имени в уктуре namei, поле адреса в структуре name2 и zip-код в структуре иамез. Действие ^роковой инструкции rep stosb выяснится в дальнейшем при изучении системы хоманд- 3.3. Методы адресации инструкций В инструкциях передачи управления jmp и call применяются три метода адресации памяти программ: прямой, относительный и косвенный. В этом разделе мы рассмотрим эти методы адресации на примере инструкции jmp. Прямая адресация Прямая адресация памяти программ применялась в большинстве первых микропроцессоров для передачи управления при выполнении переходов и вызовов подпрограмм. Этот метод адресации также используется в языках высокого уровня типа Basic при передаче управления операторами goto и gosub. В микропроцессорах Intel этот вид адресации тоже применяется, хотя и не столь часто, как относительная или косвенная. Адрес перехода при прямой адресации программной памяти хранится в коде инструкции. Например, в команде перехода по адресу 10000Н значение адреса (10000Н) хранится в конце кода команды, как показано на рис. 3.14. Инструкция jmp, приведенная на рис. 3.14, загружает в регистр CS число 1000Н, а в IP — 0000Н; таким образом, она передает управление инструкции по адресу 10000Н. Переход в произ-в°льный сегмент, или межсегментный переход, обеспечивает передачу управления в нределах всего адресного пространства. По этой причине прямой переход также на-Зь,вают дальним (far jump). В реальном режиме дальний переход ограничен стандартной памятью объемом 1 Мбайт. В защищенном режиме микропроцессоров 80386— ntiuin 4 дальний переход возможен в пределах всего адресного пространства я Гайт. Код операции Смещение (младший байт) Смещение (старший байт) Сегмент (младший байт) Сегмент (старший байт) Е А О О О О О О 1 О Рис. 3.14. Машинный код инструкции JMP [ 10000Н ] используется также в инструкции call — как при внугрисегмент- ^чМая адресация ’ так и при дальнем вызове подпрограммы. Обычно адрес перехода задают не в 144 числовой форме, а в символическом виде — меткой. В последнем случае ассембл^ сам выбирает, при трансляции, наиболее подходящий метод адресации. "д Относительная адресация В ранних микропроцессорах этот метод адресации не поддерживался, но в микъх процессорах Intel 8086—Pentium 4 он присутствует. Термин "относительная адр^Т ция" означает, что смещение следующей инструкции отсчитывается от текуще|ъ значения указателя инструкции IP. Например, если инструкция jmp передает у прям ление вперед через два байта (задает обход следующих двух байт программы)7<|£ относительный адрес перехода равен двум. Пример относительной адресации в иц» струкцип jmp приведен на рис. 3.15. Заметим, что код инструкции jmp в примере состоит всего из двух байт: в первом байте записан код операции, а во втором — смещение относительно IP. Смешение кодируется одним байтом при короткой (short) форме перехода. Двухбайтное смешение используется при ближних (пеа^ передачах управления. В последнем случае возможен переход в любую точку текущего сегмента кода (внутрисегментный переход). В процессорах 80386—Pentium 4 смещение может быть закодировано 32-битной величиной, что позволяет передавал управление в пределах текущего сегмента кода размером до 4 Гбайт. юоо 1001 1002 юоз 1004 Рис. 3.15. Машинный код инструкции JMP [2], передающей управление через два байта кода вперед Относительные инструкции jmp и call содержат 8- или 16-битное знаковое смешение, что позволяет адресовать как последующие, так и предшествующие инструкции. В процессорах 80386—Pentium 4 в дополнение к 8-битному смещению может использоваться 32-битное. При трансляции ассемблер вычисляет смешение и выбирает наиболее подходящую форму его представления — 1-, 2- или 4-байтную. Если относительное смещение не может быть представлено двухбайтной величиной, семблер отказывается от относительной адресации и использует прямую. Диапа^ short-переходов — при задании смещения 8-битной величиной — составляет от " до +127 байт. При 16-битном смещении (пеаг-переход) "дальность" перехода ±32 Кбайт. В процессорах 80386—Pentium 4 при использовании 32-битного сме^ ния (что возможно только в защищенном режиме) диапазон переходов соста ±2 Гбайт. Косвенная адресация Микропроцессоры Intel 8086—Pentium 4 поддерживают несколько форм косВ деН*1 адресации памяти программ для инструкций jmp и call. В табл. 3.10 прив примеры косвенной адресации в инструкциях перехода. Адрес перехода задан любым 16-битным регистром (АХ, ВХ, СХ, DX, SP, BP, DI или SI), а 145 Мх*****^ спи е м необязательной констан ты смещения. с < 1 4 .............. ..........—........................... На|*।•'*, ’*'-'Н' одержимым регистра ЕАХ. етсЯ с ^положенным в сегменте данных по смещению [bpj, [bxi, [di] или [si], В процессорах 80386— 4 команды jmp и call допускают задание адреса перехода в расширенном Например, jmp еах передает управление команде, адрес которой определи- Таблица 3.10. Примеры косвенной адресации памяти программ Действие Инс JMP AX Переход в текущем сегменте кода по смещению, заданному содержимым АХ JMP ex Переход в текущем сегменте кода по смещению, заданному содержимым СХ JMP near ptr [DX] Переход в текущем сегменте кода по смещению, заданному содержимым слова, расположенного в сегменте данных по смещению ВХ JMP NEAR PTR[DI+2] Переход в текущем сегменте кода по смещению, заданному в слове из сегмента данных по смещению DI + 2 JMP TABLE [ b:< J Переход в текущем сегменте кода по смещению, заданному 16-битным содержимым сегмента данных по смещению table + ВХ JMP ECX Переход в текущем сегменте кода по смещению, заданному содержимым ЕСХ Если адрес перехода инструкции jmp задан 16-бптным регистром, то переход ближний. Например, если регистр ВХ содержит 1000Н, то инструкция jmp вх передает управление команде, смещение которой в текущем сегменте кода равно 1000Н. Переход считается косвенным и тогда, когда операнд инструкции перехода задан Регистром-указателем в квадратных скобках. Так, например, команда jmp [bxj обра-™Тся за адресом перехода к слову, которое находится в сегменте данных по смешению, заданному регистром ВХ. Прочитанное из сегмента данных 16-битное число ^пользуется в качестве смешения; переход выполняется в текущем сегменте кода. В °т ваРпант перехода называют косвенно-косвенным, или дважды косвенным. дИцРИМере 3 13 приведен фрагмент программы с таблицей адресов переходов. Таб-Bhi расположена в памяти данных с адреса table. Выбор элемента таблицы при Мере вСНИ11 инстРУкции jmp table[вх] определяется значением регистра ВХ. В при-= 4, поэтому адрес перехода равен содержимому второго слова массива ет элементов массива — от 0). : 3 1 ЯЛ мУльтиветвление с использованием косвенной адресации \ ииць1 переходов Че • Таблица адресов переходов DW LOCO DW LOCI DW LOC2 DW LOC3 • "ОВД ф Таблица 3.11 (окончание) Инструкция Действие PCPAD Удаляет данные из стека, помещая их в регистры ESI, EDI, EBP, ESP ЕВХ, EDX, ЕСХ и ЕАХ pop е;ах Удаляет двойное слово из стека, помещая его в ЕАХ PUSH EDI Копирует EDI в стек Парные инструкции pusha и рора, доступные в микропроцессорах 80286—Pentium 4 предназначены для сохранения и восстановления всех регистров, за исключением сегментных. Порядок записи и считывания регистров при выполнении команд fusha/popa приведен в табл. 3.11. Начиная с процессора 80286, в инструкции push допускается непосредственный операнд. В процессорах 80386—Pentium 4 операндом инструкции push и pop может быть также расширенный регистр. В примере 3.14 приведен листинг программы, которая, сохранив в стеке содержимое регистров АХ, ВХ и СХ, восстанавливает их в обратном порядке. Первая команда pop извлекает из стека копию содержимого регистра СХ, но записывает се в АХ. Вторая команда pop помешает исходное значение регистра ВХ в СХ. Последняя команда pop записывает в ВХ исходное значение АХ. Пример 3.14. Программа для иллюстрации работы стека .MODEL TINY 0000 .CODE .STARTUP 0100 В8 1000 MOV AX,1000H 0103 ВВ 2000 MOV BX,200CH 0106 В9 3000 MOV CX,3000H 0109 50 PUSH AX 010А 53 PUSH BX 010В 51 PUSH ex 01ОС 58 POP AX 010D 59 POP ex 010Е 5В POP BX .EXIT END ; выбор модели TINY ; начало сегмента кода ; начало программы ; загрузить тестовые данные ; записать 1000Н в стек ; записать 2000Н в стек ; записать 3000Н в стек ; прочесть ЗОООН в АХ ; прочесть 2000Н в СХ ; прочесть 1000Н в ВХ ; выход в DOS ; конец текста программы Итоги О Существуют следующие методы адресации данных: регистровая, непосредственная, прямая, регистровая косвенная, базово-индексная, регистровая косвенная со смещением и базово-индексная со смещением. Дополнительный метод, принятый в микропроцессорах 80386—Pentium 4, — это индексная адресация с мас-ш габированием. 149 тОдам адресации инструкций относят: прямую, относительную и косвенную, и К ме U оды адресации данных, доступные в реальном режиме микропроцессоров 0 ^6-80286, приведены в табл. 3.12. Таблица 3.12. Примеры методов адресации данных в реальном режиме Инструкция Местонахождение операнда MOV AL, BI. MOV AX,BX MOV EAX,ECa 8-битный регистр (регистровая адресация) 16-битный регистр 32-битный регистр MOV DS/CX Сегментный регистр MOV AL,LIST (DS * ЮН) + list MOV CH,DATA1 (DS * ЮН) 4- DATA1 MOV ES,DATA2 (DS * ЮН) 4- DATA2 MOV AL,12 Непосредственные данные (число 12Н) MOV AL, [BP] (SS * ЮН) + ВР MOV AL,[BX] (DS * ЮН) + ВХ MOV AL,[DI] (DS * ЮН) + DI MOV AL,[SI] (DS * ЮН) + SI MOV AL,[BP+2] (SS * ЮН) + ВР + 2 MOV AL,[BX-4] (DS*10H) + BX-4 MOV AL, [DI + 1000H] (DS * ЮН) + DI-ь ЮООН MOV AL, [SI + 300H] (DS * ЮН) + SI + 300Н MOV AL,LIST[BP] (SS * ЮН) ч-LIST +ВР MOV AL,LIST[BX] (DS * ЮН) + LIST +ВХ MOV AL,LIST[DI] MOV AL,LIST[SI] MOV AL,LIST[BP+2] MOV AL,LIST[BX-6] MOV AL, LIST[DI+100H] Mov AL,LIST[SI+200H] MOV al, [BP+DI] MOV al, [BP+SI] Mov AL, [BX+DI] MOV AL, [BX+SI] bp+di+4 J (DS * ЮН) + LIST + DI (DS * ЮН) + list +SI (SS * ЮН) + LIST +BP + 2 (DS* 10H) 4-LIST +BX-6 (DS*1OH) + LIST + DI + 1OOH (DS * ЮН) + list 4-SI + 200H (SS * 10H) + BP + DI (SS * ЮН) + BP + SI (DS * ЮН) 4-BX 4-DI (DS * 10H) 4-BX 4-SI (SS * 10H) 4-BP 4-DI 4-4 150 Таблица 3.12 (от Инструкция Местонахождение операнда MOV ALZ [BP+SI-S] (SS * 10H) + BP + SI - 8 MOV ALZ [BX+DI+10H] (DS * 10H) + BX + DI + 10H MOV ALZ [BX+ SI-10H] (DS ’ 10H) + BX + SI - 10H MOV ALZLIST[BP+DI] (SS * 10H) + LIST + BP + DI MOV ALZLIST[BP+SI ] (SS * 10H) + LIST + BP + SI MOV AL,LIST[BX+DI] (DS * 10H) + LIST + BX + DI MOV ALZLIST[BX+SI] (DS * 10H) + LIST + BX + SI MOV ALZLIST[BP+DI+2] (SS * 10H) + LIST + BP + DI+ 2 MOV ALZLIST[BP+SI-7] (SS * 10H) + LIST + BP + SI-7 MOV ALZLIST[BX+DI+3] (DS * 10H) + LIST + BX + DI + 3 MOV ALzLIST[BX+SI-2 ] (DS * 10H) + LIST + BX + SI-2 □ В микропроцессорах 80386—Pentium 4 предусмотрены дополнительные методы адресации с использованием регистров ЕАХ, ЕВХ, ЕСХ, EDX, EBP, EDI и ESI дня задания смещения (см. табл. 3.12). Пример — команда mov al, table[евх+2*есх+юн]. □ Инструкция mov копирует содержимое операнда-источника в операнд-приемник; при этом источник не изменяется. □ Регистровая адресация применяется для доступа к 8-битному (АН, AL, ВН, BL, СН, CL, DH или DL) или 16-битному регистру (АХ, ВХ, СХ, DX, SP, ВР, SI или D1). Сегментный регистр (CS, DS, ES или SS) может быть указан в командах копирования при обмене данными с 16-битным регистром, а также в командах № и pop. Микропроцессоры 80386—Pentium 4 располагают дополнительными сегментными регистрами FS и GS, а также расширенными регистрами ЕАХ, Е»** ЕСХ, EDX, ESP, EBP, EDI и ESI. □ Непосредственная команда mov копирует в регистр или в память данные, Рас^ ложенные в коде инструкции (после кода операции). Размерность непосрсД венного операнда — байт, слово или, в процессорах 80386—Pentium 4, дв° П слово. Директива .model в программе на языке ассемблера указывается в начале и 3 ного текста и определяет модель памяти. В модели tiny программа одного сегмента кода и транслируется в исполняемую программу формата В модели small программа содержит один сегмент кода и один сегмент Д транслируется в формат EXE. Характеристики других моделей памяти см. в ложен ни 1. И Прямая адресация, предназначенная для обмена данными между памятью ги стром, кодируется в двух формах. Первая форма, 3-байтная, предназнач^ г обмена данными с регистром-аккумулятором EAX/AX/AL. Вторая форма 151 0 0 тся при обмене данными с другими регистрами и кодируется четырьмя бай-Н ш. Заметим, что некоторые инструкции с прямой адресацией в микропроцес-пах 80386—Pentium 4 имеют более длинный код — при добавлении префиксов р33мерности регистра и операнда. И и регистровой косвенной адресации смещение данных в памяти задано значе-iieM базового (ВР или ВХ) или индексного регистра (DI или SI). В процессорах «0386— Pentium 4 для адресации данных в памяти используются также расширенные регистры ЕАХ, ЕВХ, ЕСХ, EDX, EBP, EDI и ESL При базово-индексной адресации смещение данных в памяти определяется суммой значений базового и индексного регистров, указанных в команде. Этот метод адресации часто используется для доступа к элементам массивов. В процессорах 80386—Pentium 4 в качестве базового и индексного регистра может быть задан любой из 32-битных регистров, кроме EIP и ESP. □ При регистровой косвенной адресации со смешением адрес данных в сегменте данных определяется суммой константы и содержимого базового или индексного регистра. □ Базово-индексная адресация со смещением используется для доступа к двумерным массивам. Смещение данных определяется суммой константы и содержимого базового и индексного регистров. □ Индексная адресация с масштабированием доступна только в процессорах 80386—Pentium 4. Примеры: инструкции mov ах,[евх+2*есх] и mov (4*ecxj,edx. Второй регистр (индексный) умножается на заданный масштабный коэффициент 2, 4 или 8, что используется при обработке массивов с 16-, 32- или 64-битными элементами. О Структуры в языке ассемблера играют роль шаблонов для определения наборов данных. Элементы данных в наборе адресуются именем поля. Например, поле ten набора данных number обозначается number.ten. □ □ 0 tj Прямая адресация памяти программ в инструкциях jmp и call позволяет передавать управление в любую точку адресного пространства, поскольку в коде команды задана информация о смещении и сегменте. Относительная адресация памяти программ обеспечивает переход по произвольному смещению в текущем сегменте кода. В защищенном режиме процессоров 0386— Pentium 4 за счет использования 32-битного смещения дальность перехода в текущем сегменте кода достигает ±2 Гбайт. При косвенной адресации памяти программ адрес перехода для команд jmp и Call задан содержимым регистра или косвенно адресуемого слова из сегмента Данных. Нструкции push и pop предназначены для передачи 16-битных данных между еком и регистром или памятью. Инструкция push допускает также непосредст-Нные операнды. Команды pusha и рора предназначены для обмена данными ^Жду стеком и набором регисгров АХ, СХ, DX, ВХ, ВР, SP, SI и D1. В процессах 80386—Pentium 4 предусмотрены команды записи/чтения стека для расши-Ных регистров. Команда pushed предназначена для записи в стек копии ретива eflags, а команда pushf — для сохранения регистра flags. 152 Гпава 3 □ Программа в примере 3.15 демонстрирует многие из рассмотренных методов адресации. Программа заполняет массив arrayi значениями, прочитанными из ячеек в диапазоне адресов 0000:0000—0000:0009. Затем в массив array2 записываются значения, возрастающие от 0 до 9 с шагом 1. В завершение программа обменивает местами значения второго элемента arrayi и третьего элемента ARRAY2. Пример 3.15. Примеры использования различных методов адресации данных .MODEL SMALL ; выбор модели SMALL 0000 .DATA ; начало сегмента данных 0000 000А [ ARRAYI DB 10 DUP (?) ; массив ARRAYI из 10 байт 00 J 000A 000A [ ARRAY2 DB 10 DUP (?) ; массив ARRAY2 из 10 байт 00 0000 .CODE ; начало сегмента кода .STARTUP ; точка входа в программу 0017 B8 0000 MOV AX,0 ; ES = 0000Н 001A 8E CO MOV ES,AX 001C BE 0000 MOV DI,0 ; смещение элемента номер 0 COIF B9 000A MOV CX,10 ; счетчик = 10 0022 LABI: 0022 26: :8A 05 MOV AL,ES:[DI] ; копировать данные 0025 88 85 0000 R MOV ARRAYI[DI],AL ; в ARRAYI 0029 47 INC DI 002A E2 F6 LOOP LABI 002C BF 0000 MOV DI,0 ; смещение элемента номер 0 002F B9 000A MOV CX,10 ; счетчик = 10 0032 B0 00 MOV AL, 0 установить начальное значение 0034 LAB2: 0034 88 85 000A R MOV ARRAY2[DI),AL ; заполнить массив ARRAY2 0038 FE CO INC AL 003A 47 INC DI 003В E2 F7 LOOP LAB 2 003D BF 0003 MOV DI,3 ; обмен значений массивов 0040 8A 85 0000 R MOV AL,ARRAYI[DI] 0044 8A A5 000B R MOV AH,ARRAY2[DI + 1] 0948 88 A5 0000 R MOV ARRAYI[DI], AH 004C 88 85 000B R MOV ARRAY2[DI+1],AL .EXIT END выход в DOS конец текста программы Методы адресации У53 Контрольные вопросы I. Какие действия выполняют следующие инструкции: a) mov ах,вх б) MOV ВХ, АХ в) MOV BL,CH Г) MOV ESP, EBP Д) MOV AX,CS 2. Перечислите 8-битные регистры, используемые при регистровой адресации. 3. Перечислите 16-битные регистры, пригодные для регистровой адресации. 4. Перечислите 32-битные регистры, используемые при регистровой адресации в процессорах 80386—Pentium 4. 5. Перечислите 16-битные сегментные регистры, применяемые в командах mov, push и pop при регистровой адресации. 6. Почему инструкция MOV BL,CX ошибочна? 7. Почему инструкция MOV DS,SS недопустима? 8. Запишите инструкции для выполнения следующих действий: а) скопировать ЕВХ в EDX б) скопировать BL в CL в) скопировать SI в ВХ г) скопировать DS в АХ д) скопировать AL в АН 9. Запишите инструкции для выполнения следующих действий: а) записать 12Н в AL б) записать 123АН в АХ в) записать 0CDH в CL г) записать 1000Н в SI д) записать 1200А2Н в ЕВХ 10. Каким символом обозначаются непосредственные данные в некоторых ассемблерах? 11. Для чего предназначена директива .MODEL tiny? 12. Какой директивой обозначается в языке ассемблера начало сегмента кода? 13. Что такое метка? 14. В каком поле оператора ассемблера записывается обозначение MOV? 15. Какие символы допустимы в начале имени метки? 16. Для чего предназначена директива .exit? 17. В каком формате создается исполняемая программа при задании директивы .MODEL tiny? 18. Какие действия задаст директива .startup, если применяется модель памяти small? 19. Что означает термин "смещение"? Как определяется адрес данных в команде MOV [200СН], AL? 20. Что означают квадратные скобки в программе на языке ассемблера? 21. Предположим, что DS = 0200Н, ВХ = 0300Н, a DI = 400Н. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV AL, [1234Н] б) MOV ЕАХ,[ВХ] В) MOV [DI],AL 154 Гпава 3 22. Почему инструкция mov [ВХ], [di] ошибочна? 23. Приведите пример инструкции, требующей применения директивы BYTE ptr. 24. Приведите пример инструкции, требующей директивы word ptr. 25. Приведите пример инструкции, требующей директивы DWORD PTR. 26. В чем разница между командами MOV BX,DATA и MOV вх, OFFSET DATA? 27. Предположим, что DS = ЮООН, SS = 2000H, BP = Ю00Н, a DI = 0I00H. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV AL,[BP+DI] б) MOV СХ, [DI] В) MOV EDX, [BP] 28. Ошибочна ли инструкция mov al, [BX] [si]? 29. Предположим, что DS = 1200H, BX = 0100H, a SI = O25OH. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV [100H],DL б) MOV [SI + 100H],ЕАХ В) MOV DL, [ВХ+100Н] 30. Предположим, что DS = 1100Н, BX = 0200H, list - O25OH, a SI = 0500H. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV LIST[SI],EDX 6) MOV CL,LIST[BX+SI] B) MOV CH, [BX+SI] 31. Предположим, что DS = 1300H, SS = 1400H, BP = I500H, a SI = 0I00H. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV ЕАХ, [ВР+200Н] б) MOV AL, [BP+SI-200H] В) MOV AL, [SI-0100H] 32. Какой базовый регистр адресует данные в сегменте стека? 33. Предположим, что ЕАХ = 0000ЮООН, ЕВХ = 00002000Н, a DS = 00ЮН. По каким адресам обращаются к памяти следующие инструкции в реальном режиме? a) MOV ЕСХ, [ЕАХ+ЕВХ] б) MOV [ЕАХ+2*ЕВХ],CL В) MOV DH, [ЕВХ+4*ЕАХ+1000Н] 34. Запрограммируйте структуру данных FIELDS с полями Fl, F2, F3, F4 И F5. 35. Как обозначить в программе адрес поля F3 структуры FIELDS? 36. Какие методы адресации инструкций реализованы в процессорах 8086—Pentium 4? 37. Сколько байт занимает машинный код дальней инструкции перехода? Какая информация хранится в каждом из них? 38. Чем различаются внутрисегментный и межсегментный переходы? 39. Какова дальность перехода при задании смешения 16-битным знаковым числом? 40. Какова разрядность смешения, позволяющего перейти в любую точку текущего сегмента кода размером до 4 Гбайт (в процессорах 80386—Pentium 4)? 41. Что означает дальний переход? 42. Какая разновидность инструкции jmp не позволяет передать управление по адресу 200Н в текущем сегменте кода, если сама инструкция находится по адресу 100Н? Методы адресации 155 43. Какой вариант инструкции перехода (short, near или far) выберет ассемблер, если инструкция jmp THERE находится по адресу Ю000Н, а адрес THERE равен: а) Ю020Н б) П000Н в) 0FFFEH г) 30000Н 44. Запишите инструкцию перехода для передачи управления по адресу, заданному содержимым регистра ВХ. 45. Запишите инструкцию ближнего (near) перехода для передачи управления по адресу из таблицы адресов. 46. Сколько байт записывает в стек инструкция push? 47. Объясните действие инструкции push [DI). 48. Какие регистры помешает в стек инструкция pusha и в каком порядке? 49. Какие действия выполняет инструкция PUSHAD? 50. Какая инструкция микропроцессора Pentium 4 записывает в стек значение регистра ЕFLAGS? ГЛАВА 4 Инструкции передачи данных Введение В этой главе мы рассмотрим инструкции передачи данных. В эту группу инструкций входят команды MOV, movsx, movzx, push, pop, bswap, xchg, xlat, in, out, lea, lds, les, I.FS, LGS, LSS, LAHF И SAHF, 3 ТЗКЖе СТроКОВЫС ИНСТРУКЦИИ MOVS, LODS, STOS, INS 11 OUTS. В Pentium Pro—Pentium 4 также имеется инструкция условной передачи cmov. Мы начинаем изучение системы команд с инструкций передачи данных, поскольку они самые простые и чаще других используются при написании программ. Программирование машинных команд выполняется, как правило, нс вручную, а на языке ассемблера — машинный язык слишком сложен. В этой главе мы начнем изучение синтаксиса ассемблера и ознакомимся с некоторыми директивами этого языка. Поскольку в книге рассматривается ассемблер MASM фирмы Microsoft, мы рекомендуем вам пользоваться при выполнении примеров именно этой реализацией ассемблера1. Конечно, вы можете воспользоваться и другими, похожими реализациями — например, ассемблерами ASM фирмы Intel или TASM фирмы Borland. Кстати, последняя версия TASM полностью совместима с MASM. Подробные сведения об ассемблере MASM, о компоновщике и среде Programmer's WorkBench приведены в Приложении /. Темы главы В этой главе мы рассмотрим: □ действие инструкций передачи данных; □ назначение директив языка ассемблера align, assume, db, dd, dw, end, ends, endp, EQU, .MODEL, OFFSET, ORG, PROC, PTR, SEGMENT, USE16, USE32 И USES; П выбор инструкции передачи данных в различных ситуациях; □ поля машинного кода; □ оформление сегментов данных, стека и кода на языке ассемблера; □ оформление процедур с использованием директив proc и endp; □ разницу между моделью памяти и полными определениями сегментов в ассемблере MASM. 1 В этой книге используется MASM 6..v с директивами структурного ассемблера. Инструкции передачи данных 157 4.1. Инструкция MOV Инструкция mov вам знакома — на ее примере в главе 3 рассмотрены методы адресации данных в процессорах 8086—Pentium 4. В этой главе мы обсудим построение машинного кода инструкций при разных методах адресации на примере команд mov. Знакомство с машинным кодом пригодится на тот случай, если вам придется исследовать результат работы транслятора. Вы сможете исправить исполняемый код при отладке с использованием DOS-утилиты DEBUG. Машинный код и правила его построения см. в Приложении 2. Машинный язык В машинном языке инструкции хранятся в двоичном коде, понятном процессору. Длина машинных инструкций для процессоров 8086—Pentium 4 варьируется в пределах I —!3 байт. Хотя машинный язык кажется весьма сложным и обширным2, в нем есть некая система. Формат машинных инструкций для !6-битных процессоров 8086—80286 показан на рис. 4.1, а3. Этот формат совместим с процессорами 80386—Pentium 4 в 16-битном режиме, хотя для этих процессоров 16-битный код может быть расширен префиксами, изображенными на рис. 4.1, о пунктиром. В процессорах 80386 и выше 16-битный формат используется в реальном режиме. В защищенном режиме выбор между 16- и 32-битным режимом определяется значением бита D в старшем байте дескриптора. В 32-битном режиме функционируют такие операционные системы, как Windows ХР, Windows 95, Windows 98 и OS/2. 32-битный формат показан на рис. 4.1, б. Инструкции 32-битного формата могут применяться и в 16-битном режиме за счет специальных префиксов, которые мы рассмотрим далее в этой главе. Формат 16-битных инструкций Код операции (1 или 2 байта) MOD-REG-R/M 0-1 байт Смещение 0-1 байт Непосредственное значение . 0-2 байт а) Формат 32-битных инструкций Размерность адреса 0-1 байт Размерность операнда 0-1 байт Код операции MOD-REG-R/M (1 или 2 байта) 0-1 байт Масштаб-индекс-база 0-1 байт Смещение 0-4 байт Непосредственное значение 0-4 байт б) Рис. 4.1. Форматы машинных инструкций 8086—Pentium 4: а) 16-битный; б) 32-битный Первые два байта в 32-битном формате — это префиксы модификации размерности; их наличие в команде не обязательно. Первый префикс модифицирует размерность адреса операнда, второй — размерность регистра. Если процессор 80386—Pentium II работает в 16-битном режиме (что возможно в реальном и в защищенном режиме), и в команде используется 32-битный регистр, то в начале команды ставится префикс 2 Количество вариантов кода превышает 100 000. 3 В дальнейшем этот формат называется 16-битным. Число 16 в данном случае нс относился к длине машинного кода, а связано только с разрядностью операций. — Пер. 158 Гпава 4 модификации размерности регистра — байт со значением 66Н. Если режим инструкций 32-битный (что возможно только в защищенном режиме работы процессора), и используется 32-битный регистр, то префикс модификации размерности регистра не ставится. В 32-битном режиме инструкций префикс должен быть указан, если нужен доступ к 16-битному регистру. Префикс модификации размерности адреса операнда (байт со значением 67Н) используется аналогичным образом Префиксы модификации размерности переключают разрядность адреса или регистра для одной инструкции между 16 и 32 битами. По умолчанию в 16-битном режиме используются 8- и 16-битные регистры и смещения, а в 32-битном режиме — 8- и 32-битные регистры и смещения. Рассмотренные префиксы временно изменяют разрядность по умолчанию, что позволяет обращаться к 32-битному регистру в 16-битном режиме, а к 16-битному регистру — в 32-битном режиме. Выбор между 16- и 32-битными режимами определяется разрядностью данных, с которыми работает программа. Обычно выбор разрядности возлагается на операционную систему. (Операционная система DOS функционирует только в 16-битном режиме.) Код операции Код операции (opcode) определяет выполняемой тип операции (сложение, вычитание, копирование и т. д.). Код операции занимает один или два байта в начале машинной инструкции. Формат первого байта кода операции для большинства инструкций показан на рис. 4.2. Первые шесть бит — двоичный код операции. Бит D задает направление (не путайте с флагом D, который определяет увеличение или уменьшение указателей при выполнении строковых команд), бит W — размерность операции (байт или слово). Установка бита W = 1 в процессорах 80386—Pentium 4 может означать или слово, или двойное слово; выбор между ними зависит от текущего режима инструкций (16- или 32-битный) и наличия префикса модификации размерности операнда (66Н). MOD REG Код операции Рис. 4.2. Первый байт кода операции Рис. 4.3. Второй байт кода операции Местоположение источника и приемника данных закодировано в полях REG и R/M — во втором байте машинного кода. Если бит направления D установлен в 1, то местоположение источника определяется полем R/М. а местоположение приемника — полем REG. Если бит D = 0, то направление передачи противоположное: в этом случае поле REG задает источник, а поле R/M — приемник. При W = 0 размерность данных — байт, а при W = I — слово или двойное слово. Бит W присутствует в большинстве инструкции, а бит D — в основном, в командах mov. Формат второго байта кода операции для большинства инструкций показан на рис. 4.3. Этот байт — reg-mod-r/m — содержит поля MOD (режим), REG (регистр) и R/М (ре* гистр/память). Инструкции передачи данных 159 Поле MOD Поле MOD определяет метод адресации и, в частности, наличие константного смещения при адресации памяти. Коды поля MOD для 16-битного режима приведены в табл. 4.1. Код 11 означает регистровую адресацию; код регистра записан в поле R/М. При MOD =00, 01 и 10 поле R/М задает метод адресации памяти. Значение MOD = 00 говорит о том, что при адресации памяти постоянное смещение не используется. При MOD = 01 и 10 смещение имеется и задано знаковым байтом (MOD = 01) или словом (MOD = 10). Например, адрес данных в памяти для команды mov al, [di] задан без смещения, в инструкции mov al, [di+2] используется S-битное смещение (+2), в команде mov al, [di+ioooh] — 16-битное (+1000Н). Таблица 4.1. Коды поля MOD в 16-битном режиме Код поля MOD Значение 00 Смещение отсутствует 01 Смещение задано знаковым байтом 10 Смещение 16-битное 11 Поле R/М содержит код регистра Смещение, заданное в команде 8-битным значением, при выполнении инструкции расширяется до 16-битной величины, с учетом знака. Положительное 8-битное смещен е (ООН—7FH) преобразуется в 16-битное положительное значение в пределах 0000Н—007FH. Отрицательное 8-битное смещение (80Н—FFH) преобразуется в 16-битное отрицательное число в диапазоне FF80H—FFFFH. При знаковом расширении старший бит исходного байта копируется в старший байт результата, т. е. старший байт получает значение ООН или FFH. Значения поля MOD в 32-битном режиме микропроцессоров 80386—Pentium 4 приведены в табл. 4.2. Смысл значений поля MOD для 16- и 32-битного режимов различен только для одного значения — MOD = 10. Код 10 для 16-битного режима определяет 16-битное смещение, а для 32-битного режима — 32-битное. Напомним, что процессоры 80386—Pentium 4 используют в 32-битном режиме 8- или 32-битное смещение, если не задан префикс модификации адреса операнда. Если смещение задано 8-битным значением, то при формировании адреса оно расширяется до 32 бит, с учетом знака. Таблица 4.2. Коды поля MOD в 32-битном режиме (только для процессоров 80386—Pentium 4) Код поля MOD Значение 00 Смещение отсутствует • 01 Смещение задано знаковым байтом 10 Смещение 32-битное 11 Поле R/М содержит код регистра 160 Гпава 4 Коды регистров В табл. 4.3 приведены значения кодов полей REG и R/М при MOD = Н, в зависимости от размерности операнда. Таблица 4.3. Коды REG и R/М (при MOD = 11) Код w= 0 (байт) w= 1 (слово) w= 1 (двойное слово) 000 AL АХ ЕАХ 001 CL СХ ЕСХ 010 DL DX EDX 011 BL ВХ ЕВХ 100 АН SP ESP 101 СН ВР ЕВР 110 DH SI ESI 111 ВН DI EDI Разберем, например, машинный код 8ВЕСН. Первый байт не равен ни 67Н (пре-, фикс модификации размерности адреса), ни 66Н (префикс модификации размерив сти регистра) — значит, в первом байте находится код операции. Значения полА 16-битной инструкции с кодом 8ВЕСН показаны на рис. 4.4. Код операции равен 100010. Из Приложения 2 выясняем, что это код инструкции mov. Поскольку биты О и W установлены в 1, то задана операция над словами, приемником является регистр, а код регистра задан полем REG. Значение REG =101 соответствует регистру ВР. Поскольку MOD = 11, в поле R/М задан код второго регистра — источника. Код R/M = 100 обозначает регистр SP. Таким образом, машинный код 8ВЕСН соответствует инструкции MOV BP,SP. Код операции D W MOD REG R/M 1 ! 0 [ ° ° j 1 0 1 1 1 1 1 0 I 1 1 । 0 0 Код операции = MOV D = Передача в регистр REG W = Слово MOD = R/M задает регистр REG = ВР R/M = SP Рис. 4.4. Машинный код 8ВЕСН (инструкция MOV ВР, SP) Рассмотрим код 668ВЕ8Н применительно к процессорам 80386 и выше. Пред подо* жим, что процессор работает в 16-битном режиме. Первый байт машинного КОД* имеет значение 66Н — это префикс модификации размерности регистра. Таким оо* разом, в этой команде используются 32-битные операнды. Далее выясняется, код операции соответствует команде mov, источником является регистр ЕАХ, а пр11 Инструкции передачи данных 161 смником — ЕВР. То есть, код 668ВЕ8Н в 16-битном режиме задает инструкцию v евр,еах. В 32-битном режиме тот же код, с учетом префикса 66Н, соответствует команде mov вр,ах. Подстановка префиксов, модифицирующих размерность адреса и регистра, выполняется ассемблером автоматически — под управлением директив, определяющих текущий режим инструкций (16- пли 32-битный). Напомним, что директива .386, поставленная перед оператором .model, определяет 32-битный режим; если же она указана после оператора .model, то режим — 16-битный. Коды поля R/M при адресации памяти Кодировка поля R/M при MOD = 00, 01 и 10 приведена в табл. 4.4. Коды MOD = 00, 01 и 10 задают адресацию памяти. Каким образом, это выяснится в следующем разделе, код R/M = ПО неоднозначен. Таблица 4.4. Коды R/M при адресации памяти в 16-битном режиме Код поля R/M Метод адресации Код поля R/M Метод адресации 000 DS:[BX+SI] 100 DS:[SI] 001 DS:[BX+DI] 101 DS:[DI] 010 SS:[BP+SI] 110 SS:[ВР] 011 SS:[BP+DI] 111 DS:[ВХ] В гибл. 4.4 приведены все варианты 16-битной косвенной адресации, рассмотренные в г.шве 3. Наличие и разрядность константного смещения определяется полем MOD. Если MOD = 00 и R/M = 101, то операнд — [di]. Если MOD = 01 или 10, то операнд адресуется суммой DI и константы смещения, например, [dh-ззн] или LIST [DI+22H] И Т. П. Код операции D W MOD* REG R/M i I I 1 0 I 0 I 0 I I 1 I 0 1 0 0 0 i i 0 I 1 i о ! I 1 0 I 1 i Код операции = MOV D = Передача в регистр REG W = Байт MOD = Нет смещения REG = DL R/M = DS:[DI] Рис. 4.5. Инструкция MOV DL, [Di] в машинном представлении На рис. 4.5 показаны значения полей 16-битной инструкции mov dl, [di]. Машинный код составляет два байта, значение — 8А15Н. Код операции равен 100010, бит D = I (приемник задан полем REG, а источник — полем R/M), бит W - 0 (операция байтовая), поле MOD = 00 (смещение отсутствует), REG = 010 (регистр — DL) и R/M =101 (адресация — [di]). Если изменить инструкцию на mov dl, [dt+ij, то в Первой паре байт машинного кода изменится только поле MOD — оно примет зна-Пение 01 (смещение — 8-битное). Код станет трехбайтным (8А5501Н); последний Зак 384 162 Гпава 4 байт содержит 8-битное смещение. Команда mov dl, [di+ioooh] кодируется уже четырьмя байтами (8A7500I0H); последние два содержат 16-битное смещение ЮООН. Кодирование прямой адресации Прямая адресация памяти (адрес задан константой смещения) кодируется особым образом. Этот метод адресации в табл. 4.2—4.4 не указан. Примеры инструкций с прямой адресацией: mov [Ioooh],dl и mov humb,dl. Первая инструкция передает содержимое регистра DL в сегмент данных по смещению ЮООН, а вторая копирует регистр DL в сегмент данных по смещению numb. MOD REG R/M Байт 2 Код операции О W о о о о 0 0 Байт 1 Смещение (младший байт) , i I ! 0l0*0 0|0|0l0 0 ' i I I I i I Байт 3 Смещение (старший байт) —'------|--------Г~~!-----------j— О I О I О 1 ! О ' О ! О ’ О I । I I i, Байт 4 Код операции = MOV D = Передача из регистра REG W = Байт MOD = Прямая адресация REG = DL R/M = DS:[BP] Смещение = ЮООН Рис. 4.6. Инструкция MOV [ЮООН], DLс прямой адресацией Код операции Байт 1 8-битное смещение MOD REG R/M т 0 ’!0 1 1 ! о । Байт 2 Байт 3 Код операции = MOV D = Передача из регистра REG W = Байт MOD = Адресация [ВР+смещение] REG = DL R/M = DS:[BP] Смещение = ООН Рис. 4.7. Машинный код инструкции MOV [BP], DL Инструкции передачи данных 163 Прямая адресация определяется сочетанием MOD = 00 и R/M = ПО. Эта комбинация полей MOD и R/М, согласно табл. 4.2 и 4.4, была предназначена для кодирования косвенной адресации через регистр ВР без смещения — [вр] . Но сочетанию MOD = 00 и R/M = ПО придан совершенно другой смысл — оно обозначает прямую адресацию; при этом косвенная адресация без смещения через регистр ВР исключена вообще. При трансляции ассемблер заменяет [вр] на [вр+0] с 8-битным смещением (MOD = 01). На рис. 4.6 показаны поля машинного кода команды mov [1000H],dl, а на рис. 4.7 — инструкция mov [bp],dl. Обратите внимание, что инструкция mov [bp],dl кодируется тремя байтами; последний байт содержит смещение ООН. 32-битная адресация Процессоры 80386 и выше применяют 32-битную адресацию либо в режиме 32-битных инструкций, либо при выполнении 16-битной инструкции с префиксом модификации размерности адреса (67Н). Коды поля R/М для 32-битной адресации приведены в табл. 4.5. Заметим, что R/M =101 обозначает также прямую адресацию. Обратите внимание, что при R/M = 100 в коде инструкции появляется дополнительный байт масштаб-индекс-база4. Этот байт используется, когда в формировании смещения участвуют два регистра. Максимальное число комбинаций кодов при добавлении байта масштаб-индекс-база к байту кода операции составляет 215, или 32 К. Команда mov в 80386—Pentium 4 кодируется более чем 32000 сочетаниями кодов. Таблица 4.5. Коды поля R/М при 32-6итной адресации Код поля R/M Метод адресации 000 DS:(ЕАХ) 001 DS:[ЕСХ[ 010 DS:[EDX] •* 011 DS:[EBX] • 100 Базово-индексная адресация с масштабированием 101 SS:[ЕВР] 110 DS:[ESI] 111 DS:[EDI] Формат байта масштаб-индекс-база показан на рис. 4.8. Следует напомнить, что этот байт добавляется к байту кода операции, если адресация 32-битная и R/M = 100. Два бита слева определяют масштабный коэффициент — 1, 2, 4 или 8. При базово-индексной адресации через 32-битные регистры по умолчанию используется масштабный коэффициент 1. В поле Index указывается код 32-битного индексного регистра; в поле Base — код 32-битного базового регистра. Коды регистров приведены в крайнем правом столбце табл. 4.3. 4 Обозначается аббревиатурой SIB (Scale-Indcx-Base). — Пер. 164 Глава^ База Масштаб Индекс Г 00 = х 1 м с 01=х2 Масштаб-! 10 = х4 . 11 =х8 Рис. 4.8. Формат байта масштаб-индекс-база Ф Ф Инструкция mov eax, [евх+4*есх] кодируется как 67668В048ВН. В этом коде задан] префиксы модификации размерности адреса (67Н) и регистра (66Н) — предполагя ется, что микропроцессор работает в 16-битном режиме. В 32-битном режиме инея рукция mov еах, [евх+4*есх] кодируется без префиксов, как 8В048ВН. Напомню, Ч1 адресация с масштабированием может применяться и для одного регистра, как, q пример, в команде mov al, [2*есх], которая задает копирование в регистр AL байА расположенного в сегменте данных по смещению удвоенного значения региста ЕСХ. ] Непосредственный операнд > Пример непосредственного операнда — команда mov word ptr [вх+юоон] , 1234Н. Э* инструкция копирует непосредственное значение 1234Н в сегмент данных по см! тению ЮООН 4- ВХ. В 16-битном режиме эта команда кодируется шестью байтай! как показано па рис. 4.9. Первые два байта содержат код операции, бит W и пен Смещение (младший байт) MOD R/M х | ! 1 I 0 0 : 0 ] 0 1 i __________!_______________ Байт 2 о о Смещение (старший байт) 1 ! 0 | 0 j 0 1 ! ; i I i I 0 I 0 | 0 I 0 i ! i Байт 4 О I о ! о о ! Байт 3 Код операции = MOV (непосредственная адресация) ! 1 W = Слово j MOD = 16-битное смещение REG = ООО R/M = DS:[BX] Смещение = ЮООН Данные = 1234Н Рис. 4.9. Код инструкции MOV WORD PTR [ВХ+ЮООН] , 1234Н Инструкции передачи данных 165 >101) и R/M. В следующих двух байтах задана константа смещения (IOOOH), а в победней паре байт — непосредственный операнд 1234Н. 11ри записи этой команды на языке ассемблера применена директива word ptr. Она уведомляет транслятор о том, что в инструкции задан указатель на слово. Чтобы записать непосредственное значение в байт памяти, следует вместо word ptr задать директиву byte ptr. При использовании 32-битного непосредственного операнда указывается директива dword ptr. Заметим, что директивы byte ptr, word ptr и , ?rd ptr нужны не во всех случаях, когда требуется обращение к данным в памяти. Они необходимы лишь тогда, когда размерность операнда неопределима. Например, команда mov (bx],al является байтовой, что следует из размерности AL. Напротив, размерность данных инструкции mov (вх],1 неизвестна — здесь операнды могут быть байтами, словами или двойными словами. Такая команда считается ошибочной, ассемблер ее не пропустит. В данной ситуации следует уточнить размерность операндов, записав команду в виде mov byte ptr [вх], 1, или mov word ptr [bx],i, n/lll MOV DWORD PTR [BX],1. Коды сегментных регистров Коды сегментных регистров в поле REG, используемые при копировании сегментною регистра в командах mov, push и pop, приведены в табл. 4.6. Замечание по поводу регистра CS: команды mov cs,r/m(16) и pop cs не поддерживаются микропроцессором. Таблица 4.6. Кодировка сегментных регистров Код Сегментный регистр Код Сегментный регистр ООО ES 011 DS 001 CS 100 FS 010 SS 101 GS Код операции 1 0 0 0 1 1 0 0 Код операции = MOV MOD = R/M обозначает регистр REG = CS R/M = [ВХ] MOD REG R/M Рис. 4.10. Машинный код инструкции MOV ВХ, CS Na рис. 4.IO показан машинный код инструкции mov bx,cs. Код операции для этого T,iiia инструкции mov отличается от кодов в предыдущих примерах. Допускается об-Х|сц данными между сегментным регистром и любым 16-битным регистром или памятью. Например, команда mov [di],ds записывает содержимое регистра DS в сегмент данных по смещению, заданному регистром D1. Непосредственный операнд йрн обмене данными с сегментным регистром не допускается. Для загрузки в сег 166 Глава ментный регистр непосредственного значения следует скопировать число в 16-бит, ный регистр общего назначения, а из него — в сегментный регистр. Хотя мы рассмотрели правила построения машинных кодов не полностью, вы поду,; чили общее представление о машинном языке, которого вполне достаточно для про^ граммирования на ассемблере. Напомним, что при использовании символическое языка ассемблера необходимость в составлении кодов машинного языка возникает крайне редко, поскольку транслятор с языка ассемблера выполняет эту задачу за вас. 4.2. Инструкции для работы со стеком — PUSHw POP Инструкции push и pop предназначены для доступа к стеку. В микропроцессору 8086—Pentium 4 предусмотрено шесть форм инструкций push и pop для следующие операндов: регистр, данные в памяти, непосредственное значение, сегментный регистр, регистр флагов, а также набор регистров общего назначения как целое. Команды push и pop с непосредственным операндом, а также инструкции pusha и рора, предназначенные для сохранения и восстановления всех регистров общего назначения, доступны только в процессорах 80286—Pentium 4. При регистровой адресации в командах push и pop может быть указан любой 16-битный регистр. В процессорах 80386—Pentium 4 также допустимы команды push и pop для 32-битных регистров, включая eflags5. В качестве операнда команд push и pop может быть задано также 16- или 32-битное слово в памяти (32-битное слово — в процессорах 80386—Pentium 4). Непосредственное значение может быть указано при записи в стек командой push, но в команде pop недопустимо. Ограничение при использовании сегментных регистров следующее: имеется возможность записать в стек копию CS, но обратная операция — запись в CS из стека — запрещена. Ио пользование регистров общего назначения и регистра флагов в командах push и pop не ограничено ничем — любой из них может быть указан в качестве источника команд push и приемника команды pop. Инструкция PUSH Инструкция push в процессорах 8086—80286 всегда передаст в стек два байта данных* В процессорах 80386 и выше она пересылает или два, или четыре байта, в зависимости от размерности операнда. Операндом команды push может быть любой внутренний 16- или 32-битный регистр, непосредственные данные, любой сегментный ре* гистр или двухбайтовое слово в памяти. Имеется специальная инструкция pusHA (push all), которая копирует в стек полный набор внутренних регистров, кроме сегментных регистров. Порядок копирования следующий: АХ, СХ, DX, ВХ, SP, ВР, Si и DI. Причем значение SP записывается в стек таким, каким оно было до выполнения команды pusha. Команда pushf (push flags) копирует в стек содержимое регистр* 5 Для сохранения и восстановления флагов предусмотрены команды PUSHF/POPF (для 16-битного регистра FLAGS) и PUSHFD/POPFD (для 32-битного регистра EFLAGS). — Пер. инструкции передачи данных 167 фюгов. Команды pushad и popad сохраняют и восстанавливают значения набора 32-5И।пых регистров, имеющихся в процессорах 80386— Pentium 4. ррп записи в стек первый байт (наиболее значимый) сохраняется по адресу SP — I. jpopoii (наименее значимый) байт записывается по адресу SP - 2. Затем содержите регистра SP уменьшается на 2. Аналогичным образом выполняется запись в сТек двойного слова, только значение SP уменьшается не на 2, а на 4. На рис. 4.Н показано действие инструкции push ах. Запись регистра АХ в стек выполняется следующим образом: SS:|SP - I] = АН, SS:[SP - 2| = AL, после чего SP = SP - 2. Рис. 4.11. Воздействие инструкции PUSH АК.на регистр ESP и на данные в стеке по адресам 37FFH и 37FEH Команда pusha сохраняет в стеке все внутренние 16-битные регистры, как показано на рис. 4.12. Для сохранения восьми регистров ей требуется 16 байт стека. После копирования регистров содержимое SP уменьшается на 16. Команда pusha процессора 80286 очень удобна в тех случаях, когда необходимо полностью сохранить кон-*екст текущей задачи. Команда процессора 80386 pushad выполняет аналогичные действия в отношении 32-битных регистров, сохраняя их в 32 байтах стека. Инструкция push с непосредственным операндом записывает в стек 16-битное значение. Команда pushd с непосредственным операндом помещает в стек 32-битное значение. Если непосредственный операнд находится в диапазоне ООН—FFH, то код °нерации push равен 6АН; если же число попадает в диапазон 0100Н—FFFFH, то к°д операции — 68Н. Например, команда push 8 в машинном коде представлена как 6Д08Н, a push 1000Н — как 680010Н. Еще один пример команды push с непосредственным операндом — инструкция push 'а', которая записывает в стек ASCII-код Отпиской буквы А — число 0041Н. табл. 4.7 приведены варианты инструкции push, включая pusha и pushf. 168 Гпава 4 Таблица 4.7. Инструкции push Вариант инструкции Пример Операнды PUSH reg16 PUSH BX 16-битный регистр PUSH reg32 PUSH EDX 32-битный регистр PUSH meml6 PUSH WORD PTR [BX] 16-битный указатель PUSH mem32 PUSH DWORD PTR [EBX] 32-битный указатель PUSH seg PUSH DS Сегментный регистр PUSH imm8 PUSH ', ' 8-битное непосредственное значение PUSHW iirunl6 PUSHW 1000H 16-битное непосредственное значение PUSHD iinin32 PUSHD 20 32-битное непосредственное значение PUSHA PUSHA Все 16-битные регистры PUSHAD PUSHAD Все 32-битн’ые регистры PUSHF PUSHF Флаги PUSHED PUSHFD Регистр EFLAGS Инструкция POP Инструкция pop противоположна push — эта команда извлекает данные из стека и помешает их либо в 16-битный регистр, в том числе сегментный, или в 16-битное слово в памяти. В процессорах 80386—Pentium 4 команда pop может оперировать также с 32-битными данными; также допускается 32-битная адресация данных в памяти. Непосредственный операнд в инструкции pop недопустим. Команда popf (Pop Flags) помешает 16-битное значение из стека в регистр флагов; команда popfd выполняет аналогичное действие с 32-битным регистром eflags. Инструкция рора (Pop АП) извлекает из стека 16 байт, копируя их в регистры общего назначения DI, SI, BP, SP, ВХ, DX, СХ и АХ (в таком порядке). Последовательность чтения, как видите, обратна порядку записи регистров в стек при выполнении команды pusha. Для сохранения/восстановления набора 32-битных регистров в процессорах 80386— Pentium 4 имеются команды pushad/popad. Инструкции передачи данных 169 Рис. 4.13 иллюстрирует выполнение инструкции pop вх. Эта команда извлекает из стека 16-битное значение и записывает его в регистр вх. Происходит это следующим образом. Первый байт, расположенный в сегменте стека по адресу SP, передается в регистр BL. Затем второй байт, по адресу SP + 1, копируется в регистр ВН. После этого значение регистра SP увеличивается на 2. Варианты инструкции pop приведены в табл. 4.8. Следует отметить, что команда : op cs микропроцессорами Intel не поддерживается — запись в регистр CS без одновременного изменения IP лишена смысла. Таблица 4.8. Разновидности инструкции pop Вариант инструкции Пример Операнды POP reg16 POP ex 16-битный регистр POP reg32 POP EBP 32-битный регистр POP meml6 POP WORD PTR[BX+1] 16-битное косвенно адресуемое слово в памяти POP mem32 POP DATA3 32-битное слово в памяти POP seg POP FS Сегментный регистр POPA POPA Все 16-битные регистры POPAD POPAD Все 32-битные регистры POPF POPF Флаги POPFD POPFD Регистр EFLAGS 170 Гпава 4 Инициализация стека Для инициализации стека требуется установить значения регистров стекового сегмента (SS) н указателя стека (SP). В SS загружается сегментный адрес начала (дна) стека. Например, если для стека зарезервирована память размером 64 Кбайт по адресам Ю000Н —1FFFFH, то в SS следует загрузить число ЮООН. Напомню, что в реальном режиме абсолютный адрес получается из адреса сегмента добавлением ОН справа. Чтобы установить указатель стека на вершину этой области, в регистр SP следует записать число 0000Н. Если бы верхняя граница стека проходила по адресу 10FFFH, то в SP следовало бы загрузить ЮООН. Выполнение первой после инициализации стека команды push показано на рис. 4.14. Как видите, сегменты цикличны — вершина сегмента примыкает к началу сегмента. Рис. 4.14. Иллюстрация цикличности стека (стек до выполнения команды push сх) На языке ассемблера установка сегмента стека программируется так, как это показано в примере 4.1. Первый оператор определяет начало сегмента стека, а последний — его конец. В результате трансляции и компоновки определяются два значения: сегментный адрес стека6 — для записи в регистр SS — и длина стека — для записи в SP. Заметим, что программировать инструкции для установки значений SS и SP не требуется. h В результате компоновки вычисляется относительный сегментный адрес стека, отсчитываемый от начала загрузочного модуля. Абсолютное значение для записи в SS определяется лишь при загрузке программы, когда становится известен абсолютный адрес выделенного нро1раммс блока памяти. — Пер. Инструкции передачи данных 171 I Пример 4.1. Задание стека в программе на языке ассемблера 0000 STACK-SEG SEGMENT STACK 0000 0100 [ DW 100Н DUP (?) ???? ) 0200 STACK SEG ENDS При использовании ассемблера MASM стек может быть определен иначе. В примере 4.2 приведен листинг программы задания стека в стиле MASM — посредством директивы .stack, в которой указана емкость стека в байтах (полный список директив MASM см. в Приложении /). Приведенный пример аналогичен заданию стека в предыдущем случае. i Пример 4.2. Задание стека посредством директивы .stack .MODEL SMALL .STACK 200H /установить размер стека Если стек не определен никаким из указанных способов, то при компоновке будет выдано предупреждение. Его можно проигнорировать, если требуемый размер стека не больше 128 байт. Стек такого объема распределяется системой автоматически (при работе в DOS) — в области префикса программного сегмента (Program Segment Prefix — PSP), находящегося в начале блока памяти, выделяемого программе при загрузке. Если вы используете стек большего размера, то при выполнении программы будет стерта часть PSP с информацией, существенной для выполнения программы. Заметим, что при использовании модели TINY указатель стека автоматически устанавливается на последний байт сегмента программы, что обеспечивает более протяженный стек7 В. 4.3. Загрузка адреса В системе команд микропроцессора имеются специальные инструкции для загрузки адреса. Команда lea загружает в 16-битный регистр (первый операнд — приемник) эффективный адрес (смещение) второго операнда (источника), определяемый в соответствии с использованным методом адресации. Команды lds/les копируют в указанный 16-битный регистр и в регистр ds/es значение двойного слова из памяти. В процессорах 80386—Pentium 4 имеются аналогичные команды lfs, lgs и lss; кроме того, первым операндом может быть указан не только 16-битный, но и 32-битный регистр. Разновидности инструкций загрузки адреса показаны в табл. 4.9. 7 При за груз кс СОМ-файла программе всегда выделяется ровно 64 Кбайт памяти. Содержимое СОМ-файла переписывается в этот блок памяти со смещением 100Н. Сегментный адрес начала блока автоматически записывается в CS, SS, DS и ES; регистр SP получает значение 0FFFFH. В итоге, код и данные находятся "внизу" (начиная со смещения 100Н), а стек "растет" им навстречу — "вниз" с самого "верха" (со смещения 0FFFFH). — Пер. V72 Гпава 4 Таблица 4.9. Инструкции загрузки адреса Инструкция Действие LEA АХ,NUMB Загрузка в АХ адреса numb LEA ЕАХ,NUMB Загрузка в ЕАХ адреса numb LDS DI,LIST Загрузка в DS и DI 32-битного содержимого сегмента данных по смещению LIST LDS EDI,LIST Загрузка в DS и EDI 48-битного содержимого сегмента данных по смещению LIST LES BX,CAT Загрузка в ES и ВХ 32-битного содержимого сегмента данных по смещению CAT LFS DI,DATAI Загрузка в FS и DI 32-битного содержимого сегмента данных по смещению DATA1 LGS SI,DATA5 Загрузка в GS и SI 32-битного содержимого сегмента данных по смещению DATA5 LSS SP,MEM Загрузка в SS и SP 32-битного слова из сегмента данных по смещению мем Инструкция LEA Инструкция lea загружает в 16- или 32-битпый регистр смещение данных в памяти. Например, команда в первой строке табл. 4.9 записывает в регистр АХ адрес numb, а не содержимое numb — в этом и заключается отличие команды lea от команды mov. Например, команда lea вх, [di] загружает в регистр вх смещение данных, адресуемых регистром di (т. е. в вх копируется значение регистра di); напротив, команда mov вх., [di] записывает в вх слово, расположенное в сегменте данных по смещению [DIJ. В предыдущих примерах мы воспользовались директивой offset. Действие этой директивы аналогично действию команды lea. Например, команда mov вх, offset list равносильна команде lea bx,list. Обе инструкции записывают в вх смещение list. Заметим, что длина этих инструкций тоже одинакова — 3 байта. В примере 4.3 показан вариант использования команды lea. При помощи этой команды в регистр S1 записывается адрес datai, а в DI — адрес data2; затем выполняется обмен данными. Листинг 4.3. Пример использования инструкции LEA .MODEL SMALL ; выбор модели SMALL 0000 .DATA ; начало сегмента данных 0000 2000 DATA1 DW 2000H ; определение слова DATA1 0002 3000 DATA2 DW 3000H ; определение слова DATA2 0000 .CODE ; начало сегмента кода .STARTUP ; точка входа в программу 0017 BE 0000 R LEA SI,DATAI ; адрес DATA1 - в SI 001А BF 0002 R MOV DI,OFFSET DATA2 ; адрес DATA2 - в DI 001D 8В 1С MOV ВХ,[SI] ; обмен значений DATA1 и DATA2 Инструкции передачи данных 173 001Г 8В 0D 0021 89 ОС Э023 89 1D MOV MOV MOV СХ,[DI] (SI],CX [DI],BX .EXIT END ; выход в DOS ; конец исходного текста Зачем понадобилась инструкция lea, если директива offset выполняет ту же функцию? Во-первых, директива offset применима только к простым операндам вроде list. Ее нельзя использовать при косвенной адресации, например, для операндов ;di], list [si] и т. п. Во-вторых, директива offset, когда ее можно применить, оказывается более эффективной. То есть инструкция lea bx,list выполняется дольше, чем команда mov вх,offset list. Например, микропроцессор 80486 затрачивает на выполнение lea bx,list два такта, в то время как инструкция mov вх,offset list требует всего лишь одного. Причина в том, что смещение для инструкции mov вх, offset list вычисляется заранее, при трансляции (смещение подставляется в виде непосредственного операнда). Напротив, для команды lea смешение операнда вычисляется при выполнении самой команды. Предположим, что микропроцессор выполняет инструкцию lea вх, [di]. Поскольку смещение задано регистром di, микропроцессор передает в вх копию dt. Команда mov вх, di выполняет ту же задачу за более короткое время и поэтому более предпочтительна. Еще один пример — команда lea si, [bx+di] . Эта инструкция складывает содержимое регистров ВХ и DI по модулю 64К и сохраняет сумму в регистре S1. Например, если ВХ = 1000Н, a DI = 2000Н, то в SI записывается число 3000Н. Если при том же значении ВХ регистр DI = FF00H, то в SI запишется 0F00H, а не 10F00H — поскольку сложение выполняется по модулю 64 К, и перенос за пределы 16-битной разрядной сетки игнорируется. Инструкции LDS, LES, LFS, LGS и LSS Команды lds, les, lfs, lgs и lss загружают в произвольный 16- или 32-битный регистр смещение, а в соответствующий сегментный регистр DS, ES, FS, GS или SS — сегментный адрес. В этих командах применимы любые методы адресации, обеспечивающие доступ к 32- или 48-битной области памяти, где хранятся значения составляющих адреса — сегмента и смещения. 32-битная область используется при 16-битном смещении, а 48-битная — при 32-битном смещении (значение сегмента — всегда 16-битное). Регистровый метод адресации (MOD = 11) здесь нс применяется. Использование 32-битных регистров и команд lfs, lgs и lss возможно только в процессорах 80386 и выше. Команды lds, les, lfs, lgs и lss позволяют загрузить новое значение дальнего указателя на данные, находящиеся в памяти. На рис. 4.15 показан пример выполнения команды lds вх, [Di]. Эта инструкция передает 32-битное число, находящееся в сегменте данных по смещению D1, в пару регистров ВХ и DS. Смещение хранится в младшем слове, а адрес сегмента — в старшем слове двойного слова [di]. То есть в регистр ВХ записываются данные из ячеек 11000Н и 11001Н (число 127АН), а в регистр DS — данные из ячеек 11002Н и 11003Н (число 3000Н). 174 Гпава 4 Для формирования в памяти данных со значением дальнего указателя используется директива dd. Например, оператор addr dd far ptr frog резервирует двойное слово со значениями смещения и адреса сегмента объекта frog; это двойное слово обозначается именем addr. Инструкция lds евх, [Di] в процессорах 80386—Pentium 4 загружает в регистр евх смещение из двойного слова, расположенного в сегменте данных по адресу, указанному в регистре DI. За этим двойным словом находится 16-битное слово, значение которого записывается в регистр DS. Таким образом, при указании 32-битного регистра загрузка происходит из 48-битной области памяти. Первые 4 байта содержат смещение для записи в 32-битный регистр, а последние два байта — сегментный адрес. Среди инструкций загрузки дальнего указателя следует отметить весьма удобную команду lss. В примере 4.4 приведен листинг программы, которая создает новый стек, предварительно сохранив настройки исходного стека. После выполнения нескольких команд прежний стек восстанавливается — за счет одновременной загрузки регистров SS и SP командой lss. Заметим, что при переключении стека без использования команды lss необходимо запретить прерывания командой сы; затем прерывания вновь разрешаются командой sti. Поскольку команда lss поддерживается процессорами 80386 и выше, перед оператором .model в примере 4.4 поставлена директива .386. Директива .386 позволяет транслировать программы для процессоров 80386, 80486 и всех поколений процессоров Pentium. Чтобы воспользоваться такими командами, как cmpxchg, xadd или bswap, следует указать директиву .486; а команда cmpxchg8 из системы команд Pentium предполагает задание директивы .586. Обратите внимание на использование директивы word ptr при записи 16-битной составляющей двойного слова, определенного директивой dd. Инструкции передачи данных 175 Пример 4.4. Использование команды lss 0000 0000 00000000 0004 1000 [ SADDR SAREA .MODEL SMALL .386 . DATA выбор модели SMALL выбор процессора 80386 начало сегмента данных прежний адрес стека новая область стека DD ? DW 1000H DUP (?) ; 0000 2004 0000 0010 ООН 0013 0016 0018 ] = 2004 ГА 8В С4 АЗ 0000 R 8С D0 АЗ 0002 R STOP EQU THIS WORD ; вершина нового стека .CODE ; начало сегмента кода .STARTUP ; точка входа в программу CLI ; запрет прерываний MOV АХ,SP ; сохранить SP MOV WORD PTR SADDR,АХ MOV AX,SS ; сохранить SS MOV WORD PTR SADDR+2,AX 001В 001D 8С D8 8Е D0 MOV AX,DS MOV SS,AX загрузить новое значение SS 001F 0022 0024 0025 0027 В8 2004 R 8В Е0 ГВ 8В СО 8В СО MOV AX,OFFSET STOP ; MOV SP,AX STI MOV AX,AX MOV AX,AX загрузить новое значение SP разрешить прерывания две пустые операции 9029 OF В2 26 0000 R LSS SP,SADDR .EXIT END восстановить прежние значения SS и SP выход в DOS конец исходного текста 4.4. Строковые команды К строковым командам относятся lods, stos, movs, ins и outs. Эти инструкции позволяют передавать байты, слова или двойные слова, а при использовании префиксов повторения целые блоки данных, передавая их байтами, словами или двойными словами. Предварительно рассмотрим роль флага D и регистров D1 и S1 в выполнении строковых инструкций. Флаг направления Флаг направления D выбирает режим автоувеличения (при D = 0) или автоуменьшения (при D = I) значений регистров DI и SI, используемых строковой операцией. Флаг направления влияет на выполнение только строковых инструкций. Инструкция cld обнуляет флаг D, а команда std — устанавливает D = 1. Таким образом, режим автоувеличения устанавливается командой cld, а режим автоуменьшения — командой std. При передаче байта строковой инструкцией содержимое регистра D1 и/или S1 увеличивается или уменьшается на 1, при передаче слова — на 2, а при передаче двойного слова — на 4. Причем изменяются только тс регистры из SI и D1, которые дсй- 176 Гпава 4 ствителыю используются данной строковой инструкцией. Например, команда stosb использует только регистр DI — для адресации данных в памяти. При выполнении команды stosb изменяется только регистр DI, a S1 остается прежним. Напротив, при выполнении команды lodsb, адресующей память только посредством регистра SI, его содержимое изменится, a DI сохранит прежнее значение. Регистры DI и SI При выполнении строковой инструкции доступ к памяти определяется содержимым регистров DI и SI — одного из них или обоих сразу. Регистр DI содержит смещение данных в дополнительном сегменте, a SI адресует данные в главном сегменте данных (по умолчанию). Сегмент данных, связанный с регистром SI, может быть изменен префиксом переназначения сегмента. Сегмент, связанный с регистром DI, не может быть изменен — для строковой команды это всегда дополнительный сегмент. То обстоятельство, что операнды строковых команд находятся в разных сегментах, позволяет передавать (инструкцией movs) до 64 Кбайт данных между произвольными областями памяти. Инструкция LODS Инструкция logs загружает в аккумулятор: регистр AL, АХ или ЕАХ данные, расположенные в сегменте данных по смещению SI. Следует заметить, что загрузка в ЕАХ возможна только в процессорах от 80386 и выше. После записи байта в AL, или слова в АХ, или двойного слова в ЕАХ содержимое регистра SI увеличивается при D = 0 или уменьшается при D = I. При передаче байта значение SI изменяется на I, при передаче слова — на 2, а при передаче двойного слова — на 4. Допустимые обозначения инструкции lods приведены в табл. 4.Ю. Мнемоника lodsb (Loads a Byte) обозначает инструкцию lods для записи байта в al, мнемоника lodsw (Loads a Word) — это вариант lods для записи слова в ах, a lodsd (Loads а Doubleword) обозначает команду lods для загрузки двойного слова в еах. Также (хотя это используется реже) вместо lodsb, lodsw и lodsd применяется lods с операндом, по типу которого ассемблер определяет размерность данных. Таблица 4.10. Варианты инструкции lods Обозначение Действие LODSB AL = DS:[SI]; SI = SI ± 1 LODSW AX = DS:[SI]; SI = SI ± 2 LODSD EAX = DS;[SI], SI = SI ± 4 LODS IdST AL = DS:[SI]; SI = SI ± 1 (если имя list определено как байт) LODS DATAI АХ = DS:[SI], SI = SI ± 2 (если имя datai определено как слово) LODS FROG ЕАХ = DS:[SI]; SI = SI ± 4 (если имя FROG обозначает двойное слово) _ Иллюстрация действия команды lodsw при D = 0, SI = 1000Н и DS = 1000Н представлена на рис. 4.16. В результате выполнения lodsw в АХ копируется 16-битное Инструкции передачи данных 177 число из ячеек памяти по адресам H000H и Н001Н. Поскольку передается слово, а D = 0, то содержимое регистра SI после загрузки АХ увеличивается на 2. Сегмент Рис. 4.16. Выполнение команды LODSW при D = OrSI = ЮООН, DS = ЮООН, [11000Н] = 32 и [11001Н] = ОАОН. (Показано в момент после загрузки АХ, но до изменения SI) Инструкция STOS Команда stos сохраняет значение al, ах или еах в дополнительном сегменте данных по смещению, заданному регистром di. Формы инструкции stos приведены в табл. 4.П. Размерность команды stos уточняется суффиксами в, w или d (обозначает пересылку байтами, словами или двойными словами). Так, команда stosb копирует al, stosw — ах, a stosd — еах. Затем содержимое регистра D1 автоматически Изменяется — увеличивается или уменьшается. Таблица 4.11. Варианты команды stos Обозначение Действие STOSB ES:[DI] = AL; DI = DI ± 1 STOSW ES:[DI] = AX; DI = DI ± 2 178 Гпава 4 Таблица 4.11 (окончание) Обозначение Действие S'L’OSD ES:[DI] = EAX; DI = DI ± 4 STOS LIST ES:[DI] = AL; DI = DI ± 1 (если имя list определено как байт) sros DATA3 ES:[DI] = АХ; DI = DI ± 2 (если имя DATA3 определено как слово) STOS DATA4 ES:[DI] = ЕАХ; DI = DI ± 4 (если DATA4 обозначает двойное слово) Команда STOS с префиксом повторения REP Префикс повторения rep может быть добавлен к любой строковой инструкции, кроме lods — повторное выполнение операции lods не имеет смысла. При включении префикса повторения выполнение строковой инструкции приводит к уменьшению значения регистра СХ. Если СХ после уменьшения не равно нулю, то инструкция повторяется. Если СХ, в результате действия префикса повторения, становится равным нулю, то повторы прекращаются и программа продолжается со следующей команды. Например, если в СХ загружено число 100, то команда rep stosb выполнится ЮО раз. Поскольку регистр DI автоматически увеличивается или уменьшается после каждого цикла stosb, инструкция rep stosb запишет содержимое регистра AL во все байты ЮО-байтного блока данных. В примере 4.5 приведен пример использования команды stosw для очистки видеобуфера в текстовом режиме. Видеопамять начинается по адресу В800:0000. Экран в текстовом режиме состоит из 25 строк по 80 символов в каждой. Одно знакоместо кодируется двумя байтами: в первом байте хранится ASCI 1-код символа, во втором — атрибуты символа (цвет символа, цвет фона и признак мигания). Для очистки экрана в видеобуфер записываются символы пробела (AL = 20Н), белые на черном фоне (АН = 07Н). Пример 4.5. Очистка экрана в текстовом режиме .MODEL TINY оооо .CODE .STARTUP 0100 ЕС OLD 0101 В8 Б800 MOV AX,0B800H 0104 8Е СО MOV ES,AX 0106 BF 0000 MOV DI, 0 0109 В9 07D0 MOV CX,25*80 010С В8 0720 MOV AX,0720H 010F F3/AB REP STOSW .EXIT END ; выбор модели TINY ; начало сегмента кода ; точка входа в программу ; выбор режима автоувеличения ; в ES - адрес сегмента В800 ; в DI - смещение 0000 ; установить счетчик ; загрузить данные ; очистить экран ; выход в DOS ; конец исходного текста Счетчик повторов для команды rep stosw задан константным выражением 25*80, значение которого вычисляется ассемблером при трансляции. Некоторые операторы, используемые в константных выражениях, приведены в табл. 4.12. Инструкции передачи данных 179 Таблица 4.12. Арифметические операторы в константных выражениях Оператор Пример использования в команде Действие команды MOV AL,6+3 Копирует 9 в AL - MOV AL,8-2 Копирует 6 в AL MOV AL,4*3 Копирует 12 в AL / MOV AX,12/5 Копирует 2 в АХ (остаток от деления не используется) MOD MOV AX, 12 MOD 7 Копирует 5 в АХ (целая часть результата деления не используется) AND MOV AX,12 AND 4 Копирует 4 в АХ (1100 AND 0100 = 0100) OR MOV AX,12 OR 1 Копирует 13 в АХ (1100 OR 0001 = 1101) NOT’ MOV AL,NOT 1 Копирует 254 в AL (поразрядная инверсия двоичного числа 0000 0001 равна 1111 1110 или 254) Префиксу rep в машинном коде соответствует байт со значением F3H. В результате, команда rep stosw кодируется двумя байтами со значениями F3H (rep) и АВН (stosw). Если выполнить rep stosw при АХ = 0731Н, то экран будет заполнен белыми единицами на черном фоне. При АХ = 0132Н экран заполняется цифрами 2, с тем же цветом. Подбирая значения регистра АХ в программе из примера 4.5, можно добиться при заполнении экрана любого сочетания символа и цвета. В дальнейшем мы рассмотрим доступ к видеобуферу в текстовом режиме более подробно. Инструкция MOVS Инструкция movs позволяет копировать массивы данных. Это единственная команда копирования в системе команд процессоров 8086—Pentium 4, выполняющая передачу данных из памяти в память. Команда movs копирует байт, слово или двойное слово, расположенное в сегменте данных по смещению SI, в дополнительный сегмент данных по смещению DI. При выполнении movs указатели SI и DI увеличиваются или уменьшаются, в зависимости от значения флага направления. Варианты записи инструкции movs на языке ассемблера приведены в табл. 4.13. Обратите внимание, что переназначение сегмента возможно только для операнда-источника, адресуемого парой регистров DS:Sl. Операнд-приемник всегда находится в дополнительном сегменте данных — по адресу ES:DI. Таблица 4.13. Варианты инструкции movs Обозначение Действие MOVS в ES:[DI] = DS:[SI]; DI = DI ± 1, SI = SI ± 1 (передача байта) MOVSW ES:[DI] = DS:[SIJ; DI = DI ± 2; SI = SI ± 2 (передача слова) MOVSD ES:[DI] = DS:[SI]; DI = DI ± 4; SI = SI ± 4 (передача двойного слова) 180 Гпава 4 Таблица 4.13 (окончание) Обозначение Действие MOVS BYTE1,BYTE2 ES:[DI] = DS:[SIJ; Dl = Dl ± 1; SI = SI ± 1 (если bytei и byte2 определены как байты) MOVS WORD1,WORD2 ES:[DI] = DS:[SI]; Dl = Dl ± 2, SI = SI ± 2 (если wordi и WORD2 определены как слова) MOVS DWORD1,DWORD2 ES:[DI] = DS:[SI]; Dl = Dl ± 4; SI = SI ± 4 (если имена dwordi и dword2 обозначают двойные слова) Рассмотрим еще один пример использования команды movs с префиксом повторения — сдвиг содержимого экрана на одну строку вверх. Программа, приведенная в примере 4.6, копирует содержимое видеобуфера с адреса В800:0000, заданного в регистрах DS:S1. Начальный адрес приемника В800:00А0 задан в регистрах ES:DI8. Инструкция rep movsw выполняется 24*80 раз — за счет этого происходит сдвиг изображения. Затем команда rep stosw очищает нижнюю строку экрана. Пример 4.6. Сдвиг содержймого экрана на одну строку вверх .MODEL TINY ; выбрать модель TINY 0000 .CODE ; начало сегмента кода .STARTUP ; начало программы 0100 FC CLD ; режим автоувеличения Old B8 B800 MOV AX,0B800H ; в ES и DS - В800 0104 8E CO MOV ES,AX 0106 8E D8 MOV DS,AX 0106 BE 00A0 MOV SI,160 ; адрес строки 1 010b BE’ 0000 MOV DI,0 ; адрес строки 0 010F. B9 0780 MOV CX,24*80 ; загрузить счетчик 0111 F3/A5 REP MOVSW ; прокрутка экрана 0113 BF 0F00 MOV DI,24*80*2 ; очистить нижнюю строку 0116 В9 0050 MOV CX, 80 0119 B8 0720 MOV AX,0720H 011C F3/AB REP STOSW .EXIT ; выход в DOS END ; конец исходного текста Инструкция INS Инструкция ins (input string), доступная в микропроцессорах 80286—Pentium 4, передает байт, слово или двойное слово из устройства ввода-вывода в дополнительный сегмент по смещению, заданному регистром D1. Адрес в пространстве адресов сис s Области копирования образуют перекрытие: расстояние между ними соответствует одной строке экрана, а размер каждой из них — 24 строкам (массив-источник начинается с первой строки видеобуфера, а массив-приемник — со второй). — Пер. Инструкции передачи данных 181 темы ввода-вывода задан регистром DX9. Эта инструкция применяется при вводе блока данных из внешнего устройства в память, например, при чтении данных с диска. Подобно остальным строковым инструкциям, команда ins допускает две основные формы записи10. Инструкция insb вводит данные из одного байтового порта и сохраняет их в памяти по адресу ES:DI. Команда insw вводит 16-битное значение из пары смежных портов, a insd — 32-битное значение из четырех смежных портов. С этими инструкциями допустимо применение префикса rep, что позволяет записывать данные в массив целым блоком. Варианты инструкции ins приведены в табл. 4.14. Таблица 4.14. Варианты инструкции ins Обозначение Действие INS В ES:[DI] = [DX]; DI = DI ± 1 (передача байта) INSW ES:[DI] = [DX]; DI = DI ± 2 (передача слова из пары соседних портов) INSD ES:[DI] = [DX]; DI = DI ± 4 (передача двойного слова из четырех смежных портов) INS LIST ES:[DI] = [DX]; DI = DI ± 1 (если имя list определено как байт) INS DATA4 ES:[DI] = [DX]; DI = DI ± 2 (если DATA4 определено как слово) INS DATA5 ES:[DI] = [DX]; DI = DI ± 4 (если DATA5 определено как двойное слово) Фрагмент программы, приведенный в примере 4.7, выполняет 50-кратное чтение порта ОЗАСН, сохраняя результаты чтения в массиве, расположенном в дополнительном сегменте данных по смещению lists. Предполагается, что очередные данные периферийного устройства постоянно готовы для чтения. Иначе пришлось бы отказаться от префикса rep и проверять готовность данных перед каждым обращением к порту. * : Пример 4.7. Чтение из порта в массив командой rep insb 0000 BF 0000 R MOV DI,OFFSET LISTS ; адрес массива 0003 BA 03АС 00'06 FC MOV OLD DX,3ACH ; адрес порта ввода-вывода ; режим автоувеличения 0007 В9 0032 MOV CX, 50 ; счетчик повторов ОООА F3/6C REP INSB ; чтение данных из порта Инструкция OUTS Инструкция outs (output string), доступная в процессорах 80286—Pentium 4, передает байт, слово или двойное слово из сегмента данных (смещение задано регистром SI) } При чтении слова (или двойного слова) DX содержит адрес первого порта из пары (или четверки) смежных портов. — Пер. 10 Вероятно, основными формами следует считать INSB/W/D (с явным указанием размерности) и INS <имя> (размерность определяется типом имени). — Пер. 182 Гпава 4 в пространство портов ввода-вывода по адресу, заданному регистром DX. Формы инструкции outs приведены в табл. 4.15. Таблица 4.15. Формы инструкции outs Обозначение Действие GUT SB [DX] = DS:[SI]; SI = SI ± 1 (передача байта) OUTSW [DX] = DS:[SI]; SI = SI ± 2 (передача слова в пару соседних портов) ?UTSD [DX] = DS:[SI]; SI = SI ± 4 (передача двойного слова в четыре смежных порта) OUTS DATA7 [DX] = DS:[SI]; SI = SI ± 1 (если имя DATA7 определено как байт) GUTS DATA8 [DX] = DS:[SI]; SI = SI ± 2 (если DATA8 определено как слово) GUTS DATA9 [DX] = DS:[SI]; SI = SI ± 4 (если DATA9 определено как двойное слово) В примере 4.8 приведен фрагмент, выполняющий передачу байтов из массива array в порт по адресу ЗАСН. Предполагается, что после очередной записи в порт устройство сразу же готово к следующей записи. ; Пример 4.8. Вывод из массива в порт инструкцией rep outs I ;......................................................................................;.J 0000 BE 0064 R MOV SI,OFFSET ARRAY ; адрес массива 0003 BA ОЗАС MOV DX,3ACH ; номер порта 0006 ГС CLD ; режим автоувеличения 0007 В9 0064 MOV CX,100 ; загрузка счетчика 000А ГЗ/еЕ REP OUTSB 4.5. Дополнительные инструкции передачи данных В этом разделе мы рассмотрим следующие инструкции: xchg, lahf, sahf, xlat, in, out, bswap, movsz, movzx и cmov. Эти инструкции также выполняют передачу данных, хотя применяются реже, чем mov. Инструкция XCHG Команда xchg (exchange) выполняет обмен содержимого регистра и ячейки памяти пли регистра. Обмен между сегментными регистрами или между двумя ячейками памяти не поддерживается. Размерность операндов — байт, слово или двойное слово (в процессорах 80386 и выше); допустимы все методы адресации, рассмотренные в главе 3, кроме непосредственной. Примеры инструкции xchg приведены в табл. 4.16-Вариант инструкции xchg с использованием двух 16-битных регистров, из которых один — АХ, является наиболее коротким — машинный код занимает всего один байт. Другие варианты xchg требуют два и более байтов в зависимости от метоДа адресации. Инструкции передачи данных 183 Таблица 4.16. Примеры инструкции xchg Обозначение Действие XCHG AL,CL Обмен содержимого AL и CL XCHG CX,BP Обмен содержимого СХ и ВР XCHG EDX,ESI Обмен содержимого EDX и ESI XCHG AL,DATA2 Обмен байта, расположенного в сегменте данных по смещению DATA2, с регистром AL При обмене с ячейкой памяти не имеет значения, какой операнд адресует эту ячей-кун. Например, инструкции xchg al, (dij и xchg [di],al выполняют одно и то же действие. В процессорах 80386—Pentium 4 инструкция xchg может оперировать с 32-битными данными. Например, команда xchg еах, евх выполняет обмен содержимого регистров ЕВХ И ЕАХ. Инструкции LAHFvt SAHF Инструкции IAHF и sahf используются довольно редко — они были некогда введены в процессор 8086 для обеспечения совместимости с программами, разработанными для 8-битного микропроцессора 8085, что уже не актуально. Команда lahf передает младший байт регистра флаюв в регистр АН, а команда sahf выполняет обратное действие. Команда sahf используется при работе с арифметическим сопроцессором в следующей ситуации. Регистр состояния сопроцессора копируется в регистр АХ командой fstsw ах, а затем инструкция sahf передает старший байт АХ в регистр FLAGS центрального процессора. Последующая проверка флагов позволяет выявить некоторые из состояний сопроцессора11 12. Эта возможность рассмотрена в г.шве 14. Инструкция XLAT Инструкция xlat преобразует содержимое регистра al в число из таблицы, хранящейся в памяти. Эта команда выполняет доступ к массиву байт по номеру элемента, что часто применяется в задачах преобразования кодов. При выполнении инструкции xlat сначала вычисляется сумма содержимого AL и ВХ; она используется в качестве смешения при доступе к байту в сегменте данных. Содержимое адресуемого байта копируется в регистр AL. Это единственная инструкция, при выполнении которой происходит сложение 8- и 16-битных чисел. 11 Порядок задания операндов нс имеет значения также и при обмене между регистрами. — Пер. 12 Виты слова состояния сопроцессора и регистра FLAGS сочетаются таким образом, что при выполнении пары команд FSTSW АХ и SAHF свойства результата предыдущей операции с плавающей точкой (знак, равенство нулю) отражаются именно в тех флагах центрального процессора, в которых обычно содержатся сведения о результате целочисленной операции. Эго обстоятельство позволяет при работе с сопроцессором использовать тс же команды условного перехода, что и при Целочисленных операциях центрального процессора. — Пер. 184 Гпава 4 рассмотрим листинг, приведенный в примере 4.9. В памяти по смещению table задана таблица кодов семисегментного светодиодного индикатора. Инструкция xlat преобразует двоично-десятичное число, заданное в регистре AL, в семисегментный код; результат записывается в AL. Пример 4.9. Преобразование двоично-десятичного числа в семисегментный код .MODEL SMALL ; выбор модели SMALL _ J00 .DATA ; начало сегмента данных . Д'С1 ЗЕ 06 5В 4F TABLE DB 3FH, 6, 5BH, 4FH ; таблица 7-сегментных ; кодов 66 6D 7D 27 DB 66H, 6DH,7DH,27H 7F 6F DB 7FH,6FH 00 CODE7 DB ; место для результата l 'J'J .CODE ; начало сегмента кода .STARTUP ; точка входа в программу uci7 ВО 04 MOV AL, 4 ; запись тестовых данных вв 0000 R MOV BX,OFFSET TABLE ; смещение таблицы TABLE ОС 1 с D7 XLAT ; преобразование кода 001D Л г 000А R MOV CODE7,AL ; сохранить результат .EXIT ; выход в DOS END ; конец исходного текста На рис. 4.17 показано выполнение команды xlat в соответствии с листингом примера 4.9 при следующих значениях: table = ЮООН, DS = ЮООН и AL = 05Н (двоично-десятичное число 5). После преобразования AL = 6DH. Рис. 4.17. Выполнение инструкции xlat (перед загрузкой 6DH в регистр AL) Инструкции IN и OUT В табл. 4.17 приведены варианты команд ты и оит, выполняющих операции ввода-вывода (р8 обозначает адрес порта в диапазоне О—0FFH, заданный непосредствен- Инструкции передачи данных 185 ним операндом). Во всех вариантах команд in и out обмен между портами и микропроцессором выполняется через регистры AL, АХ или ЕАХ. Инструкция in читает данные из внешнего устройства в al, ка или еах; команда оит записывает содержимое al, ах или еах в устройство. Следует напомнить, что регистр ЕАХ имеется только в процессорах 80386 и выше. Таблица 4.17. Инструкции in и out Обозначение Действие IN AL,p8 Чтение байта из порта по адресу р8 в регистр AL IN АХ,р8 Чтение слова из портов с адресами р8 и р8 + 1 в регистр АХ IN ЕАХ,р8 Чтение двойного слова из четырех портов с адресами от р8 до рй + 3 в регистр ЕАХ IN AL, DX Чтение байта из порта, адресуемого регистром DX, в регистр AL IN AX,DX Чтение в регистр АХ слова из двух портов по адресам DX и DX + 1 IN EAX,DX Чтение в регистр ЕАХ двойного слова из 4 портов, начиная с адреса в DX OUT p8,AL Запись байта из регистра AL в порт по адресу р8 OUT p8,AX Запись слова из регистра АХ в порты р8 и р8 +1 OUT p8,EAX Запись двойного слова из регистра ЕАХ в порты с адресами от р8 ДО р8 +3 OUT DX,AL Запись байта из регистра AL в порт, адресуемый регистром DX OUT DX,AX Запись слова в два порта с адресами DX и DX+1 из регистра АХ OUT DX, EAX Запись двойного слова в 4 порта, адресуемых регистром DX начиная с адреса, указанного в DX Номер порта задается либо фиксированным, либо переменным. Фиксированный адрес — 8-битный. При выдаче в шину адреса он расширяется нулями до 16 бит. Например, при выполнении инструкции in al,6ан адрес порта 6АН выдается на адресные линии АО—А15 в виде 16-битного числа 006АН. Состояние сигналов на линиях А16-А19 (в процессорах 8086/8088), AI6-A23 (в 80286/80386SX), А16-А24 (в 80386SL/80386SLC/80386EX) и А16—А32 (в 80386—Pentium 4) при выполнении операций in и out не определено. Переменный 16-битный адрес задается содержимым регистра DX, которое может быть изменено при выполнении программы. На рис. 4.18 показано выполнение команды оит 19н,ах. Эта инструкция передает содержимое регистра АХ в порты по адресам 19Н и 20Н. По шине адреса передается число 0019Н, по шине данных — содержимое АХ; управляющий сигнал IOWC (I/O Write Control) при передаче сбрасывается в 0. В примере 4.10 приведена программа для получения звукового сигнала из динамика IBM PC. Динамик подключен к порту 61Н. Звук включается одновременной установкой в 1 первых двух разрядов порта 61Н. Заметим, что в программе используются команды or и and — для установки и сброса отдельных разрядов. Эти команды подробно рассмотрены в главе 5. Инструкция mov сх,4ооон и последующая команда 186 Гпава 4 loop ы обеспечивают задержку между включением и выключением звука. Если записать в регистр СХ большее число, звук будет продолжительней. Рис. 4.18. Сигналы на системной шине при выполнении команды OUT 19Н,АХ Пример 4.10. Получение звукового сигнала из динамика IBM PC .MODEL TINY ; выбрать модель TINY оооо .CODE ; начало сегмента кода .STARTUP ; начало программы 0100 Е4 61 IN AL,61H ; чтение порта 61Н и102 ОС 03 OR AL,3 ; установив биты 0 и 1, 0104 Е6 61 OUT 61H,AL ; включить динамик 0106 В9 1000 MOV C.Y,10C'0H ; счетчик задержки 0109 LI: 0109 Е2 ЕЕ LOOP LI ; цикл задержки 010В Е4 61 IN AL,61H ; прочитать порт 61Н 010D 24 ЕС AND AL,0FCH ; очистив биты 0 и 1, 010F Е6 61 OUT 61H,AL ; выключить динамик .EXIT ; выход в DOS END ; конец исходного текста Инструкции MOVSX м MOVZX В процессорах 80386—Pentium 4 введены команды пересылки movsx (Move and Sign-eXtend) и movzx (Move and Zero-eXtend). Они позволяют расширять передаваемые данные нулями (zero-extend) или значением знакового бита (sign-extend). Примеры инструкций movsx и movzx приведены в табл. 4.18. Команда movzx записывает в старшую часть приемника нули. Так, например, при записи командой movzx 8-битного значения 34Н в 16-битный приемник число преобразуется в 16-битное — 0034Н. Инструкция movzx часто используется для преобразования беззнаковых 8- или 16-битных значений в 16- или 32-битные. Инструкции передачи данных 187 Таблица 4.18. Инструкции movsx и movzx Обозначение Действие MOVSX CX,BL Передает BL в СХ, с расширением знака MOVSX ЕСХ,АХ Передает АХ в ЕСХ, с расширением знака MOVSX ВХ,DATAI Передает байт datai в ВХ, с расширением знака MOVSX ЕАХ,[EDI] Передает в ЕАХ слово из сегмента данных по смещению EDI, с расширением знака MOVZX DX,AL Передает, дополняя нулями, AL в DX MOVZX EBP,DI Передает, дополняя нулями, DI в ЕВР MOVZX DX,DATA2 Передает в DL байт из сегмента данных по смещению data2, обнуляя DH MOVZX EAX,DATA3 Передает в АХ слово из сегмента данных по смещению DATA3, обнуляя старшее слово регистра ЕАХ Команда movsx копирует знаковый бит источника в старшие биты приемника. Например, 8-битная отрицательная величина 84Н при записи в 16-битный приемник преобразуется в 16-битную величину без потери знака — FF84H. Знаковый бит 8-битного числа 84Н равен 1, поэтому биты старшего байта приемника устанавливаются в 1. Инструкция movsx используется для преобразования 8- или 16-битных знаковых чисел в 16- или 32-битные, с сохранением величины и знака. Инструкция BSWAP Инструкция bswap (byte swap), доступная в процессорах 80486—Pentium 4, меняет местами байты 32-битного регистра. Первый байт обменивается с четвертым, второй — с третьим. Например, в результате*^ выполнения команды bswap еах при ЕАХ = 00112233Н значение ЕАХ станет равным 33221100Н. Порядок байт, в результате, меняется на обратный. Инструкция bswap применяется для преобразования формы представления слов и двойных слов — между форматами Intel и Motorola. Группа команд CMOV Группа команд условного копирования cmov (conditional move) впервые появилась в процессорах Pentium Pro и Pentium II. В табл. 4.19 приведены многочисленные варианты инструкций cmov. Команды этой группы передают данные лишь при выполнении некоторого условия13. Например, команда cmovz копирует данные, если результат предыдущей инструкции равен нулю (zero). Приемником при выполнении инструкции cmov может быть только 16- или 32-битный регистр, а источником — регистр или данные в памяти (той же размерности). Поскольку эти инструкции отсутствуют в системе команд Pentium, их использование возможно только при поддержке ассемблером директивы .686. Если эта дирек- 13 Если условие нс выполнено, то команда CMOV равносильна пустой операции. — Пер. 188 Гпава 4у тива в вашей версии ассемблера не предусмотрена, команды cmov придется кодировать вручную при помощи директивы db. Код операции для команд cmov равец^ 0F4xH, где х — код условия в диапазоне О—F (коды условия см. в Приложении 2). Зд^ кодом операции следует байт mod-reg-r/м. Пример кодирования инструкции cmov1 приведен в примере 4.Н. Пример 4.11. Задание инструкции cmovb ах,вх при помощи директивы db 0000 OF 42 СЗ DB 0FH,42H,0C3H ; код инструкции CMOVB АХ, ВХ Таблица 4.19. Инструкции условного копирования Обозначение Условие Действие CMOVB С = 1 Передать, если установлен признак "ниже" (Below) CMOVAE с = о Передать, если "выше или равно" (Above or Equal) CMOVBE Z = 1 или С = 1 Передать, если "ниже или равно" (Below or Equal) CMOVA Z=0nC=0 Передать, если "выше" (Above) » CMOVE/CMOVZ Z= 1 Передать, если "равно" (Equal)14 ] ч CMOVNE/CMOVNZ Z = 0 Передать, если "не равно" (Not Equal) или, что-то же i самое, если не "ноль" (Not Zero) CMOVL S<> О Передать, если "меньше" (Less than) 3 CMOVLE Z = 1 или S <> О Передать, если "меньше или равно" (Less than or^ Equal) CMOVG Z=0nS=O Передать, если "больше" (Greater than) I CMOVGE S = O Передать, если "больше или равно" (Greater than orJ Equal) CMOVS S = 1 Передать, если знак отрицательный (Sign) CMOVNS s = o Передать, если знак неотрицательный (No Sign) CMOVC C = 1 Передать, если перенос (Carry) * | CMOVNC c = o Передать, если нет переноса (No Carry) $ CMOVO 0 = 1 Передать, если переполнение (Overflow) | CMOVNO 0 = 0 Передать, если нет переполнения (No Overflow) * CMOVP/CMOVPE p = 1 Передать, если parity or set if parity even CMOVNP/CMOVPO P = 0 Передать, если нет паритета (No Parity) или, иначе j говоря, паритет нечетный (Parity Odd) u 14 Признаки "равно" (equal) и "ноль" (zero) соответствуют одному и тому же флагу Z регистр11 FLAGS, так что мнемоники CMOVE и CMOVZ обозначают одну и ту же машинную команду. — Пер- Инструкции передачи данных 189 4.6. Префиксы переназначения сегмента Префикс переназначения сегмента позволяет при доступе к данным в памяти изменить сегмент, выбираемый процессором по умолчанию. Префикс может быть добавлен почти к любой инструкции, адресующей данные в памяти. В машинном пред-С|авлении префикс переназначения сегмента — это дополнительный байт перед кодом команды. Префикс обычно не ставится перед инструкциями передачи управления, поскольку они всегда адресуют сегмент кода15. В процессорах 80386— Pentium 4 допускаются дополнительные префиксы fs и gs. рассмотрим пример. Инструкция mov ах, [dij по умолчанию выполняет доступ к данным в текущем сегменте данных. Предположим, что данные находятся в дополнительном сегменте. Для доступа к ним используем префикс переназначения сегмента: MOV AX,ES:[DIJ. В табл. 4.20 приведены примеры команд с переназначением сегмента. Напомним, что при включении префикса длина инструкции увеличивается на один байт. Также увеличивается и время выполнения. Поэтому использование префиксов в программе рекомендуется свести к минимуму. Таблица 4.20. Примеры инструкций с префиксом переназначения сегмента Обозначение Адресуемый сегмент Сегмент по умолчанию MOV Ал, DS:[ВР] Data — данные Stack — стек МО'.’ AX,ES: [ВР] Extra — дополнительные данные Stack — стек MOV SS:[DI] Stack — стек Data — данные MOV .AX, CS: LIST Code — инструкции Data —данные MOV AX,ES:[SI] Extra — дополнительные данные Data — данные LODS ES:DATA1 Data —данные Extra — дополнительные данные MOV EAX,FS:DATA2 Data — данные FS MOV BL,GS:[ECX] Data — данные GS 4.7. Введение в язык ассемблера Ассемблер обеспечивает два способа организации программы: за счет полного описания сегментов (этот способ универсален и поддерживается всеми ассемблерами) либо посредством сокращенных директив, доступных при указании модели памяти, этом разделе мы рассмотрим оба способа, с объяснением наиболее важных дирек- Тив- Справочник по директивам ассемблера см. в Приложении 1. 15 и ивключение составляют команды типа JMP/CALL [ADDR], где ADDR определено как слово или двойное слово, в котором сформирован ближний или дальний адрес перехода. По умолчанию z'Sdr находится в сегменте данных, и переназначение сегмента допускается. Например. ES: [ADDR], CALL CS: [ADDR] И т. п. — Пер. 190 Гпава 4 Директивы Наиболее важные директивы, или псевдооператоры языка ассемблера, приведены в табл. 4.2I. Директивы определяют способ трансляции операнда инс1рукции пли фрагмента программы. Некоторые директивы генерируют данные в памяти или влияют на машинный код инструкций. К ним относится, например, директива db, которая резервирует данные в памяти (байты) и присваивает им начальные значения. Напротив, директива byte ptr нс резервирует память, а лишь уточняет размерность данных в памяти, косвенно адресуемых через индексный п/или базовый регистр. Таблица 4.21. Наиболее используемые директивы ассемблера Директива Назначение .286 Выбор набора инструкций микропроцессора 80286 .286Р Выбор инструкций защищенного режима микропроцессора 80286 .386 Выбор инструкций процессора 80386 . 386Р Выбор инструкций защищенного режима процессора 80386 .486 Выбор инструкций процессора 80486 . 486Р Выбор инструкций защищенного режима процессора 80486 .586 Выбор инструкций Pentium .586Р Выбор инструкций защищенного режима Pentium .287 Выбор сопроцессора 80287 .387 Выбор сопроцессора 80387 .EXIT Выход в DOS .MODEL Выбор программной модели .STARTUP Установка точки входа в программу, если выбрана программная модель ALIGN 2 Выравнивание данных по границе слова (align 4 задает выравнивание по границе двойного слова) ASSUME Устанавливает соответствие между сегментными регистрами и сегментами, определенными в программе BYTE Указывает, что операнд имеет размерность байта (равносильно byte ptr) DB Определяет байты (один, как минимум) DD Определяет двойные слова DQ Определяет 8-байтные (64-битные) слова DT Определяет 10-байтные (80-битные) слова DUP Задает повтор элементов списка DW Определяет двухбайтные слова DWORD Указывает, что операнд имеет размерность двойного слова (равносильно DWORD PTR) Инструкции передачи данных 191 Таблица 4.21 (окончание) Директива Назначение END Завершает текст программы ENDM Завершает макроопределение ENDP Завершает определение процедуры ENDS Завершает сегмент или структуру данных EQU Определяет новое имя со значением и типом указанного выражения FAR Определяет дальний указатель MACRO Обозначает начала макроопределения NEAR Определяет ближний указатель OFFSET Возвращает смещение указанного объекта в памяти ORG Устанавливает смещение в программном сегменте равным заданному значению PROC Обозначает начало определения процедуры PTR Обозначает указатель SEGMENT Определяет начало программного сегмента .STACK Определяет начало сегмента стека STRUC Определяет начало структуры данных USES Задает сохранение и восстановление указанных регистров в процедуре USE16 Включает режим 16-битных инструкций для процессоров 80386—Pentium 4 USE32 Предписывает генерирование ассемблером инструкций 32-битного режима WORD Указывает, что операнд имеет размерность слова (равносильно word ptr) По умолчанию, если в начале программы не указана директива выбора процессора (например, .386 или .386р), ассемблер использует инструкции 8086/8088. Директива .396 предписывает использование команд реального режима процессора 80386. а директива .386р— инструкций защищенного режима 80386. Эти директивы в настоящее время применяются довольно часто, поскольку вновь разрабатываемое программное обеспечение полностью ориентировано на микропроцессоры 80386— Pentium 4. Это, в первую очередь, относится к программам для 32-битной операционной системы Windows. Директивы определения данных Директивы db (define byte), dw (define word) и dd (define doubleword), с которыми вы ’’ознакомились в главе Ц применяются для резервирования и инициализации данных в памяти. В программах, работающих с арифметическим сопроцессором, обычно используются дополнительные директивы для определения 8- и 10-байтных данных — dq (define quadword) и dt (define ten bytes). Необязательное имя перед ключе-’’Ым словом db/dw/dd/dq/dt получает значение адреса данных, определяемых директивой. 192 Глава 4 > - < Пример 4.12 демонстрирует использование этих директив в программе. Для задания : начала сегмента данных применяется оператор segment; имя в начале этого операто- ' ра используется для обозначения сегментного адреса. Определение сегмента посредством оператора segment является стандартным и универсальным (полное определение). Сокращенный вариант предполагает использование оператора .data при предварительном указании модели памяти. Последний оператор в примере 4.12— директива ends, обозначающая конец сегмента. Имя сегмента (list_seg) может быть любым, на ваше усмотрение. Число сегментов не ограничено. Пример 4.12. Использование директив db, dw и dd 0000 LIST-SEG SEGMENT 0000 01 02 03 DATAI DB 1,2,3 ; определить байты 0003 45 DB 45H ; 16-ричное начальное значение 0004 41 DB 'A' ; начальное значение - ASCII-код 0005 F0 DB 11110000B ; начальное значение - двоичное 0006 000С 000D DATA2 DW 12,13 ; определить слова 000А 0200 DW LIST1 ; начальное значение - смещение LIST1 ооос 2345 DW 2345H ; 16-ричное начальное значение 000Е 00000300 DATA3 DD 300H ; аналогично 0012 4007DF3B DD 2.123 ; начальное значение - действительное 0016 544269Е1 DD 3.34E+12 ; аналогично 001А 00 LISTA DB 9 ; зарезервировать один байт 001В 000А [ ?? LISTB DB 10 DUP ( ?) ; зарезервировать десять байт 0025 ] 00 ALIGN 2 ; выравнивание по границе слова 0026 0100 [ 0000 LISTC DW 100H DUP (0); массив слов 0226 J 0016 [ LIST_9 ???????? DD 22 DUP ( ?) ; массив двойных слов 027Е 02Е2 0064( 06 ] J SIXES LIST SEG DB ENDS 100 DUP (6) ; массив байт В примере 4.12 продемонстрированы различные варианты определения данных. Kj видите, один оператор может определять более одного элемента данных (наприме по адресу метки datai). При задании значений элементов использованы двоичны шестнадцатеричные и десятичные числа, а также ASCII-символы16. При определ нии двойных слов (с адреса метки иатаз) начальные значения заданы действитеЛ^ ными числами, хранятся они как числа с плавающей точкой одинарной точности, и । 16 При определении слов (с адреса метки DATA2) в качестве инициализирующего значения TalCJ?J использовано имя LIST1. В результате, в памяти сформирован ближний указатель на °бъе1Р LIST1. Поскольку фрагмент в примере 4.12 не содержит определения LIST1, это имя долЖ# быть задано в другой части программы. — Пер. Инструкции передачи данных 193 Неопределенное начальное значение задается знаком вопроса. Элемент данных, за-ишнын знаком вопроса, обычно инициализируется нулем17. Директива dup (duplicate) используется для задания и инициализации массива. Так, например, выражение ю dup (?) в списке начальных значении задает десять элементов данных неопределенной величины. Оператор datai db io dup (2) резервирует десять байт в памяти со значением два (02Н); метка первого байта массива именуется в дальнейшем DATA1. Директива align 2 в примере 4.12 задает выравнивание последующего элемента данных или машинной инструкции по границе слова, a align 4 — по границе двойного с юва. В процессорах Pentium—Pentium 4 используется также директива align 8 — дня выравнивания в памяти 8-байтных данных в формате действительных чисел двойной точности. Выравнивание сокращает время доступа к данным. Так, например, доступ к слову, расположенному но четному адресу, выполняется вдвое быстрее, чем к слову но нечетному адресу. Заметим, что использование директивы align не имеет смысла при указании модели памяти, поскольку модель определяет выравнивание сегмента в целом18. Заметим также, что директива align нс понадобится вам в том случае, если вы определяете сначала двойные слова, затем обычные слова, а байты — в конце. Директивы ASSUME, EQU и ORG Директива equ вводит новое имя п присваивает ему значение числа, ASCII-кода или другого имени. Введение символических имен делает программу понятней и упрощает ее отладку и сопровождение. В примере 4.13 показано использование директивы equ н определенных ею имен. Пример 4.13. Использование директивы equ :эоа - J009 TEN NINE EQU 10 EQU 9 во 0А MOV AL,TEN -Л2 04 09 ADD AL,NINE Ключевое слово this используется в директивах this byte, this word и this dword. “hn директивы позволяют создавать синонимы для имен, определенных в начале операторов db/dw/dd/dq/dt. Синонимы разных типов позволяют адресовать одну и ту В некоторых ситуациях значения, заданные знаком вопроса, действительно будуг неопределенными. Например, если при компоновке сегмент с неопределенными значениями помещается в конец Исполняемой программы, то, возможно, его данные с неопределенными начальными значениями вообще нс будут записаны в ЕХЕ-файл. При запуске программы загрузчик выделит память для всех сегментов, но данные в конце последнего сегмента инициализированы не будуг, и их значения окажукя случайными. — Пер. 'Эффективность директивы ALIGN зависит от того, какое выравнивание задано для сегмента в Пелом (в директиве SEGMENT или в сокращенных директивах, связанных с моделью программы). Если, например, сегмент должен быть выровнен но границе байта (то есть нс выровнен вообще), любая директива ALIGN бесполезна. Если сегмент выравнивается по границе слова, то директива ALIGN 2 имеет смысл, a ALIGN 4 — бесполезна. — Пер. 7 Лак ЗК4 194 Гпава 4 же область данных как байт, слово или двойное слово. Пример использования директивы this byte приведен в примере 4.14. Пример 4.14. Использование директив this и org 0000 DATA_SEG SEGMENT 0100 ORG 100H 0100 DATA1 EQU THIS BYTE 0100 0000 0102 DATA2 DW ? DATA_SEG ENDS 0000 CODE_SEG SEGMENT 'CODE' ASSUME CS :CODE_SEGZDS:DATA_SEG 0000 КА 1Е 0100 R MOV BL, DATA1 0004 А1 ОН 30 R MOV AXZDATA2 000Л 8А ЗЕ 0101 R MOV BHZDATA1+1 000.8 CODE SEG ENDS В примере 4.14 также показано применение директивы org (origin). В примере эта директива устанавливает начальное смещение в сегменте data_seg равным 100Н19. Еще одна новая директива — assume — сообщает ассемблеру имена, выбранные для сегментов кода, данных, дополнительных данных и стека. Если директива assume не указана, то ассемблер ничего не знает о назначении сегментов (что равносильно оператору assume nothing) и добавляет префикс переназначения сегмента ко всем инструкциям, адресующим данные20. Оператор assume используется только при полном определении сегментов. Директивы PROCn ENDP Директивы proc и endp обозначают начало и конец определения процедуры, или подпрограммы. Структура программы при использовании этих директив становится яснее. Кроме того, в отсутствие этих директив или при их неправильном использовании21 вам придется явно указывать дальность вызовов и возвратов — командами CALLF, CALLN, RF.TF И RETN22. В ДИреКТИВЗХ PROC И ENDP ДОЛЖНО бЫТЬ ЗаДЗНО ИМЯ ПрО 19 Начальное смешение по умолчанию равно нулю. Оператор ORG 100Н в примере резервирует 256 байт в начале сегмента DATA_SEG. — Пер. 20 Директива ASSUME обеспечивает автоматическую подстановку префикса переназначения сегмента при обращении к данным по имени. Ассемблер знает, в каком сегменте определено имя, а также — посредством ASSUME — информирован о соответствии между сегментами в программе и сегментными регистрами. При косвенной адресации автоматическая подстановка префиксов невозможна — нет информации о сегменте. Отсутствие ASSUME, если ассемблер это позволяет, отключает автоматическую подстановку префиксов переназначения сегмента. — Пер. 21 Процедура может быть определена и без использования директив PROC/ENDP — меткой в начале процедуры. При использовании PROC этой директиве должна соответствовать парная директива ENDP; кроме того, пары PROC/ENDP не должны быть вложенными. — Пер. 22 При указании в директиве PROC атрибуга FAR или NEAR (действует по умолчанию) вызов процедуры может быть запрограммирован без указания "дальности" — оператором CALL. Также, команды возврата (в теле процедуры) могут быть заданы операторов RET. Зная "дальность" процедуры, ассемблер автоматически подставляет на место операторов CALL и RET инструкции CALLN/CALLF И RETN/RETF. — Пер. Инструкции передачи данных 195 цедуры. После ключевого слова proc, обозначающего начало процедуры, указывается атрибут near или far. Определение NEAR-процедуры и оператор ее вызова должны находиться в одном сегменте кода. Определение FAR-процедуры может быть задано в произвольном кодовом сегменте. Ближние (near) процедуры называют также локальными, а дальние процедуры (far) — глобальными, подразумевая под этим, что глобальная процедура может быть вызвана из любой точки программы, а локальная — только из текущего сегмента кода. Метки в процедуре также могут быть определены как локальные (near) или глобальные (far). В примере 4.15 показана процедура, которая складывает значения в регистрах вх, сх и dx и помещает результат в регистр ах. Конечно, эта короткая процедура не представляет какой-либо практической ценности, но она хорошо иллюстрирует применение директив proc и endp. Заметим, что действия, выполняемые процедурой, желательно описывать в комментариях перед ее определением, с указанием регистров, в которых передаются входные значения и возвращаются результаты, а также регистров, изменяемых при выполнении процедуры. Пример 4.15. Сложение значений регистров вх, сх и dx с записью результата в ах 0000 ADDEM PROC FAR ; начало процедуры 0000 03 D9 ADD BX,CX 0002 03 DA ADD BX, DX 0004 83 C3 MOV AX, BX 0006 CB RET 0007 ADDEM ENDP ; конец процедуры Ассемблер Microsoft MASM версии 6.x позволяет указать в директиве proc перечень регистров, которые должны быть сохранены при выполнении процедуры. Для этого используется директива uses со списком регистров, в соответствии с которым ассемблер автоматически генерирует команды push в начале процедуры и команды pop в конце — перед инструкцией ret. Так, например, оператор adds proc uses ах вх сх задает сохранение и восстановление регистров ах, вх и сх. В примере 4.16 приведен пример процедуры, написанной на MASM 6.Х с использованием директивы uses. Обратите внимание, что регистры в списке разделены не запятыми, а пробелами. Заметим также, что команды push и pop, автоматически сгенерированные ассемблером, попадают в листинг, только если в исходном тексте указана директива .listall. Пример 4.16. Использование процедуры с директивой uses для сохранения регистров вх, сх и dx U000 ADDS PROC NEAR USES BX CX DX 0000 53 pash bx 0001 51 push CX 0002 52 push dx 0003 03 D8 ADD BX, AX 0005 03 СВ ADD CX, BX 0007 03 D1 ADD DX,CX 0009 8В С2 MOV AX, DX RET 196 Глава 4 ОСОБ 5 А ; pop dx ОООС 59 ; pop сх ОООЬ 5В ; pop Ьх COGE СЗ ; ret OOOOOh иOOF ADDS ENDP Организация памяти Сегментная структура программы описывается на языке ассемблера одним из двух способов: при помощи моделей либо посредством полного определения каждого сегмента. Модели памяти, с которыми вы познакомились в главе 2 и 3, уникальны для ассемблера MASM. Модели же в ассемблере TASM несколько отличаются от моделей в MASM. Полное определение сегментов поддерживается всеми ассемблерами, включая ассемблер фирмы Intel. Если модели удобны в простых задачах, то полное определение больше подходит дня сложных приложении, поскольку дает больше возможностей по управлению памятью. В этой книге все примеры простые, поэтому здесь предпочтение отдано моделям памяти. Модели упрощают разработку интерфейсных процедур (т. е. процедур на ассемблере, вызываемых из программ на языках С или C++), вместе с тем, полное описание, безусловно, имеет свои преимущества. Модели памяти В ассемблере MASM доступны модели памяти с наименованиями от tiny до huge: (полный список см. в Приложении /). Модель памяти определяется оператором .model. Модель tiny означает, что данные и команды помещаются в один сегмент размером 64 Кбайт, что вполне подходит для большинства программ небольшого размера. Модель small предполагает, что данные помещаются в один сегмент, а программный код — в другой сегмент (всего не более 128 Кбайт). Пример 4.17 демонстрирует применение оператора .model в программе копирования 100-байтного блока данных lista в блок данных listb. В этом примере также показано определение стека и сегментов данных и кода. Директива .emit о задает возврат в DOS с кодом ошибки 0 (нет ошибки). Если директива .exit задана без параметра, то выход в DOS все равно произойдет, но значение кода ошибки при этом не определено. Для обозначения адресов сегментов используются специальные директивы, например, @data (см. Приложение /). Две команды при входе в программу — mov ах, @data и movds,ax— в MASM б.л* программируются одной директивой .startup. Директива .startup также отмечает точку входа в программу, избавляя от необходимости указывать стартовый адрес в операторе end. Также использование моделей памяти упрощает включение фрагментов па ассемблере в проекты на языке C/C++ в системах Microsoft C/C++ и Borland C/C++. Пример 4.17. Использование директивы .model .model small .STACK 100H ; определить сегмент стека .DATA ; определить сегмент данных Инструкции передачи данных 197 0000 0064 [ LISTA DB 100 DUP (?) ] 0064 0064[ ] LISTB DB 100 DUP (?) .CODE ; определить сегмент кода 0000 B8 P. 0003 8E CO 0005 8E D8 0007 EC 0008 BE 0000 R 000B BE 0064 R 000E B9 0064 ООН E3/A4 0013 HEPE: MOV AX,@DATA ; адрес сегмента данньс< - в ES и DS MOV ES,AX MOV DS,AX CLD ; move data MOV SI,OFFSET LISTA MOV DI,OFFSET LISTB MOV CX,100 REP MOVSB .EXIT 0 ; выход в DOS END HERE Полное определение сегментов В примере 4.18 показан листинг программы с полным определением сегментов. Следует отметить, что при использовании систем Borland C/C++ или Microsoft C/C++ полное определение сегментов необходимо при включении ассемблерной процедуры в проект на языке C/C++. Как видите, исходный текст в примере 4.18 увеличился по сравнению с примером 4.17. Вместе с тем, структура сегментов здесь более отчетлива, поскольку границы сегментов обозначены парными директивами segment и ends. Сегмент по имени stack_seg определен с атрибутом stack — это сегмент стека. Память под стек зарезервирована внутри сегмента stack_seg оператором dw loo dup (?) и составляет 256 слов. В соответствии с описанием сегмента стека ассемблер и компоновщик вычислят сегмент и смещение вершины стека и поместят их значения в регистры ss:sp. Пример 4.18. Задание сегментов директивой segment 0000 0000 0100[ 1 0200 STACK_SEG SEGMENT STACK DW 100H DUP (?) STACK SEG ENDS 0000 DATA SEG SEGMENT 'DATA' 00U0 0064[ LISTA DB 100 DUP (?) 0064 0064[ LISTB DB 100 DUP (?) 00C3 DATA SEG ENDS 198 Гпава 4 0000 CODE_SEG SEGMENT 'CODE' ASSUME CS:CODE_SEG,DS:DATA_SEG ASSUME SS:STACK_SEG 0000 MAIN PROC FAR 0000 В8 R MOV AX,DATA_SEG ; адрес сегмента данных - в DS и ES 0003 8Е СО MOV ES,AX 0005 8Е D8 MOV DS,AX 0007 FC CLD ; копировать данные 0008 BE 0000 R MOV SI,OFFSET LISTA 000В BF 0064 R MOV DI,OFFSET LISTB 000Е В9 0064 MOV CX,100 ООП F3/A4 REP MOVSB 0013 В4 4С MOV AH,4CH ; выход в DOS 0015 CD 21 INT 21H 0017 MAIN ENDP 0017 CODE_ _SEG ENDS END MAIN Данные определены в сегменте data_seg. Это два массива, обозначенных метками lista и listb, по 100 байт в каждом. Следует отметить, что имена сегментов могут быть выбраны любыми. Обычно в директивах определения данных указывается класс 'data'23, что необходимо для организации символической отладки средствами отладчика CodeView. (Отладчик CodeView входит в дистрибутив ассемблера MASM.) Запуск CodeView выполняется командой cv, с указанием имени файла, из командной строки DOS. Если при определении сегментов был задан класс 'data', CodeView обеспечивает отладку с использованием имен исходной программы. В противном случае отладка по-прежнему возможна, но уже без символов. Другие стандартные классы — 'stack' и 'code' — рассмотрены в Приложении /. Заметим, что символическая отладка в CodeView предполагает также указание класса 'code* при описании сегмента кода. Программа в сегменте code_seg определена в виде дальней процедуры24. До начала исполняемой части программы задан оператор assume с перечнем предполагаемых значений сегментных регистров: например, cs = code_seg. 23 Имя класса имеет значение при объединении сегментов. Например, объединение одноименных сегментов из разных исходных модулей происходит лишь в том случае, если класс у них один и тог же (также при определении каждого из этих сегментов должен быть задан атрибут PUBLIC). Класс 'DATA' является стандартным в том смысле, что он назначается сегментам данных при трансляции с языка С. Именно это имя класса — 'DATA' — следует указывать в определении сегментов данных при объединении программ на языках ассемблер и C/C++. — Пер. 24 Определение главной программы в виде FAR-процедуры обычно подразумевает следующее. В начале программы в стек записывается дальний указатель на начало PSP (Program Segment Prefix), где хранится инструкция INT 20Н — один из возможных вариантов выхода в DOS. Оператор RET, заданный в конце программы, отрабатывается как RETF. В результате, управление передается нд инструкцию INT 20Н, и программа завершается. В итоге этих ухищрений программа выглядит как FAR-процедура, вызываемая из DOS командой CALLF. Но в примере,’приведенном автором, выход в DOS запрограммирован явно — функцией 4СН прерывания 21Н (что является лучшим решением). В этом случае определение программы в виде FAR-процедуры лишено смысла. — Пер. Инструкции передачи данных 199 После загрузки регистров ES и DS значением сегментного адреса сегмента данных data_seg программа выполняет копирование 100 байт из массива lista в массив LISTB. Затем выполняется выход в DOS. Обратите внимание, что загрузчик не записывает в регистры DS и ES значение data_seg — эти регистры следует инициализировать до обращения к сегменту данных25. Последний оператор в программе — это end main. Оператор end отмечает конец исходного текста программы, а метка после ключевого слова end указывает точку входа в программу (смещение первой исполняемой команды). При определении сегментов кода для микропроцессоров 80386—Pentium 4 используется дополнительный атрибут — useig или USE32. Атрибуг USE16 предписывает генерирование инструкций 16-битного режима, a use32 — 32-битного. В программах для DOS следует указывать атрибут USE16, если в начале программы выбран процессор 80386—Pentium 4. Дело в том, что при наличии директивы .386 (.486 и т. д.) MASM считает все сегменты по умолчанию 32-битными и генерирует инструкции для 32-битного режима. В листинге, приведенном в примере 4.19, выбран процессор 80386, а кодовый сегмент определен с атрибутом USE16. Пример 4.19. Вариант задания кодового сегмента с использованием атрибута use 16 0000 0000 0100[ .386 ; выбрать процессор 80386 STACK SEG SEGMENT STACK DW 100H DUP (?) ???? 0200 ] STACK_SEG .ENDS 0000 DATA_SEG SEGMENT ' DATA' 0000 0064[ LISTA ?? DB 100 DUP (?) 1 T- 0064 0064[ LISTB ?? DB 100 DUP (?) 00С8 ] DATA_SEG ENDS 0000 CODE_SEG SEGMENT USE16 'CODE' ASSUME CS:CODE_SEG,DS:DATA_SEG ASSUME SS:STACK_SEG 0000 MAIN PROC FAR 0000 В8 R MOV AX,DATA_SEG ; адрес сегмента данных - в DS и ES 0003 8Е СО MOV ES,AX 0005 8Е D8 MOV DS,AX 0007 FC CLD ; копировать данные 0008 BE 0000 R MOV SI,OFFSET LISTA 25 Загрузчик автоматически устанавливает значения регистров SS:SP и CS:1 Р. Регистры ES и DS после загрузки адресуют сегмент PSP. — Пер. 200 Гпава 4 СООВ BF 0064 В MOV DI,OFFSET LISTB иООЕ В9 0064 MOV CX,100 ООН F3/A4 REP MOVSВ 0013 В4 4С MOV AH,4CH ; выход в DOS 0015 CD 21 INT 21H 0017 MAIN ENDP 0017 CODE _SEG ENDS END MAIN Пример программы В примере 4.20 приведен листинг программы, с полным определением сегментов, для ввода символов с клавиатуры и отображения их на экране. Эла программа, хотя и тривиальна, представляет собой пример законченного приложения, работающего на всех персональных компьютерах IBM PC. Также здесь демонс*1 рнруек’я обращение к функциям DOS. (Справочник по функциям DOS. с указанием параметров вызова, см. в Приложении /.) Функции DOS обеспечивают работу с клавиатурой, принтером и дисками. Программа определена в виде дальней процедуры main. В программе используется только один сегмент — кодовый. Сегмент данных опущен, поскольку данные в памяти здесь не нужны. Сегмент стека также не определен, поскольку в данном случае достаточно пространства в 128 байт, распределяемого по умолчанию при загрузке. (Компоновщик выдаст предупреждение, что стек не определен.) Стек в этой иро-1раммс используется только при вызове функций DOS командой int 21н. Из функций DOS здесь использованы функции с номерами 06Н и 4СН. Номер функции загружается в регистр АН перед выполнением инструкции int нн. Функция 06Н при значении регистра DL = 0FFH опрашивает буфер ввода клавиазуры без ожидания нажатия клавиши. Если при завершении функции флаг Z = I, то буфер пуст. Если Z = 0, это означает, что символ прочитан и его ASCII-код сохранен в регистре AL. Ожидание нажатия клавиши в программе оформлено в виде цикла — загрузка регистров АН и DL и вызов прерывания INT 21Н выполняются до тех пор, пока флаг Z не обнулится. При вводе символа с клавиатуры программа выходит из цикла ожидания. Полученный в регистре AL код сравнивается с кодом символа @. Если коды различны, то программа выводит веденный символ на экран и возвращается к чтению очередного символа с клавиатуры. Если же была нажата клавиша @, то программа завершается. Функция 06Н при значении регистра dl не равного 0FFH отображает на экране ASCII-код, заданный в регистре. После вывода полученного символа выполняется инструкция jmp, и программа продолжается с адреса, указанного меткой main. При вводе символа @ программа переходит к метке maini, где запрограммирован вызов DOS-функции номер 4СН. Эта функция завершает программу. Дополни тельная информация об ассемблере содержится в Приложении /. (В Приложении / приведен полный перечень средств ассемблера и компоновщика, а также функций DOS и BIOS.) В последующих главах рассматривается применение ассемблера для решения различных типов задач. Инструкции передачи данных 201 Пример 4.20. Эхо-печать до нажатия клавиши @ 0000 CODE_SEG SEGMENT 'CODE' ASSUME CS:CODE_SEG 0000 MAIN PROC EAR 0000 В 4 06 MOV AH, 6 ; чтение символа с клавиатуры 0002 В2 ЕЕ MOV DL,0FEH 0004 CD 21 INT 21H 0008 74 F8 ЗЕ MAIN ; клавиша не нажата 0003 ЗС 40 CMP AL,'@' ; символ @? 000А 74 08 JE MAIN1 ; да 00GC В4 06 MOV AH, 6 ; отобразить символ 000Е 8А DO MOV DL, AL 0010 CD 21 INT 21H 0012 ЕВ ЕС JMP MAIN ; повторить 0014 MAIN1: 0014 В4 4 С MOV АН,4CH ; выход в DOS 0016 CD 21 INT 21H 0018 MAIN ENDP 0018 CODE SEG ENDS END MAIN В примере 4.21 приведена эта же программа с использованием модели памяти вместо полного определения сегментов. Сравните эти варианта и обратите внимание, насколько модель памяти может сократить текст программы26. Пример 4.21. Оформление программы эхо-печати при задании модели памяти .MODEL TINY 0000 . CODE .STARTUP 0100 MAIN: 0000 В4 06 MOV АН,6 ; чтение символа с клавиатуры 0002 В2 ЕЕ MOV DL,0FFH 0004 CD 21 INT 21H 0006 74 F8 JE MAIN ; клавиша не нажата 0008 ЗС 40 CMP AL, '@' ; символ @ ? ОООА 74 08 JE MAIN1 ; да 000С В4 06 MOV AH, 6 ; отобразить символ 000Е 8А D0 MOV DL,AL 0030 CD 21 INT 21H 0012 ЕВ ЕС JMP MAIN ; повторить 0014 MAIN1: .EXIT ; выход в DOS END 26 При разработке незривиальных программ эффект от применения моделей незначителен. — Пер. 202 Гпава 4 Итоги □ Инструкции передачи данных выполняют обмен данными между: • регистрами; • регистром и памятью; • регистром и стеком; • памятью и стеком; • аккумулятором и портом ввода-вы вода; • аккумулятором и регистром флагов; • регистром флагов и стеком. Передача данных из памяти в память выполняется только инструкцией movs. □ К инструкциям передачи данных относятся mov, push, pop. xchg, xlat, in, out, lea, LDS, LES, LSS, LGS, LFS, LAHF, SAHF, а ТаКЖС СТрОКОВЫе ИНСТРУКЦИИ LODS, STOS, MOVS, INS И OUTS. □ Первый байт машинной инструкции содержит код операции. Код операции определяет действие, выполняемое микропроцессором. Перед кодом операции может быть задан один или несколько префиксов. О Бит D в машинном коде инструкции определяет направление передачи данных. Если D = 0, то источник задан полем REG, а приемник — полем R/М. При D = I поле R/М обозначает источник, а поле REG -- приемник. □ Бит W определяет размерность данных. Если W = 0, то размерность — байт, а при W = 1 — слово. В процессорах 80386—Pentium 4 бит W = 1 означает слово пли двойное слово. □ Поле MOD определяет метод адресации в сочетании с полем R/М. Значение MOD = 00 говорит о том, что смещение при адресации данных в памяти отсутствует; при MOD = 01 смещение задано знаковым байтом; при MOD = 10 используется 16-битное смещение. Во всех лих вариантах поле R/М содержит информацию о методе адресации памяти. Код MOD = II означает регистровую адресацию, поле R/М при этом содержит код регистра. Код MOD =10 в процессорах 80386—Pentium 4 обозначает 32-битное смещение. □ Поля REG и R/М содержат трехбитный код регистра при MOD =11. Всего имеется три группы по 8 регистров разной размерности, а именно — байт (АН, AL. ВН, BL, СН, CL, DH и DL), 16-битное слово (АХ, ВХ, СХ, DX, SP, ВР, DI и S1) и 32-битное двойное слово (ЕАХ, ЕВХ, ЕСХ, EDX, ESP, EBP. EDI и ESI). □ Если поле MOD задает адресацию данных в памяти, то значения REG и R/M выбирают один из следующих режимов адресации (в 16-битном режиме): (bx+di], [Bx+si], [bp+di], [bp+si], [вх], [вр], [di] или [si]. В процессорах 80386—Pentium 4 поле R/М содержит код 32-битного регистра (ЕАХ, ЕВХ, ЕСХ, EDX, EBP, EDI или ESI) либо одного из режимов индексной адресации памяти с масштабированием. При выборе последней (R/M = 100) инструкция содержит дополнительный байт (байт масштаба-индекса-базы) для задания базового и индексного регистров и масштабного коэффициента. Инструкции передачи данных 203 □ При адресации памяти процессор выбирает сегмент данных, по умолчанию. Исключение составляет косвенная адресация с использованием регистра ВР или ЕВР. В этом случае используется сегмент стека. □ Копирование сегментных регистров выполняется только командами mov, push, и pop. Инструкция mov позволяет обменивать данные между сегментным регистром и любым 16-битным регистром общего назначения. Инструкции mov cs,reg и pop cs недопустимы, поскольку их выполнение привело бы к изменению части полною адреса следующей инструкции. В процессорах 80386—Pentium 4 имеются дополнительные сегментные регистры FS и GS. □ Для передачи данных между регистром/памятью и стеком предназначены инструкции push и pop. Команда push также допускает запись в стек непосредственных данных. Команды push и pop позволяют передавать данные между стеком и регистром флагов, сохранять и восстанавливать все 16- или 32-битныс регистры общего назначения. В стек может быть записано только слово или двойное слово. При записи в стек 16-битного слова наиболее значимый байт помещается по адресу SP - 1, а наименее значимый — по адресу SP - 2. После записи содержимое SP уменьшается на 2. В процессорах 80386—Pentium 4 введены варианты команд push/pop для копирования 4-байтных двойных слов. □ Команды pushf и popf выполняют обмен данными между регистром флагов и стеком. Инструкции pusha и рора сохраняют и восстанавливают все регистры общего назначения. В процессорах 80386—Pentium 4 для сохранения и восстановления 32-битного регистра флагов используются команды pushed и popfd. □ Инструкции lea, lds и les загружают адрес в регистр или в пару регистров. Команда lea записывает в произвольный 16-битный регистр смещение указанного объекта; lds и les загружают в 16-битный регистр и в DS или ES адрес из двойного слова в памяти. В процессорах 80386—Pentium 4 имеются дополнительные инструкции lfs, lgs и lss — для записи адреса в 16-битный регистр и сегментный регистр FS, GS ИЛИ SS. □ Строковые инструкции используют для адресации памяти регистры DI и/или S1. В SI указывается смещение источника в сегменте данных, а в DI — смещение приемника в дополнительном сегменте данных. □ Флаг направления D выбирает режим автоувеличения или автоуменьшения значений регистров DI/S1 при выполнении строковых инструкций. Режим автоувеличения включается при D = 0; для обнуления флага D используется инструкция cld. При выполнении инструкции std устанавливается режим автоуменьшения (D = 1). Регистр DI и/или SI при выполнении строковой операции нал байтом, словом или двойным словом уменьшается или увеличивается, соответственно, на 1, 2 или 4. □ Команда lods загружает в регистр AL, АХ или ЕАХ данные, расположенные в сегменте данных по смещению SI; инструкция stos сохраняет AL, АХ или ЕАХ в дополнительном сегменте данных по смещению DI; инструкция movs передает байт, слово или двойное слово из памяти по адресу DS:SI в память по адресу ES:DL □ Инструкция ins вводит данные из порта ввода-вывода, адресуемого регистром DX, и сохраняет их в памяти по смещению D1. Инструкция outs считывает данные из памяти по смешению SI и передает их в порт по адресу DX. 204 Гпава 4 □ Перед строковой инструкцией может быть задан префикс rep — для повторного выполнения инструкции. Число повторений определяется значением регистра СХ. О В языке ассемблера используются константные выражения с операторами арифметических и логических действий. Пример: команда mov ах,34*3, которая записывает в регистр АХ число 102. О Команда перекодировки xlat записывает в регистр AL значение из таблицы, адресуемое суммой регистров ВХ и AL. О Команды in и оит передают данные между регистром AL, АХ или ЕАХ и портом или портами ввода-вывода. Номер порта в командах in и out может быть задан фиксированным (числом в диапазоне 0—0FFH) или переменным (в регистре DX). □ Начиная с процессоров Pentium Pro и Pentium II, в систему команд включена Iрупиа инструкций условной передачи данных — cmov. Инструкция cmovcc передает данные при выполнении условия сс. □ Префикс переназначения сегмента позволяет изменить сегментный регистр, используемый по умолчанию при обращении к памяти. Например, при выполнении инструкции mov ах, [вх] процессор использует сегмент данных, а при выполнении команды mov ax,es:[bx] он обращается к дополнительному сегменту данных, назначенному префиксом es. Сегментные регистры FS и GS процессоров 80386—Pentium 4 используются лишь при задании одноименных префиксов переназначения; никакая команда нс использует их но умолчанию. □ Команды movzx и movsx, доступные в процессорах 80386 и выше, позволяют расширить размерность данных при копировании от 8/16 до 16/32 бит. Команда movzx заполняет старшие биты приемника нулями, a movsx — значением знакового бита источника. □ Директивы db, dw и dd совместно с dup применяются для определения данных в памяти. П Директива эквивалентности equ вводит новое имя, значение и тип которого совпадают со значением и типом указанного выражения. П При полном описании сегментов начало сегмента задается директивой segment, а его окончание — директивой ends. Cl Директива assume устанавливает соответствие между именами программных сегментов и сегментными регистрами CS, DS, ES и SS при полном определении сегментов. Для процессоров 80386—Pentium 4 директива assume также может определять назначение сегментных регистров FS и GS. П Директивы proc и endp отмечают начало и конец процедуры. Атрибут uses директивы proc, доступный в MASM 6.л\ предписывает ассемблеру генерировать команды для сохранения в стеке указанных регистров — при входе в процедуру, и для их восстановления — при выходе. □ По умолчанию ассемблер предполагает, что программа написана для процессора 8086/8088. Чтобы воспользоваться расширениями процессоров 80286—Pentium, следует указать в программе соответствующую директиву от .286 до .586. Если эта директива поставлена после оператора .model, ассемблер генерирует 16-бит- Инструкции передачи данных 205 ные инструкции, а если наоборот, то генерируются инструкции 32-битного режима. □ Модель памяти позволяет немного сократить исходный текст программы, но усложняет разработку больших программ. Контрольные вопросы I. Какая информация задана в первом байте инструкции, нс содержащей префиксов? 2. Какую информацию несут биты D и W машинного кода инструкции? 3. Какая информация содержится в поле MOD? 4. Какой регистр задан в команде, если REG — 010, W = 0, а режим инструкций — 16-битный9 5. Каким образом кодируется доступ к 32-битным регистрам в микропроцессоре 80486? 6. Какой метод адресации памяти выбран, если R/M = 001, MOD = 00, а режим инструкций — 16-битный? 7. Какой сегментный регистр используется по умолчанию при косвенной адресации через регистр: a) SP б) ЕВХ в) DI г) ЕВР д) SI 8. Какая инструкция кодируется 16-бигным числом 8В07Н? 9. Какая инструкция закодирована числом 8В1Е004СН? 10. Как выглядит инструкция mov si, [вх<-2] в машинном представлении? 11. Каким кодом представлена инструкция MOV ESI, [ЕАХ] в микропроцессоре Pentium 11 при условии, что режим инструкций — 16-битный? 12. Почему инструкция mov CS, ах ошибочна? 13. Запишите последовательность команд для загрузки в сегментный регистр числа ЮООН. 14. Какова размерность данных инструкций PUSH и POP для процессоров 8086—80286? 15. Какой сегментный регистр нельзя указывать в команде pop? 16. Какие регистры сохраняются в стеке командой PUSHA? 17. Какие регистры сохраняются в стеке командой PUSHAD? 18. Опишите действие следующих инструкций: a) push ах б) POP ESI В) PUSH [ВХ] Г) PUSHED л) POP DS С) PUSHD 4 19. Объясните, что происходит при выполнении инструкции PUSH вх. По каким адресам в памяти сохраняются регистры ВН и BL. если SP = 0100Н, a SS = 0200Н? 20. Что происходит при выполнении инструкции push ЕАХ. Куда записываются составляющие регистра ЕАХ, если значение регистра SP = 01 ООН, a SS = 0200Н? 206 Гпава 4 21. На сколько увеличивается значение регистра SP при выполнении 16-битной инструкции POP? 22. Назовите одно из возможных сочетаний значений регистров SP и SS, если вершина стека находится по адресу 02200Н? 23. В чем разница между инструкциями MOV DI,NUMB и LEA DI,NUMB? 24. Какая команда более эффективна — MOV с оператором offset или lea? 25. В чем разница между инструкциями MOV SI,OFFSET NUMB 11 LEA SI,NUMB? 26. Опишите действие инструкции lds BX,numb. 27. В чем разница между инструкциями lds и LSS? 28. Запишите последовательность инструкций для передачи слов, расположенных в сегменте данных по смещениям numb и NUMB+1, в регистры ВХ, DX и SI. 29. Для чего предназначен флаг направления? 30. Какие инструкции устанавливают и сбрасывают флаг направления? 31. В каких сегментах находятся операнды строковых инструкций, адресуемые регистрами DI и Si? 32. Объясните действие инструкции LODSB. 33. Объясните действие инструкции stosw. 34. Объясните действие инструкции OUTSB. 35. С какими командами используется префикс rep и для чего он предназначен? 36. Напишите последовательность команд для копирования 12 байт из массива SOURCE в массив dest, в предположении, что флаг направления D = 0. 37. Где находится информация о номере порта для команды INSB? 38. Запишите инструкцию для обмена содержимого регистров ЕВХ и ESI. 39. Какая из инструкций LAHF и SAHF применяется при разработке программ в настоящее время? 40. Объясните, как инструкция xlat изменяет содержимое регистра AL. 41. Напишите короткую программу с использованием инструкции XLAT для преобразования BCD-чисел 0—9 в коды ЗОН—39Н. Поместите таблицу перекодировки в сегмент данных по смешению table. 42 Объясните действие инструкции in al, 12Н. 43. Объясните действие инструкции out dx,ax. 44. Для чего используется префикс переназначения сегмента? 45. Запишите инструкцию для записи в регистр АН байта, расположенного в памяти по адресу, заданному регистром ВХ. 46. Запрограммируйте обмен содержимого регистров АХ и ВХ, ЕСХ и EDX, S1 и DI. 47. Объясните действие инструкции процессора Pentium Pro cmovne cx,dx? 48. Какая директива позволяет запрограммировать команду CMOVNS ЕСХ, ЕВХ, если ассемблер нс поддерживает набор команд Pentium Pro? 49. Какую функцию выполняют директивы ассемблера? 50. Для чего предназначены директивы DB, DW и DD? 51. Напишите директиву, которая резервирует 30 байт памяти для массива LIST1. 52. Для чего предназначена директива EQU? 53. Для чего предназначена директива .386? Инструкции передачи данных 207 54. Для чего предназначена директива .model? 55. Если начало сегмента задано директивой .data, какой вариант организации памяти используется в данном случае? 56. Если начало сегмента задано директивой segment, какая организация памяти используется в данном случае? 57. Какую функцию выполняет команда INT 21Н при значении регистра АН = 4СН? 58. Какими директивами обозначаются начало и конец процедуры? 59. Объясните смысл атрибута USES директивы PROC в MASM 6.x. 60. Как задать ассемблеру режим генерирования 16-битных инструкций при использовании команд микропроцессора Pentium П? 61. Разработайте ближнюю процедуру, которая копирует содержимое регистра AL в четыре смежных ячейки памяти, расположенные в сегменте данных со смещением DI. 62. Разработайте дальнюю процедуру, которая записывает в регистры АХ, ВХ, СХ, DX и SI содержимое слова, расположенного в памяти по адресу CS:DATA1. ГЛАВА 5 Арифметические и логические инструкции Введение В этой главе мы рассмотрим арифметические и логические инструкции. К арифметическим инструкциям относятся сложение, вычитание, умножение, деление, сравнение. инвертирование, инкремент и декремент. Логические инструкции включают в себя операции "И" (and), "ИЛИ" (gr), "Исключающее ИЛИ" (xor), отрицание (not). сдвиги, циклические сдвиги, а также логическое сравнение (test). В системе команд процессоров 80386—Pentium 4, кроме того, имеются инструкции xadl. shri>, shlp, команды проверки и поиска бит. В этой главе также рассмотрены строковые инструкции сравнения, используемые для поиска по таблицам (scas) и поэлементного сравнения массивов (cmps). Если вы знакомы с 8-битными микропроцессорами, вы обнаружите, что система команд процессоров 8086—Pentium 4 гораздо более гибкая, поскольку большинство инструкций оперирует не с одним, а с двумя операндами. Но даже если вы только приступаете к изучению микропроцессоров, вы с легкостью освоите простые и удобные арифметические и логические команды процессоров 8086—Pentium 4. Темы главы В этой главе рассмотрены следующие вопросы: □ использование арифметических и логических инструкций для выполнения элементарных операций двоичной, BCD- и ASCII-арифметики; □ применение машинных операций and, or и xor для обработки бит; □ инструкции сдвигов и циклических сдвигов; □ инструкции, специфические для процессоров 80386—Pentium 4: обмен со сложением. сравнение с обменом, сдвиги удвоенной точности, проверка биг и поиск бит: □ проверка содержимого таблиц посредством строковых инструкций сравнения и поиска. 5.1. Сложение, вычитание и сравнение Практически в любом микропроцессоре имеются инструкции сложения, вычитания и сравнения — их мы рассмотрим в этом разделе, с примерами. Арифметические и логические инструкции 209 Сложение Инструкция сложения (add) реализована в самых разнообразных формах. В этом разделе подробно рассмотрены инструкции add для сложения 8-, 16- и 32-битных двоичных данных, а также инструкция adc, позволяющая при сложении учитывать перенос1. Для прибавления единицы в систему команд включена инструкция инкремента (enc). Также предусмотрены команды для сложения данных в форматах BCD и ASCII. В завершение этой темы мы рассмотрим инструкцию xadd процессоров 80486—Pentium 4. Методы адресации, доступные в инструкциях add, проиллюстрированы примерами в табл. 5.1. Здесь использованы почти все методы, рассмотренные в главе 3. (Конечно, все варианты адресации, число которых составляет около 32000, продемонстрировать невозможно.) В командах add запрещена адресация память-память; также недопустимо задание в качестве операнда сегментного регистра. Вообще для сегментных регистров возможны только операции копирования, сохранения в стеке и восстановления из стека. Заметим также, что 32-битные регистры доступны только в процессорах 80386—Pentium 4. Таблица 5.1. Инструкции сложения Команда Действие ADD AL,BL AL = AL + BL ADI? CX,DI CX = CX + DI ADD EPP,EAX EBP = EBP + EAX ADD CL,44H CL = CL + 44H ADD BX,245FH BX = BX + 245FH ADD EDX,12345H EDX = EDX + 00012345H ADD [BX],AL Прибавление содержимого регистра AL к байту, расположенному в сегменте данных по смещению, указанному в регистре ВХ, с сохранением суммы в том же байте ADD CL,[BP] Прибавление к содержимому регистра CL байта из сегмента стека по смещению, указанному в регистре ВР, с записью суммы в CL ADD AL,[EBX] Суммирование содержимого регистра AL с содержимым сегмента данных по смещению, указанному в ЕВХ, с записью суммы в регистр AL ADD BX,[SI + 2] Прибавление к содержимому регистра ВХ слова из сегмента данных по смещению SI + 2, с сохранением результата в ВХ ADD CL,TEMP Суммирование байта из сегмента данных по смещению temp с содержимым регистра CL, с записью результата в CL ADD BX,TEMP[DI] Сложение слова, расположенного в сегменте данных по смещению temp + Di, с содержимым регистра ВХ; результат записывается в ВХ * Используется при сложении данных многократной точности, поскольку даст возможность учесть перепое, возникший в результате предыдущего сложения. — Пер. 210 Г~ Таблица 5.1 (окончат*) Команда Действие ADD [ВХ + DI],DL Прибавление содержимого регистра DL к содержимому сегме* данных по смещению ВХ + DI, с сохранением результата в сегм * те данных ADD BYTE PTR [DI] , 3 Прибавление числа 3 к байту из сегмента данных по смещенц указанному в регистре DI *0, ADD ВХ,[EAX + 2+ECX] Сложение слова, расположенного в сегменте данных по смеш». нию ЕСХ*2 + ЕАХ, с содержимым регистра ВХ; сумма сохраняете в ВХ Сложение при регистровой адресации В примере 5.1 приведена простая процедура, в которой слагаемые заданы регистровыми операндами. В этом примере суммируется содержимое регистров АХ, ВХ, СХ и DX; 16-битный результат формируется в регистре АХ. Пример 5.1. Сложение содержимого регистров АХ, ВХ, СХ и DX 0000 ADDS PROC NEAR 0000 03 СЗ ADD АХ,ВХ 0002 03 Cl ADD AX,CX 0004 03 C2 ADD AX,DX 0006 C3 RET 0007 ADDS ENDP Арифметические и логические операции всегда оказывают воздействие на регистр флагов. Флаги прерывания и трассировки остаются прежними; изменяются биты младшего байта регистра флагов, а также флага переполнения. В частности, инструкции add модифицируют содержимое флагов знака, нуля, вспомогательного переноса, переноса, паритета и переполнения. Заметим, что при выполнении большинства инструкций передачи данных, рассмотренных в главе 4, никакие флаги не из меняются. Сложение при непосредственной адресации Непосредственная адресация применительно к командам add означает сЛ°ЖС^т с константой. Байтовое сложение с непосредственным операндом иллюстр пример 5.2. В этом примере в регистр DL сначала загружается число 12Н му помощи команды пересылки с непосредственной адресацией. Затем к содер*и регистра DL прибавляется 33Н — командой сложения, также с неп1среДмСТуД>наГ операндом. Результат сложения (45Н) сохраняется в регистре DL, а флаги У ливаются следующим образом: □ Z = 0 (результат не ноль) □ С = 0 (нет переноса) фактические и логические инструкции 211 0 CJ CJ 0 . ₽ 0 (вспомогательный перенос отсутствует) А $ = О (результат — положительное число) р 0 (нечетный паритет) О = О (мег переполнения) Пример 5’2’ Сложение чисел и ЗЗН R^ 12 DL' 12Н ОООб В" ло riO С 2 33 ADD DL,33H 0008 Сложение данных в памяти и в регистре g примере 5-3 приведен листинг программы получения суммы двух байтов, расположенных в сегменте данных по смещениям numb и numb+i; результат сохраняется в регистре AL. | Пример 5.3. Суммирование двух байтов памяти с сохранением результата в AL ; Процедура для сложения Сайтов NUMB и NUMBH ; Результат -- в регистр AL ; Изменяет содержимое регистра DI 0000 SUMS PROC NEAR 0000 BE 0000 в. MOV DI,OFFSET NUMB ; смещение NUMB 0003 во 00 MOV AL, 0 ; обнуление суммы 0005 02 05 ADD AL,[DI] ; прибавить NUMB 0007 02 45 01 ADD AL, [DI + 1] ; прибавить NUMB+1 00ОА СЗ RET ооов SUMS ENDP Процедура Регистр DI индексный регистр DI смещение numb. Через sums сначала загружает в выполняется доступ к данным в сегменте данных, по смещениям numb и Заметим, что загрузка смещения в самой процедуре — не лучшее решение; Ычно адрес устанавливают перед вызовом процедуры — до оператора call. После гРУзки адреса в регистр DI выполняется инструкция add al, [di], она прибавляет к д^ИстРУ AL содержимое байта памяти по смещению numb. Предварительно регистр соде°^НУЛЯеТСИ‘ СледУюшая инстРУкпия сложения — add al, [di+1] — прибавляет к рс^РЖим°му регистра AL содержимое байта памяти по смещению мимв+1. В итоге, ЯмжСТр AL содержит сумму байтов, расположенных в сегменте данных по смещени-И NUMB+1. *ение элементов массива * 9. в . . . Чц, примере 5.4 приведена процедура, выполняющая суммирование элементов с Рами 3, 5 и 7. это список данных, расположенных в памяти последовательно. Предпо-что имеется массив array, состояний! из 10 байт, пронумерованных от О 212 Пример 5.4. Суммирование отдельных элементов массива ; процедура для сложения элементов 3, 5 и 7 массива ARRAY ; Результат - в регистр AL ; Использует регистр SI (изменяет его содержимое без восстановления) эоОС SUM PROC NEAR 0000 ВО 00 MOV AL,0 ; обнулить сумму 000/? BE 0003 MOV SI,3 ; смещение третьего элемента 0065 02 84 0002 R ADD AL,ARRAY[SI] ; прибавить третий элемент 0009 02 84 0004 R ADD AL,ARRAY[S1+2] ; прибавить пятый элемент 00UD 02 84 0006 R ADD AL,ARRAY[S1+4] ; прибавить седьмой элемент ООП СЗ RET 0012 SUM ENDP В этом примере сначала обнуляется сумма в регистре AL. Затем в регистр SI записывается номер третьего элемента массива. Инструкция add al, array [si ] прибавляет содержимое этого элемента к al. Последующие инструкции добавляют к al значения пятого и седьмого элементов; смещение для доступа к этим элементам задано относительно индекса в si (= 3) — как si + 2 (= 5) и si + 4 (= 7). Предположим, что массив содержит 16-битные данные, и требуется сформировать в регистре АХ 16-битную сумму элементов 3, 5 и 7. В примере 5.5 приведена процедура, написанная для процессоров 80386—Pentium 4 с использованием индексной адресации с масштабированием. В регистр ЕВХ загружается адрес array, номер текущего элемента массива формируется в ЕСХ. Масштабный коэффициент 2 удваивает смещение, заданное в регистре ЕСХ, что позволяет обращаться к двухбайтному элементу массива по его номеру. Пример 5.5. Сложение элементов массива слов ; Процедура для сложения элементов массива с номерами 3, 5 и 7 ; Результат - в регистр АХ ; Изменяет содержимое регистров ЕВХ и ЕСХ 0000 SUM PROC NEAR 0000 661 BB 00000000 R MOV EBX,OFFSET ARRAY ; смещение ARRAY 0006 66| B9 00000003 MOV ECX, 3 ; номер элемента 3 ОООС 67& 8B 04 4B MOV AX,[EBX+2*ECX] ; прибавить элемент 3 0010 66| B9 00000005 MOV ECX, 5 ; номер элемента 5 0016 67& 03 04 4B ADD AX,[EBX+2*ECX] ; прибавить элемент 5 001A 66| B9 00000007 MOV ECX, 7 ; номер элемента 7 0020 67ir 03 04 4B ADD AX,[EBX+2*ECX] ; прибавить элемент 7 0024 C3 RET 0025 SUM ENDP Инкремент Команда инкремента inc увеличивает на 1 содержимое регистра, за исклю4 сегментного, или ячейки памяти. В табл. 5.2 приведены примеры инструкиИ для процессоров 8086—Pentium 4. ^метические и логические инструкции 213 Таблица 5.2. Инструкции inc ^н/7 Действие BL = BL + 1 iNCSF SP=SP+1 iKC FAX ЕАХ = ЕАХ + 1 tnc ртк 1ВД Увеличивает на 1 байт по смещению ВХ inc word PTR Увеличивает на 1 слово из сегмента данных по смещению SI inc DWOPr ptr [ЕСХ] Прибавляет 1 к двойному слову по смещению ЕСХ tnc data’ Инкрементирует данные по смещению datai При косвенно!! адресации в командах inc необходимо указывать размерность данных посредивом директив byte ptr, word ptr или dword ptr. Иначе ассемблер не может определить размерность операции. Например, инструкция inc [di] может относиться к байту, слову или двойному слову. Напротив, команда inc byte pi’r [di] определенно указывает на байт в памяти, inc word ptr [di] — на слово, a inc dword ptr [Di] — на двойное слово. В примере 5.6 приведен вариант программы из примера 5.3 с использованием инструкции инкремента для адресации байтов numb и numbh. Инструкция inc di изменяет содержимое регистра D1 так, что этот регистр указывает на байт, следующий за байтом numb. ; Пример 5.6. Процедура из примера 5.3 с использованием команды inc i........................................................... ; Процедура для сложения байтов NUMB и NUMB+1 '• Результат в регистр AL ' Изменяет содержимое регистра DI 0000 SUMS PROC NEAR 0000 ВЕ ООО 0 R MOV DI,OFFSET NUMB ; смещение NUMB °°03 BU со 0005 02 05 MOV AL, 0 ; обнуление суммы ADD AL,[DI] ; прибавить NUMB 000? 4? INC DI ; смещение NUMB+1 0008 Op с5 000д соз °00в ADD RET SUMS ENDP AL,[DI] ; прибавить NUMB+1 *НетРУкция inc воздействует на флаги процессора, но, в отличие от команды сло-уКа^151, Не изменяет флаг переноса. Эта команда часто используется для установки ^о'.ате'г,я ,,а следующий элемент массива байт. При работе с массивами слов для Исли применяют команду add di,2 — этот вариант предпочтительней использо-УКцИЯ Двух команд INC DI- При работе с массивами двойных слов для модификации ЧСн3ите;1я используется команда add di,4. В некоторых случаях, когда при увели-указателя требуется сохранить исходное значение флага переноса, команда ^Меняется последовательностью двух или четырех команд inc. 2™_______________________________________________________________2jaeaS ^****«*. Сложение с переносом Команда сложения с переносом (adc) не юлько суммирует операнды, но и прибав ляет к результату значение флага переноса (С). Эта инструкция используется, в ос' пивном, при обработке данных, размерность которых превышает 16 бит (на процес' сорах 8086—80286) или 32 бита (на процессорах 80386—Pentium 4). Примеры инструкций adc приведены в табл. 5.3. Инструкция adc модифицируй (|viani таким же образом, как add. Таблица 5.3. Инструкции adc Команда Действие ADC АС,АН ADC СХ,ВХ AL = AL + АН + перенос СХ = СХ + ВХ + перенос adc евх,edx ЕВХ = ЕВХ + EDX + перенос ADC DH,[ВХ] Прибавляет к содержимому регистра DH байт из сегмента данных по смещению, указанному регистром ВХ, и значение переноса, сохраняя результат в регистре DH ADC ВХ, i ВР + 2] Прибавляет к регистру ВХ значение слова, расположенного в сегменте стека по смещению вр + 2, а также значение флага переноса АВС ЕСХ,[ЕВХ] Суммирует значения содержимого регистра ЕСХ, флага переноса и двойного слова из сегмента данных по смещению, указанному регистром ЕВХ; результат записывает в регистр ЕСХ Рассмотрим сложение 32-битных данных в процессоре 8086—80286. Пусть одно из 32-битных чисел задано в паре регистров ВХ и АХ, а второе — в регистрах DX и СХ. Иллюстрация сложения данных удвоенной размерности приведена на рис. 5.1. Рис. 5.1. Использование 16-битных команд ADD и ADC для 32-битного сложения суМ' Процедура для решения этой задачи приведена в примере 5.7. Эта проиеДУР^ (|арс ми руст данные в парах регистров ВХ—АХ и DX—СХ, формируя результат 215 арифметические и логические инструкции еГпстров ВХ—АХ. Сначала выполняется сложение содержимого регистров АХ и поскольку в них хранятся наименее значимые части слагаемых. В результате с/10ж^ния может возникнуть перенос. Перенос отражается во флаге С — он устанавливается в 1, если результат превышает предел FFFFH. Если сумма меньше этого предела, то флаг С обнуляется. Команда adc, при сложении наиболее значимых |6-би1иых составляющих данных, учитывает наличие переноса, который мог возникнуть при выполнении предыдущей команды add. Пример 5.7. 32-битное сложение в процессоре 8086/8088 0000 SUM32 PROC NEAR 0СОО 0 3 Cl ADD АУ.,СХ 0002 13 DA ADC BX, DX 0004 03 RET 0005 SUM32 ENDP Напишем аналогичную процедуру для процессора 80386—Pentium 4, предназначенную для суммирования 64-битных данных. Вместо 16-битных регистров воспользуемся 32-битными. Процедура приведена в примере 5.8. Пример 5.8. Сложение 64-битных данных в процессоре 80386—Pentium 4 ; Процедура суммирует 64-б’лтные данные, находящиеся в парах регистров ; ЕВУ.-ЕАХ и EDX-EUX ; Результат - в паре регистров ЕВХ-ЕАХ 0000 SUM64 PROC NEAR 0000 66| 03 С1 ADD EAX, ECX 0003 66| 1 3 DA ADC EBX,EDX 0006 С' RET 0007 SUM64 ENDP Команда обмена и сложения в процессорах 80486—Pentium 4 h ° систему команд процессора 80486 была включена новая команда обмена и сложения (xadd). Инструкция xadd складывает содержимое источника и приемника, сохраняя результат в приемнике. В отличие от других команд сложения, после сохра-НеНия результата исходное значение приемника копируется в источник. Команда xadd — одна из немногих инструкций, модифицирующих значение источника. Н' ‘Пример, если содержимое регистра BL = 12Н, a DL = 02Н, то в результате вы-°Лнения команды xadd bl,dl регистр BL содержит сумму (14Н), а регистр DL— х°Дное значение приемника (12Н). Эта команда реализована для регистров и дан-х в памяти любой размерности — 8, 16 и 32 бит. Считание РУкния вычитания (sub) предусмотрена для всех методов адресации и для дан-1ц Размерностью 8, 16 и 32 бит. Для уменьшения данных на единицу предназначе-к°Манда декремента dec. Также реализованы команды для вычитания BCD- и 216/лаааб ASCH-данных. Для обработки данных многократной размерности в систему команд введена инструкция вычитания с заемом — ивв. В табл. 5.4 приведены примеры инструкций вив. В этих инсзрукциях допускаются любые методы адресации; недопустимо задание обоих операндов в памяти, сегментный регистр также не может быть операндом команды вычитания. Подобно большинству арифметических инструкций, команда sub воздействует на флаги процессора. Таблица 5.4. Инструкции вычитания Команда Действие SUB CL, BL CL = CL-BL ’ SUB AX,SP AX = AX - SP SUB ЕСХ,EBP ECX = ECX - EBP SUB Did, cFH DH = DH-6FH SUB AX,0CCCCH AX = AX - CCCCH SUB ESI,2000300H ESI = ESI - 2000300H SUE [DI],CH Вычитает содержимое регистра CH из слова, расположенного в сегменте данных по смещению DI SUB CH,[BP] Вычитает байт, находящийся в сегменте стека по смещению ВР, из содержимого регистра СН SUE AH,TEMP Вычитает байт, расположенный в сегменте данных по смещению temp, из регистра ан SUB DI,TEMP[ESI] Вычитает из содержимого регистра DI слово, хранящееся по смещению temp + ESI SUB ECX,DATA1 Вычитает из содержимого регистра ЕСХ двойное слово, находящееся в сегменте данных по смещению datai Вычитание при регистровой адресации В примере 5.9 приведена последовательность инструкций вычитания с регистровыми операндами. В этом примере 16-битное содержимое регистров СХ и DX вычитается из содержимого регистра ВХ. После каждого вычитания микропроцессор модифицирует значения флагов. ......................................................................... Пример 5.9. Пример вычитания с регистровыми операндами ......2 0000 2В D9 0002 2В DA SUB ВХ,СХ SUB ВХ, DX Вычитание непосредственного значения В примере 5.10 приведены инструкции, вычисляющие разность чисел 22Н И Число 22Н загружается в регистр СН при помощи инструкции пересылки с исП дриФметические и логические инструкции 217 (.hiiicm непосредственной адресации. Затем выполняется команда sub с непосред-с11ным операндом 44Н. Полученная разность между 22Н и 44Н сохраняется в llicipc СН. Флаш после команды sub установлены следующим образом: Z 0 (результат не ноль) JOIT СТНе ре г а о С = I (зием) £1 д = I (полуперенос) 0 s = I (результат отрицательный) g р = I (четный паритет) g О -- 0 (нет переполнения) Пример 5.10. Вычитание непосредственного значения 0000 Вг 22 MOV СН,22Н 0002 80 ED 44 SUB CH,44Н Флаги переноса (С и А) после вычитания содержат значения заемов. Заметим, что в приведенном примере переполнения не возникает. Результат вычитания числа 44Н (+68) из 22Н (+34) равен 0DEH (-34) — это значение находится в диапазоне знаковых байтов, поэтому переполнения нет. Переполнение при 8-битных данных возникает, если результат больше +127 или меньше -128. Декремент Инструкция декремента (dec) вычитает I из регистра или содержимого памяти. В табл. 5.5 приведены примеры использования инструкции dec. Таблица 5.5. Инструкции декремента Команда Действие DEC ВЫ BH = BH - 1 dec сх сх = СХ - 1 DEC EDX EDX = EDX - 1 dec byte ptr [di] Вычитает 1 из содержимого байта, расположенного в сегменте дан- dec word ptr[bp] ных по смещению, указанному в регистре DI Вычитает 1 из содержимого слова, находящегося в сегменте стека по смещению, указанному в регистре ВР °Ec d;vORD ptrfebx] Вычитает 1 из двойного слова по смещению, указанному в регистре ^гглчв ЕВХ Вычитает 1 из содержимого сегмента данных по смещению numb ^Кт Косве,,но” адресации памяти в инструкции dec приходится использовать ди- BYTE PTf< word ptr или dword ptr, иначе ассемблер не может определить ерность данных. Например, инструкция dec [si] неоднозначна, поскольку ре- 218 г метр SI может указывать на байт, на слово или на двойное слово. Размерность ных становится ясной, если записать лу команду как dec byte pi*r [si] dec WORD PTR [DI], или DEC DWORD PTR [SI]. Дан-или Вычитание с заемом Инструкция вычитания с заемом (sbb) подобна обычной инструкции сив, но при вычитании учитывается также заем, зафиксированный во флаге переноса С. Чаще всего эта команда применяется при вычитании данных многократной размерности — длиннее I6 (для процессоров 8086—80286) или 32 бит (для процессоров 80386—Pentium 4). При вычитании таких составных данных требуется распространять заем между их частями, подобно тому, как в командах сложения (add/adc) распространяется перенос. Примеры инструкций sbb приведены в табл. 5.6. Инструкция sbb модифицирует флаги так же, как sub. Обратите внимание, что вычитание непосредственного значения при косвенной адресации вычитаемого требует уточнения размерности директивой BYTE PTR, WORD PTR ИЛИ DWORD PTR. Таблица 5.6. Инструкции вычитания с заемом Команда Действие SBB AH,AL AH = AH - AL - перенос SBB АХ,ВХ AX = AX - ВХ - перенос SBB ЕАХ, ЕСУ. ЕАХ = EAX - ECX - перенос SBB CL, 2 CL = CL - 2 - перенос SBB BYTE PTR[DIj,3 Вычитает из байта по смещению, указанному в регистре DI, число 3 и значение флага С SBB [DI],AL Вычитает из байта по смещению, указанному в регистре DI, содержимое регистра AL и значение флага С SBB DI,[BP т 2] Уменьшает содержимое регистра DI на величину флага С и на величину 16-битного слова из сегмента стека по смещению ВР + 2 SBB AL, [EBX + ECX] Вычитает из содержимого регистра AL содержимое байта, расположенного в сегменте данных по смещению ЕВХ + ЕСХ, и значение заема - Предположим, что в паре регистров ВХ и АХ находится 32-битное число, а в па^ регистров SI и DI — другое 32-битное число. Использование заема (флага С) вычитании 16-битных составляющих иллюстрирует рис. 5.2. В примере 5.11 приведен листинг вычитания 32-битных данных при помощи 16-ных команд. Сначала выполняется вычитание наименее значимых 16-битнЫ* ставляющих — командой sub. При вычитании следующих частей данных исп ется команда sbb. В примере команда sub вычисляет разность между знамен регистров АХ и D1; затем команда sbb вычитает с заемом содержимое регистр из ВХ. дриФмеТИЧеСКИв И логические инструкции 219 Листинг 5.11. Вычитание данных удвоенной размерности 0004 2В С7 0006 IB DE SUB АХ,DI SBB BX,SI Сравнение Инструкция сравнения (смр) выполняет вычитание, не изменяя значение приемника, — только для установки флагов. Сравнение позволяет оценить соотношение между значением регистра или данных в памяти и другим значением. За командой сир обычно следует условная команда, позволяющая принять решение по результату сравнения, отраженному в регистре флагов, — например, команда условного перехода. В табл. 5.7 приведены примеры инструкции сравнения с использованием методов адресации, доступных в командах сложения и вычитания. Так же, как и для этих команд, для сравнения нельзя задавать сегментный регистр, и только один из операндов может находиться в памяти. Таблица 5.7. Инструкции сравнения Команда СНР CL.BL АХ, SP ebp,es1 СМР АХ,2000Н 'Dll ,СН Действие CL-BL AX-SP EBP-ESI АХ - 2000Н Вычисление разности между байтом по смещению, указанному Cl- [ВР] в регистре DI и регистром СН Вычисление разности между регистром CL и байтом в сегменте стека по смещению, указанному в регистре ВР 220________________________________________________________________________Гпавах Таблица 5.7 (окончание) Команда Действие СМР АН,TEMP Вычисление разности между содержимым регистра АН и байтом в сегменте данных по смещению temp СМР D1,TEMP[BX] Вычисление разности между содержимым регистра DI и словом по смещению temp + ВХ СМР AL,[EDI + ESI] Вычисление разности между содержимым регистра AL и байтом из сегмента данных по смещению EDI + ESI В примере 5.12 приведен листинг, сочетающий команду сравнения и условного перехода. Здесь содержимое регистра AL сравнивайся с числом ЮН. Затем выполняется переход по условию больше или равно (беззнаковое). Переход на метку sober произойдет, если содержимое регистра AL будет больше или равно ЮН. При сравнении беззнаковых чисел также используются условные переходы jb (jump below — переход, если меньше), ja (jump above — переход, если больше) и jbe (jump below or equal — переход, если меньше или равно) — мы подробно рассмотрим их в главе 6. Пример 5.12. Условный переход после сравнения 0000 ЗС 10 CMP AL, ЮН 0002 73 1С JAE SUBER ; сравнить AL с ЮН ; переход, если AL >= ЮН Инструкция сравнения и обмена в процессорах 80486—Pentium 4 Инструкция сравнения и обмена cmpxchg, имеющаяся в процессорах 80486—Pentium 4, сравнивает приемник с аккумулятором. Если они равны, то источник копируется в приемник; а если не равны, то приемник копируется в аккумулятор. Эта инструкция реализована для 8-, 16-и 32-битных данных. Например, инструкция cmpxchg cx,dx сравнивает содержимое регистра СХ с АХ. Если СХ = АХ, то в регистр АХ передается значение DX; если же содержимое регистра СХ отличается от АХ, то в АХ копируется значение СХ. Если операнды байтовые, то подразумевается регистр AL, а если данные 32-битные — ЕАХ. В процессорах Pentium—Pentium 4 имеется также инструкция cmpxchgbb для сравнения пары 8-байтных слов. Эта команда сравнивает 64-битные числа, одно из кото_ рых задано в регистрах EDX:EAX, а другое находится в памяти. Например, HHCT?Zv. ция cmpxchgsb temp при temp = EDX:EAX записывает в temp число из ЕСХ.Ь’ если temp отличается от EDX:EAX. то значение temp копируется в рсги EDX:EAX. 5.2. Умножение и деление оцесе®* Операции умножения и деления были включены в систему команд микропр ров не сразу. В ранних 8-битных микропроцессорах эти действия приходилос поднять сочетанием сдвигов, сложений и вычитаний. Этот недостаток был Др| рован в последующих процессорах. В настоящее время процессоры rd 221 дрнфметические и логические инструкции р ntiuni 4 содержат специальные средства, позволяющие сократить выполнение ум-ожения до одного такта; раньше — в предыдущих версиях микропроцессоров Hg0x86 — на это требовалось около 40 тактов. умножение Операндами инструкций умножения могут быть байты, слова или двойные слова. Предусмотрены команды умножения для знаковых целых (imul) и беззнаковых це-дых чисел (миь). Умножение 32-битных значений возможно только в процессорах 80386—Pentium 4. Произведение всегда имеет размерность вдвое больше размерности сомножителей. То есть умножение 8-битных чисел дает 16-битный результат; произведение 16-битных сомножителей имеет размерность 32 бита; перемножение 32-битных чисел дает 64-битный результат. флаги О и С при умножении изменяются, отражая свойства результата. (Другие флаги изменяются непредсказуемым образом.) Например, если старшие 8 бит результат при 8-битном умножении равны нулю, то С = О = 0. Обнуление флагов С и О означает, что размерность результата не превышает размерности сомножителей (т. е. при байтовом умножении результат помещается в байте), а С = О = 1 — что результат имеет удвоенную размерность. При 16-битном умножении С = О = 0 в том случае, если старшее слово результата равно нулю. При умножении 32-битных величин С ~ О = 0 означает, что значащие биты результата полностью представлены 32-битным значением. Восьмибитное умножение При 8-битном умножении, как знаковом, так и беззнаковом, множимое находится в регистре AL. Множителем может быть любой 8-битный регистр или байт в памяти. Непосредственный множитель допустим лишь в специальной инструкции знакового умножения, которую мы обсудим чуть позже. В инструкциях умножения указывается только один операнд, поскольку второй операнд — всегда регистр-аккумулятор. Например, инструкция миь вь умножает содержимое регистра AL на содержимое &L, считая сомножители беззнаковыми. После умножения беззнаковый результат Удвоенной размерности записывается в регистр АХ. Примеры инструкций 8-битного Умножения приведены в табл. 5.8. Таблица 5.8. Инструкции 8-битного умножения Команда KUL СЬ 1MUL DH lMUL EyTE PTR[BX] 14 TEMP Действие Содержимое регистра AL умножается на содержимое CL; беззнаковый результат помещается в регистр АХ Содержимое регистра AL умножается на содержимое DH; знаковый результат помещается в регистр АХ Содержимое регистра AL умножается на байт, расположенный в сегменте данных по смещению, указанному в регистре ВХ; знаковый результат помещается в регистр АХ Содержимое регистра AL умножается на байт, расположенный в сегменте данных по смещению temp; беззнаковый результат помещается в регистр АХ 222 Предположим, что в регистрах BL и CL содержатся S-битные беззнаковые чис Требуется перемножить их и сохранить 16-битный результат в регистре DX. Очеви но, что выполнить заданное действие одной командой нс удастся, хотя бы потом что один из сомножителей необходимо скопировать в регистр AL. Решение эт й задачи показано в примере 5.13. Предварительно в регистры BL и CL загружаю^ значения 5 и К). Результат произведения этих значений после выполнения комаи* ды mul из регистра АХ копируется в регистр DX. Пример 5.13. Перемножение 8-битных чисел q 0000 ВЗ 05 MOV BL, 5 •загрузить данные 0002 В1 од MOV CL, 10 0004 ед 01 MOV AL, CL установить значение множимого 0006 F6 F.3 MUL BL ; умножить 0008 8В D0 MOV DX,AX ; скопировать результат При знаковом умножении отрицательный результат представлен в дополнительном коде. На языке ассемблера команда знакового умножения обозначается мнемоникой IMUL. Умножение 16-битных слов Умножение слов похоже на умножение байт. Разница лишь в том. что множимое находится не в регистре AL, а в АХ, а результат получается не в регистре АХ, а в паре регистров DX—АХ. В регистр DX записывается старшая часть 32-битного результата умножения. Примеры инструкций 16-битного умножения приведены в табл. 5.9. Таблица 5.9. Инструкции 16-битного умножения Команда Действие MUL СХ Содержимое регистра АХ умножается на содержимое СХ; беззнаковый результат сохраняется в паре регистров DX—АХ IMUL DI Содержимое регистра АХ умножается на содержимое DI; знаковый результат сохраняется в паре регистров DX—АХ MUL WORD PTRU ^1] Содержимое регистра АХ умножается на слово из сегмента данных по смещению, указанному в регистре SI; беззнаковый результат сохран ется в паре регистров DX—АХ — Инструкция 16-битного умножения с непосредственным операндом Микропроцессоры 8086/8088 не допускают умножения с непосредственным °пе^ой дом; в процессорах 80186—Pentium 4 это возможно при использовании спеии' и инструкции. Этот вариант инструкции умножения работает со знаковыми ми ^jcTp-предполагает задание трех операндов. Первый операнд — 16-битный Ре тИЙ приемник; второй операнд — 16-битное множимое в регистре или в памяти» операнд — 8- или 16-битный множитель, заданный непосредственным знамен» 223 фактические и логические инструкции имер. инструкция jmul cx,dx,12h умножает содержимое регистра DX на 12Н, ИаПР|1Яя 16-битный знаковый результат в регистре СХ. Если непосредственное зна-задано байтом, то при умножении оно преобразуется в 16-битное число с *|СН,ц!ре,,,,ем знака- Еще °Д|,Н пример — команда iitje вх, number, юоон, которая раС жаеТ слово number на ЮООН и записывает произведение в регистр ВХ. Прием-' к множимое должны иметь одинаковую размерность — 16 бит. цик н умно*ение З2'битных данных процессорах 80386—Pentium 4 допускается 32-битное умножение, знаковое и без-«1КОв°е- При 32-битном умножении содержимое регистра ЕАХ перемножается па 31,1 оацд, заданны!! в инструкции. Произведение размерностью 64 бита сохраняется ° пегистрах EDX—ЕАХ, причем регистр ЕАХ содержит наименее значимую часть В зутьтата. Примеры инструкций 32-битного умножения приведены в табл. 5.10. Таблица 5.10. Инструкции 32-битного умножения Команда Действие MUL ЕС/. Содержимое регистра ЕАХ умножается на содержимое ЕСХ; беззнаковый результат сохраняется в регистрах EDX—ЕАХ IMUL EDI Содержимое регистра ЕАХ умножается на содержимое EDI; знаковый результат сохраняется в регистрах EDX—ЕАХ MUL DWORD PTR[ЕСХ] Содержимое регистра ЕАХ умножается на двойное слово из сегмента данных по смещению, указанному в ЕСХ; беззнаковый результат сохраняется в регистрах EDX—ЕАХ Деление Подобно умножению, деление предусмотрено для знаковых (idiv) и беззнаковых (div) операндов — 8- и 16-битных, а в процессорах 80386—Pentium 4 также и ^-битных. Размерность делимого всегда вдвое больше размерности делителя. Это означает, что при 8-битном делении 16-битное число делится на 8-битное; при о-битном делении делимое и делитель имеют размерность 32 и 16 бит соответствии©; при 32-битном делении делимое — 64-битное, а делитель — 32-битный. Посредственные операнды в инструкциях деления не предусмотрены. ^Лаги ПРИ делении изменяются непредсказуемым образом. При делении возможны ибки двуХ типов: делитель равен 0 или переполнение частного2. Переполнение . ’икает при делении большого значения на сравнительно малое. Например, при Ра3ИТНом Делении АХ = 3000 на число 2 полученный результат (1500) превышает гснеСРН°СТЬ ^а,^та В этом случае, как и при делении на ноль, микропроцессор эКраРИрует прерывание. В большинстве систем это прерывание вызывает вывод на рцв н сообщения об ошибке3. Прерывание по ошибке деления и другие типы пре-ний мы рассмотрим в главе 6. НИи^Цсству, это одна ошибка — переполнение Реакция процессора на переполнение при деле-’’Рсрывапие по вектору 0. — Пер. После сообщения об ошибке программа автоматически завершается. — Пер. 224 Глава 5 Восьмибитное деление При S-битном делении в регистре АХ находится делимое, а делитель задан любым 8-битным регистром или ячейкой памяти. После деления частное сохраняется в ре> гистрс AL, а остаток — в АН. При знаковом делении частное может бьпь положительным или отрицательным числом в дополнительном коде; знак остатка равен знаку делимого4. Например, если содержимое регистра АХ = 0010Н (+16) и BL = 0FDH (-3), то в результате выполнения инструкции idiv bl регистр AX-01FBH. Это значит, что частное равно -5 (в регистре AL), а остаток — +1 (в регистре АН). При делении -16 на +3 частное равно —5 (в регистре AL), а остаток равен -1 (в регистре АН) Примеры инструкций 8-битного деления приведены в табл. 5.11. Таблица 5.11. Инструкции 8-битного деления Команда Действие DIV CL Содержимое регистра АХ делится на содержимое CL; беззнаковое частное сохраняется в регистре AL, а остаток — в АН IDIV BL Содержимое регистра АХ делится на содержимое BL; знаковое частное сохраняется в регистре AL, а остаток — в АН DIV BYTE PTR[BP] Содержимое регистра АХ делится на содержимое байта, расположенного в сегменте стека по смещению, указанному в регистре ВР; беззнаковое частное сохраняется в регистре AL, а остаток — в АН При S-битном делении делимое, если оно задано байтом, следует предварительно преобразовать в 16-битную величину — в регистре АХ. Это преобразование выполняется для знаковых и беззнаковых чисел по-разному. При расширении беззнакового 8-битного числа старший байт следует обнулить; для этого можно воспользоваться инструкцией movzx процессоров 80386—Pentium 4, рассмотренной в главе 4. При расширении знаковых величин старшая часть данных заполняется значением знакового бита. Предусмотрена специальная инструкция cbw (convert byte to word — преобразование байта в слово) для расширения байта, в результате ее выполнения значение, находящееся в регистре AL, передается в АХ с сохранением знака. В процессорах S03S6—Pentium 4 есть еще одна возможность — использовать команду movsx (см. главу 4). В примере 5.14 приведена программа, выполняющая деление беззнаковых байт, находящихся в памяти по смещениям numb и numbi. Частное сохраняется в байте ANSQ» а остаток — в байте ansr. Обратите внимание, что число, скопированное в регистр AL из numb, расширяется до 16 бит с обнулением старшего байта регистра АН. Пример 5.14. Беззнаковое деление двух байтов в памяти 0000 АО 0000 R MOV AL,NUMB ; загрузить NUMB 0003 В4 00 MOV АН,0 ; расширить АХ нулями Это означает, что при делении -5 на 2 частное равно —2, а остаток — —I. Если бы у тот же знак, что у делимого, то результатом —5/2 было бы частное, равное —3, и ° статор Р ный + I. — Пер. драматические и логические инструкции 225 36 0002 R DIV NUMB1 ; разделить AX на NUMB1 q009 л~ 0003 R MOV ANSQ,AL ; сохранить частное пООС 26 0004 R MOV ANSR,AH ; сохранить остаток (Jv v 0000 АО 0000 R MOV AL,NUMB ; загрузить NUMB 0003 S’5 00 MOV AH, 0 ; расширить нулями 0005 36 0002 R DIV NUMB1 ; разделить на NUMB1 0009 А2 0003 R MOV ANSQ,AL ; сохранить частное 000С 88 26 0004 R MOV ANSR,AH ; сохранить остаток В примере 5.15 приведен вариант этой же программы, рассчитанный на знаковые значения. Вместо расширения регистра AL нулями здесь используется знаковое расширение, выполняемое командой cbw. Г пример 5.15. Знаковое деление двух байтов в памяти 0000 АО 0000 R MOV AL,NUMB ; загрузить NUMB в AL 0003 98 CBW ; расширить знак AL в АН 0004 Гб ЗЕ 0002 R 1DIV NUMB1 ; разделить на NUMB1 0008 А2 0003 R MOV ANSQ,AL ; сохранить частное 000В 88 26 0004 R MOV ANSR,AH ; сохранить остаток Деление с 16-битным делителем Инструкции 8- и 16-битного деления похожи, но в 16-битном варианте делимое находится не в регистре АХ, а в паре регистров DX—АХ и, кроме того, является не 16-битным, а 32-битным. После деления частное записывается в АХ, а остаток — в DX. В табл. 5.12 приведены примеры инструкций 16-битного деления. Таблица 5.12. Инструкции 16-битного деления Команда Действие v сх Содержимое регистров DX—АХ делится на содержимое СХ; беззнаковое частное записывается в регистр АХ, остаток — в DX lDlv SI Содержимое регистров DX—АХ делится на содержимое SI; знаковое частное записывается в регистр АХ, остаток — в DX Iv numb Содержимое регистра АХ делится на содержимое сегмента данных по смещению ________numb; беззнаковое частное записывается в регистр АХ, остаток — в DX nojfa? Делением 16-битное делимое следует преобразовать в 32-битное. Если пред-Рах беззнаковое деление, то в регистр DX следует записать ноль. В процессора з , 6-—Pentium 4 для расширения числа нулями предусмотрена команда movzx5. ton ПуКопого Расширения содержимого регистра АХ до содержимого пары регист-Л"~АХ предусмотрена команда cwd (convert word to doubleword — преобра- Cri0c06 11 здесь бесполезна: нужно нс расширять АХ до ЕАХ, а просто обнулить DX, любым ~~ посредством MOV DX, О, ИЛИ SUB DX, DX, ИЛИ XOR DX, DX. — Пер. 384 226 CfSjas зование слова в двойное слово); в процессорах 80386—Pentium 4 также может бк. использована команда movsx6. ь,Ть В примере 5.16 приведен листинг программы деления 16-битных знаковых чис а именно числа —100, разметенного в регистре АХ, на +9, помещенного в СХ струкция cwd преобразует число, заданное в регистре АХ, в значение, которое п мешается в паре регистров DX—АХ. Результаты деления сохраняются в регистп DX и АХ: в АХ — часi ное (равно -11), а в DX — остаток (равен -1). Пример 5.16. Знаковое деление 16-битных чисел В8 FF9C MOV AX,-100 ; загрузка делимого -100 0003 В 9 0009 MOV CX, 9 ; загрузка делителя +9 ооиб 99 CWD ; знаковое расширение делимого 0007 F7 F9 IDIV CX Деление с 32-битным делителем В процессорах 80386—Pentium 4 предусмотрена команда 32-битного деления для знаковых и беззнаковых чисел. Делимое размерностью 64 бит записывается в паре регистров EDX—ЕАХ, делитель задан в инструкции. Частное размерностью 32 бита сохраняется в регистре ЕАХ, а 32-битный остаток — в EDX. В принципе, эта инструкция аналогична командам 8- и 16-битного деления и отличается от них только размерностью операндов; примеры команд 32-битного деления приведены в табл. 5.13. Преобразование двойного слова из регистра ЕАХ в 8-байтное слово, размещаемого в паре регистров EDX—ЕАХ, выполняется инструкцией cdq (convert doubleword to quadword — преобразование двойного слова в учетверенное), с расширением знака. Таблица 5.13. Инструкции 32-битного деления Команда Действие DIV ЕСХ Содержимое пары регистров EDX—ЕАХ делится на содержимое ЕСХ; беззнаковое частное записывается в регистр ЕАХ, остаток-* в EDX DIV DATA2 Содержимое пары регистров EDX—ЕАХ делится на двойное слс^ находящееся в сегменте данных по смещению data2; беззнако частное записывается в регистр ЕАХ, остаток — в EDX IDIV DWORD PTRfEDI] Содержимое пары регистров EDX—ЕАХ делится на двойное о, которое хранится в сегменте данных по смещению, Ука^^ ^а-регистре EDI; знаковое частное записывается в регистр ЬАл. ток — в EDX —*** Использование остатка _ й — Что делать с остатком, полученным при делении? Одна из возможностей ус«' зонать его для округления частного; если не анализировать остаток, то час 6 Использование MOVSX при 16-битном делении также нс имеет смысла. — Пер. 227 ^фМетические и логические инструкции тсЯ. При беззнаковом делении округление выполняется за счет сравнения остатка ^^цыиенным вдвое делителем. с У* сТццг с использованием округления приведен в примере 5.17. Здесь выполняется ^с11це содержимого регистра АХ па содержимое BL, затем остаток удваивается и вНлвастся с регистром BL. По результату сравнения принимается решение о кор- ^цИ11 частного — командой inc. ^Пример 5.17. Округление частного при беззнаковом делении о0оо Гб F3 DIV BL 0002 02 Е4 ADD АН, АН 0004 ЗА ЕЗ СМР АН, BL 0006 72 02 JB NEXT 0008 FE СО INC AL 000А NEXT: ; разделить ; удвоить остаток ; сравнить в делителем ; округлить частное Из целочисленного остатка можно получить дробный остаток. Для этого после деления следует обнулить регистр AL, предварительно сохранив его значение (частное) в другом регистре или ячейке памяти. Значение регистра АХ используется затем в качестве делимого, при том же значении делителя. Результат — дробный остаток. В примере 5.18 приведен листинг программы получения дробного остатка от деления 13 на 2. Восьмибитное частное сохраняется в ячейке ansq, затем регистр AL обнуляется. Содержимое регистра АХ вновь делится на 2. После деления в регистре AL будет записано число 80Н. В двоичном коде это 10000000. Двоичная точка находится перед крайним правым битом AL, и дробный остаток равен 0.10000000 в двоичном представлении, т. е. 0.5. Остаток сохраняется в ячейке памяти ansr. Пример 5.18. Получение дробного остатка °°00 В8 QC0D °°03 ВЗ 02 0005 F6 F3 MOV MOV DIV AX, 13 BL, 2 BL ; загрузить ; загрузить ; разделить 13 13 на 2 “°7 А2 0003 R ООп» MOV ANSQ,AL ; сохранить частное во оо ООпс г. MOV AL, 0 ; обнулить ] регистр 1 2 С F6 F3 ООпр DIV BL ; получить । остаток Е д2 0004 R MOV ANSR,AL ; сохранить остаток S О Л • Арифметика BCD- и ASCII-данных МИкро ПроцсссоР способен выполнять арифметические операции над данными в *Чци2ах BCD (двоично-десятичные) и ASCII — при помощи специальных инст-h и Коррекции, t । (*)0Р‘мата BCD используются в терминальном оборудовании, например, в ь,х аппаратах, где арифметические действия выполняются относительно ред- 228 ко. ASCII-арифметика используется при работе с числами, заданными ASCIK волами7. СИМ. BCD-арифметика Данные в формате BCD можно складывать и вычитать командами двоичной апиж метики add и sub. Результат сложения следует скорректировать инструкцией п (decimal adjust after addition — десятичная коррекция после сложения), a результат вычитания — инструкцией das (decimal adjust after subtraction — десятичная коррек ция после вычитания). Результат коррекции — правильное BCD-число. Сложение или вычитание с коррекцией выполняется для двузначных десятичных чисел в формате упакованных BCD-чисел (в одном байте — две цифры). Инструк-ции daa/das корректируют результат сложения/вычитания в регистре AL. Инструкция DAA Инструкция daa выполняется сразу после команды add или adc для приведения результата к двоично-десятичному формату. Предположим, что регистры DX и ВХ содержат четырехзначные упакованные BCD-числа. В примере 5.19 приведена программа, которая складывает BCD-числа в регистрах DX и ВХ, сохраняя результат в регистре СХ. Пример 5.19. Сложение 4-значных упакованных BCD-чисел 0000 ВА 1234 MOV DX,1234H ; загрузить 1234 0003 ВВ 3099 MOV ВХ,3099H ; загрузить 3099 0006 8А СЗ MOV AL, BL ; сложить содержимое 0008 02 С2 ADD AL, DL ; регистров BL и DL 000А 27 DAA ; скорректировать 000В 8А С8 MOV CL, AL ; результат — в регистр CL 000D 8А С7 MOV AL,BH ; сложить ВН, DH и перенос 000F 12 С6 ADC AL,DH ООП 27 DAA ; скорректировать 0012 8А Е8 MOV CH, AL ; результат — в регистр СН Поскольку инструкция daa обрабатывает только две цифры в регистре AL, 0/13 мые могут быть только 8-битными. После сложения значений регистров BL результат, перед сохранением в регистре CL, корректируется инструкцией DAA‘ ь1«т выполняется сложение содержимого регистров ВН и DH с переносом; Р63 вновь корректируется инструкцией daa и сохраняется в регистре СН. В приве примере число 1234 прибавляется к 3099; в итоге, регистр СХ содержит сУ|^наЧеН^ Заметим, что 1234 в формате упакованных BCD-чисел — это 16-ричное I234H. 7 Например, при обработке баз данных в DBF-формате, где все данные (даже численное) лены строками ASCH-символами. — Пер. 229 ифМ?тические и логические инструкции Ийсгрукчия DAS цукини das применяется в аналогичных ситуациях, но не после сложения, а ’вычитания. В примере 5.20 приведена программа, подобная программе из п°Смера 5.19, для вычисления разности между содержимым регистров DX и ВХ. ^есто daa здесь используется команда das, а вместо add/adc — инструкции sub/sbb. ^Пример 5.20. Вычитание 4-значных упакованных BCD-чисел лП00 ВА 1234 MOV DX,1234H ; загрузить 1234 (JUV V оооз вв 3099 MOV ВХ,3099H ; загрузить 3099 оооб 8А сз MOV AL, BL ; вычесть содержимое регистра DL 0008 2А 02 SUB AL, DL ; из содержимого регистра BL 000А 2F DAS ; скорректировать ооов 8А 08 MOV CL, AL ; результат - в регистр CL 000D 8А С7 MOV AL, BH ; вычесть содержимое регистра DH 000F 1А Об SBB AL, DH ООП DAS ; скорректировать 0012 8А £8 MOV CH, AL ; результат — в регистр СН ASCII-арифметика ASCII-числа кодируются ASCII-символами 'О'—’9’, в диапазоне кодов ЗОН—39Н. Для работы с ASCII-числами предусмотрено четыре инструкции: ааа (ASCII adjust after addition — ASCII-коррекция после сложения), aad (ASCII adjust before division — ASCII-коррекция перед делением), aam (ASCII adjust after multiplication — ASCII-коррекция после умножения) и aas (ASCII adjust after subtraction — ASCII-коррекция после вычитания). Эти инструкции используют регистр АХ в качестве источника и приемника. правильного результата. Например. Инструкция ААА Двоичное сложение пары ASCII-цифр не дает правильного результата. Например, сложить 'Г и '9' (31Н и 39Н), результат составит 6АН. Числа 1 и 9 должны бы-Дать в сумме ASCII-число 10, т. е. пару кодов 31Н и ЗОН. Если после сложения Не AQHl1Tb И,1СТРУКЦИЮ ааа, значение в регистре АХ станет равным 0100Н. Это еще (•|л,.^И"ЧИсло, но после прибавления кода 3030Н ('00') оно станет равным ЗВОН । Инструкция ааа обнуляет регистр АН, если результат меньше 10, и прибавляет & с°Держимому регистра АН, если результат больше 10. ^Римере 5.21 приведена программа сложения ASCII-чисел. Обратите внимание, Коцан^еРЖимое регистра АН перед сложением обнуляется в результате выполнения ДЬ1 mov ах, 31н. В регистр AL при этом записывается код 31Н (’Г). 5.21. Сложение ASCII-чисел 05 0031 MOV АХ,31Н 39 ADD AL,39Н ААА 3030 ADD АХ,ЗОЗОН ; загрузить '1' ; прибавить '9' ; скорректировать ; преобразование результата в ASCII-код 230 Гпава 5 Инструкция AAD В отличие от других инструкций коррекции, инструкция aad применяется не после, а перед операцией: перед делением. В регистре АХ перед выполнением инструкции aad записывается двузначное неупакованное BCD-число (отличается от ASCII-формата тем, что старшие тетрады байтов обнулены). После коррекции в регистре АХ находится двоичное число, которое можно использовать в качестве делимого; результат 8-битного деления сохраняется в регистрах AL (частное) и АН (остаток). В примере 5.22 приведена программа деления числа 72, заданного в формате неупакованных BCD-чисел, на 9. Код 0702Н загружается в регистр АХ и преобразуется инструкцией aad в двоичное число 72, или 48Н. Пример 5.22. Коррекция делимого в формате упакованных BCD-чисел 0000 ВЗ 09 MOV BL, 9 ; загрузить делитель 0002 В8 0702 MOV AX,0702H ; загрузить делимое 0005 D5 0А AAD ; скорректировать 0007 F6 F3 DIV BL Инструкция ААМ Инструкция аам выполняется после перемножения неупакованных BCD-цифр (т. е. чисел в диапазоне от 0 до 9). В примере 5.23 приведен листинг программы, которая умножает 5 на 5. Произведение 0019Н сохраняется в регистре АХ. После коррекции результата командой аам регистр АХ содержит код 0205Н — число 25 в формате неупакованных BCD-данных. Прибавив 3030Н, получим результат в формате ASCII-чисел — 3235Н. ; Пример 5.23. Коррекция произведения 0000 ВО 05 MOV AL, 5 ; загрузить множимое 0002 В1 05 MOV CL, 5 ; загрузить множитель 0004 F6 Е1 MUL CL 0006 D4 0А ААМ ; скорректировать Инст