Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 8 октября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Ассемблер для крэкера

Под редакцией Еpшова В.Г.
FFFF0, что является точкой входа в BIOS.  BIOS проверяет  различные  порты
компьютера для определения и инициализации подключенных устрой ств.  Затем
BIOS создает в начале памяти (по адресу  0)  таблицу  прерываний,  которая
содержит адреса обработчиков прерываний, и выполняет две операции INT  11H
(запрос списка присоединенного оборудования) и  INT  12H  (запрос  размера
физической памяти).
     Следующим шагом BIOS определяет  имеется  ли  на  диске  или  дискете
операционная система DOS.  Если  обнаружена  системная  дискета,  то  BIOS
выполняет  прерывание  INT  19H  для  доступа  к  первому  сектору  диска,
содержащему  блок  начальной  загрузки.  Этот  блок  представляет    собой
программу, которая считывает  системные  файлы  IBMBIO.COM,  IBMDOS.COM  и
COMMAND.COM  с  диска  в  память.  После  этого  память  имеет   следующее
распределение:

               Таблица векторов прерываний
               Данные BIOS
               IBMBIO.COM и IBMDOS.COM
               Резидентная часть COMMAND.COM
               Доступная память для прикладных программ
               Транзитная часть COMMAND.COM
               Конец RAM (ОЗУ)
               ROM BASIC
               ROM BIOS

     Внешние устройства передают сигнал  внимания  через  контакт  INTR  в
процессор.  Процессор реагирует на этот запрос, если  флаг  прерывания  IF
установлен  в  1  (прерывание  разрешено),  и  (в  большинстве    случаев)
игнорирует запрос, если флаг IF установлен в 0 (прерывание запрещено).
     Операнд  в  команде  прерывания,  например,  INT  12H,  содержит  тип
прерывания,  который  идентифицирует  запрос.  Для  каждого  типа  система
содержит адрес в таблице векторов прерываний, начинающейся по адресу 0000.
Так как в таблице имеется 256 четырехбайтовых элементов, то  она  занимает
первые 1024 байта памяти от шест.0 до  шест.3FF.  Каждый  элемент  таблицы
указывает на подпрограмму обработки указанного типа прерывания и  содержит
адрес кодового сегмента и смещение, которые при прерывании устанавливаются
в регистры CS и  IP  соответственно.  Список  элементов  таблицы  векторов
прерываний приведен на рис. 23.1.
     Прерывание заносит в стек содержимое флагового регистра, регистра  CS
и регистра IP. Например, для прерывания 12H (которое возвращает в регистре
AX размер памяти) адрес элемента таблицы равен шест.0048 (шест.12  х  4  =
шест.48). Операция выделяет четырехбайтовый элемент по адресу шест. 0048 и
заносит два байта в регистр IP и два байта в регистр  SS.  Адрес,  который
получается в регистровой  паре  CS:IP,  представляет  собой  адрес  начала
подпрограммы в области BIOS, которая получает управление.  Возврат из этой
подпрограммы осуществляется  командой  IRET  (Interrupt  Return),  которая
восстанавливает флаги и регистры CS и IP из стека и передает управление на
команду, следующую за выполненной командой прерывания.

__________________________________________________________________________

      Адрес                   Функция прерываний
      (шест.)                      (шест.)

       0-3         0          Деление на нуль
       4-7         1          Пошаговый режим (трассировка DEBUG)
       8-B         2          Немаскированное прерывание (NMI)
       C-F         3          Точка останова (используется в DEBUG)
      10-13        4          Переполнение регистра
      14-17        5          Печать экрана
      18-1F        6,7        Зарезервировано
      20-23        8          Сигнал от таймера
      24-27        9          Сигнал от клавиатуры
      28-37        A,B,C,D    Используются в компьютерах AT
      38-3B        E          Сигнал от дискетного дисковода
      3C-3F        F          Используется для принтера
      40-43       10          Управление дисплеем (см.гл. 8, 9, 10)
      44-47       11          Запрос оборудования (см.гл.9)
      48-4B       12          Запрос размера памяти (см.гл.2)
      4C-4F       13          Дисковые операции ввода-вывода (см.гл.18)
      50-53       14          Управление коммуникационным адаптером
      54-57       15          Кассетные операции и спец. функции AT
      58-5B       16          Ввод с клавиатуры (см.гл.9)
      5C-5F       17          Вывод на принтер (см.гл.19)
      60-63       18          Обращение к BASIC, встроенному в ROM
      64-67       19          Перезапуск системы
      68-6B       1A          Запрос и установка времени и даты
      6C-6F       1B          Прерывание от клавиатуры
      70-73       1C          Прерывание от таймера
      74-77       1D          Адрес таблицы параметров дисплея
      78-7B       1E          Адрес таблицы параметров дисковода
      7C-7F       1F          Адрес таблицы графических символов
      80-83       20          Нормальное завершение программы (DOS)
      84-87       21          Обращение к функциям DOS
      88-8B       22          Адрес обработки завершения задачи (DOS)
      8C-8F       23          Адрес реакции по Ctrl/Break (DOS)
      90-93       24          Адрес реакции на фатальную ошибку (DOS)
      94-97       25          Абсолютное чтение с диска (DOS)
      98-9B       26          Абсолютная запись на диск (DOS)
      97-9F       27          Создание резидентной программы (DOS)
      AO-FF    28-3F          Другие функции DOS
     100-1FF   40-7F          Зарезервировано
     200-217   80-85          Зарезервировано для BASIC
     218-3C3   86-F0          Используются BASIC-интерпретатором
     3C4-3FF   F1-FF          Зарезервировано

     Примечание:    Прерывания 00-1F относятся к BIOS,
                    прерывания 20-FF относятся к DOS и BASIC.
__________________________________________________________________________

     Рис.23.1. Таблица адресов прерываний.


     ПРЕРЫВАНИЯ BIOS
     ________________________________________________________________

     В данном разделе приведены основные прерывания BIOS.

     INT 05H. П е ч а т ь  э к р а н а. Выполняет вывод содержимого экрана
на печатающее устройство.  Команда INT 05H выполняет  данную  операцию  из
программы,  а  нажатие  клавишей  Ctrl/PrtSc  -  с  клавиатуры.   Операция
запрещает прерывания и сохраняет позицию курсора.

     INT 10H. У п р а в л е н и е  д и с п л е е м.  Обеспечивает экранные
и клавиатурные операции, детально описанные в гл.9.

     INT  11H.   З а п р о с   с п и с к а   п р и с о е д и н е н н о г о
о б о р у д о в а н и я. Определяет наличие различных устройств в системе,
результирующее значение возвращает в регистре AX. При включении компьютера
система выполняет эту операцию и  сохраняет  содержимое  AX  в  памяти  по
адресу шест.410. Значения битов в регистре AX:

     Бит            Устройство

     15,14     Число подключенных принтеров.
     13        Последовательный принтер.
     12        Игровой адаптер.
     11-9      Число последовательных адаптеров стыка RS232.
     7,6       Число дискетных дисководов, при бите 0=1:
                    00=1, 01=2, 10=3 и 11=4.
     5,4       Начальный видео режим:
                    00 = не используется,
                    01 = 40х25 плюс цвет,
                    10 = 80х25 плюс цвет,
                    11 = 80х25 черно-белый режим.
     1         Значение 1 говорит о наличии сопроцессора.
     0         Значение 1 говорит о наличии одного или более дисковых
               устройств и загрузка операционной системы должна
               осуществляться с диска.

     INT 12H З а п р о с  р а з м е р а  ф и з и ч е с к о й  п а м я т и.
Возвращает в регистре AX размер памяти в  килобайтах,  например,  шест.200
соответствует памяти в 512 К.  Данная операция  полезна  для  выравнивания
размера программы в соответствии с доступной памятью.

     INT 13H.   Д и с к о в ы е  о п е р а ц и и  в в о д а - в ы в о д а.
Обеспечивает операции ввода-вывода для дискет и винчестера,  рассмотренные
в главе 16.

     INT 14H.     У п р а в л е н и е      к о м м у н и к а ц и о н н ы м
а д а п т е р о м.    Обеспечивает   последовательный   ввод-вывод   через
коммуникационный порт RS232. Регистр DX должен содержать номер (0  или  1)
адаптера стыка RS232. Четыре типа  операции,  определяемые  регистром  AH,
выполняют прием и передачу  символов  и  возвращают  в  регистре  AX  байт
состояния коммуникационного порта.

     INT 15H.  К а с с е т н ы е  о п е р а ц и и  в в о д а - в ы в о д а
и  с п е ц и а л ь н ы е  ф у н к ц и и  д л я  к о м п ь ю т е р о в  AT.
Обеспечивает операции  ввода-вывода  для  кассетного магнитофона,  а также
расширенные операции для компьютеров AT.

     INT 16H.   В в о д  с  к л а в и а т у р ы.   Обеспечивает  три  типа
команд ввода с клавиатуры, подробно описанные в гл.9.

     INT 17H.  В ы в о д  н а  п р и н т е р. Обеспечивает вывод данных на
печатающее устройство. Подробно рассмотрено в гл.19.

     INT 18H. О б р а щ е н и е  к  BASIC,  в с т р о е н н о м у  в  ROM.
Вызывает BASIC-интерпретатор, находящийся в постоянной памяти ROM.

     INT 19H.  П е р е з а п у с к  с и с т е м ы.   Данная  операция  при
доступном диске считывает  сектор  1  с  дорожки  0  в  область  начальной
загрузки в памяти (сегмент 0, смещение  7C00)  и  передает  управление  по
этому адресу.  Если дисковод не доступен, то операция передает  управление
через INT 18H  в  ROM  BASIC.  Данная  операция  не  очищает  экран  и  не
инициализирует данные в  ROM  BASIC,  поэтому  ее  можно  использовать  из
программы.

     INT 1AH.     З а п р о с    и    у с т а н о в к а    т е к у щ е г о
в р е м е н и  и  д а т ы.   Считывает  и  записывает  показание  часов  в
соответствии со значением в регистре AH. Для определения продолжительности
выполнения программы можно перед началом выполнения установить часы в 0, а
после считать текущее время.  Отсчет времени идет  примерно  18,2  раза  в
секунду. Значение в регистре AH соответствует следующим операциям:

          AH=00 Запрос времени.  В  регистре  CX  устанавливается  старшая
     часть значения, а в регистре DX  -  младшая.  Если  после  последнего
     запроса прошло 24 часа, то в регистре AL будет не нулевое значение.
          AH=01 Установка времени.  Время устанавливается по регистрам  CX
     (старшая часть значения) и DX (младшая часть значения).

     Коды 02 и 06 управляют временем и датой для AT.

     INT 1FH.      А д р е с      т а б л и ц ы      г р а ф и ч е с к и х
с и м в о л о в.  В графическом режиме имеется доступ к символам с  кодами
128-255 в 1К таблице, содержащей по восемь байт на каждый  символ.  Прямой
доступ  в  графическом  режиме  обеспечивается  только  к    первым    128
ASCII-символам (от 0 до 127).


     ПРЕРЫВАНИЯ DOS
     ________________________________________________________________

     Во время своей работы BIOS использует два модуля  DOS:  IBMBIO.COM  и
IBMDOS.COM.  Так как модули DOS  обеспечивают  большое  количество  разных
дополнительных проверок, то операция DOS обычно проще  в  использовании  и
менее машиннозависимы, чем их BIOS аналоги.
     Модуль IBMBIO.COM обеспечивает интерфейс с BIOS низкого  уровня.  Эта
программа выполняет управление вводом-выводом при чтении данных из внешних
устройств в память и записи из памяти на внешние устройства.
     Модуль  IBMDOS.COM  содержит  средства  управления  файлами  и    ряд
сервисных функций, таких как блокирование и деблокирование записей.  Когда
пользовательская программа выдает запрос INT 21H, то  в  программу  IBMDOS
через регистры передается определенная информация.  Затем программа IBMDOS
транслирует эту информацию в один или несколько вызовов IBMBIO, которая  в
свою очередь вызывает BIOS. Указанные связи приведены на следующей схеме:

       Пользовательский Высший       Низший     ROM     Внешний
       уровень          уровень      уровень            уровень
       ------------¬ -----------¬ -----------¬
       ¦Программный¦ ¦   DOS    ¦ ¦   DOS    ¦ -----¬ -----------¬
       ¦запрос в/в ¦.¦IBMDOS.COM¦.¦IBMBIO.COM¦.¦BIOS¦.¦Устройство¦
       L------------ L----------- L----------- L----- L-----------

     Как показано выше, прерывания от шест.20 до  шест.62  зарезервированы
для операций DOS. Ниже приведены наиболее основные из них:

     INT 20H.  З а в е р ш е н и е  п р о г р а м м ы.   Запрос  завершает
выполнение программы и передает управление в  DOS.  Данный  запрос  обычно
находится в основной процедуре.

     INT 21H.  З а п р о с  ф у н к ц и й  DOS.   Основная  операция  DOS,
вызывающая определенную функцию в соответствии  с  кодом  в  регистре  AH.
Назначение функций DOS описано в следующем разделе.

     INT 22H.    А д р е с    п о д п р о г р а м м ы    о б р а б о т к и
з а в е р ш е н и я  з а д а ч и. (см.INT 24H).

     INT 23H.    А д р е с   п о д п р о г р а м м ы   р е а к ц и и   н а
Ctrl/Break. (см.INT 24H).

     INT 24H.    А д р е с   п о д п р о г р а м м ы   р е а к ц и и   н а
ф а т а л ь н у ю  о ш и б к у.  В  этом  элементе  и  в  двух  предыдущих
содержатся  адреса,  которые  инициализируются   системой    в    префиксе
программного  сегмента  и,  которые  можно  изменить  для  своих    целей.
Подробности приведены в техническом описании DOS.

     INT 25H. А б с о л ю т н о е  ч т е н и е  с  д и с к а. См.гл.17.

     INT 26H. А б с о л ю т н а я  з а п и с ь  н а  д и с к. См.гл.17.

     INT 27H.З а в е р ш е н и е  п р о г р а м м ы, о с т а в л я ю щ е е
е е р е з е д е н т н о й.  Позволяет сохранить  COM-программу  в  памяти.
Подробно данная операция рассмотрена в  последующем  разделе  "Резидентные
программы".


     ФУНКЦИИ ПРЕРЫВАНИЯ DOS INT 21H
     ________________________________________________________________

     Ниже приведены базовые  функции  для  прерывания  DOS  INT  21H.  Код
функции устанавливается в регистре AH:

     00   Завершение программы (аналогично INT 20H).
     01   Ввод символа с клавиатуры с эхом на экран.
     02   Вывод символа на экран.
     03   Ввод символа из асинхронного коммуникационного канала.
     04   Вывод символа на асинхронный коммуникационный канал.
     05   Вывод символа на печать (гл.19).
     06   Прямой ввод с клавиатуры и вывод на экран.
     07   Ввод с клавиатуры без эха и без проверки Ctrl/Break.
     08   Ввод с клавиатуры без эха с проверкой Ctrl/Break.
     09   Вывод строки символов на экран (гл.8).
     0А   Ввод с клавиатуры с буферизацией (гл.8).
     0В   Проверка наличия ввода с клавиатуры.
     0С   Очистка буфера ввода с клавиатуры и запрос на ввод.
     0D   Сброс диска (гл.16).
     0Е   Установка текущего дисковода (гл.16).
     0F   Открытие файла через FCB (гл.16).
     10   Закрытие файла через FCB (гл.16).
     11   Начальный поиск файла по шаблону (гл.16).
     12   Поиск следующего файла по шаблону (гл.16).
     13   Удаление файла с диска (гл.16).
     14   Последовательное чтение файла (гл.16).
     15   Последовательная запись файла (гл.16).
     16   Создание файла (гл.16).
     17   Переименование файла (гл.16).
     18   Внутренняя операция DOS.
     19   Определение текущего дисковода (гл.16).
     1А   Установка области передачи данных (DTA).
     1В   Получение таблицы FAT для текущего дисковода.
     1С   Получение FAT для любого дисковода.
     21   Чтение с диска с прямым доступом  (гл.16).
     22   Запись на диск с прямым доступом (гл.16).
     23   Определение размера файла.
     24   Установка номера записи для прямого доступа.
     25   Установка вектора прерывания.
     26   Создание программного сегмента.
     27   Чтение блока записей с прямым доступом (гл.16).
     28   Запись блока с прямым доступом (гл.16).
     29   Преобразование имени файла во внутренние параметры.
     2А   Получение даты (CX-год,DН-месяц,DL-день).
     2В   Установка даты.
     2С   Получение времени (CH-час,CL-мин,DН-с,DL-1/100с).
     2D   Установка времени.
     2Е   Установка/отмена верификации записи на диск.

     Следующие расширенные функции возможны в DOS начиная с версии 2.0:

     2F    Получение адреса DTA в регистровой паре ES:BX.
     30    Получение номера версии DOS в регистре АХ.
     31    Завершение программы, после которого она остается резидентной в
           памяти.
     33    Проверка Ctrl/Break.
     35    Получение вектора прерывания (адреса подпрограммы).
     36    Получение размера свободного пространства на диске.
     38    Получение государственно зависимых форматов.
     39    Создание подкаталога (команда MKDIR).
     ЗА    Удаление подкаталога (команда RMDIR).
     3В    Установка текущего каталога (команда CHDIR).
     3C    Создание файла без использования FCB (гл.17).
     3D    Открытие файла без использования FCB (гл.17).
     3E    Закрытие файла без использования FCB (гл.17).
     3F    Чтение из файла или ввод с устройства (гл.8,17,19).
     40    Запись в файл или вывод на устройство (гл.8,17,19).
     41    Удаление файла из каталога (гл.17).
     42    Установка позиции для последовательного доступа (гл.17).
     43    Изменение атрибутов файла (гл.17).
     44    Управление вводом-выводом для различных устройств.
     45    Дублирование файлового номера.
     46    "Склеивание" дублированных файловых номеров.
     47    Получение текущего каталога (гл.17).
     48    Выделение памяти из свободного пространства.
     49    Освобождений выделенной памяти.
     4А    Изменение длины блока выделенной памяти.
     4В    Загрузка/выполнение программы (подпроцесса).
     4С    Завершение подпроцесса с возвратом управления.
     4D    Получение кода завершения подпроцесса.
     4Е    Начальный поиск файла по шаблону (гл.17).
     4F    Поиск следующего файла по шаблону (гл.17).
     54    Получение состояния верификации.
     56    Переименование файла (гл.17).
     57    Получение/установка даты и времени изменения файла.

     Следующие расширенные функции возможны в DOS начиная с версии 3.0:

     59    Получение расширенного кода ошибки.
     5А    Создание временного файла.
     5В    Создание нового файла.
     5С    Блокирование/разблокирование доступа к файлу.
     62    Получение адреса префикса программного сегмента (PSP).

     В техническом руководстве  по  DOS  представлены  подробные  описания
каждой функции.


     РЕЗИДЕНТНЫЕ ПРОГРАММЫ
     ________________________________________________________________

     Существует ряд распространенных фирменных программ (Prokey, Superkey,
Homebase, Sidekick  и  др.),  специально  разработанных  как  резидентные,
которые находятся в памяти во время работы других программ.  Эти программы
можно  активизировать  нажатием  определенных  клавиш.  Такие    программы
называются резидентными, и они загружаются в память сразу  после  загрузки
DOS перед выполнением обычных программ.
     Для  того,  чтобы  оставить  резидентную  COM-программу  в    памяти,
необходимо вместо команды RET или INT 20H для выхода использовать  команду
INT 27H  или  функцию  DOS  31Н.  Для  INT  27Н следует передать системе в
регистре DX размер программы:

               MOV     DX,prog-size
               INT     27H

     При выполнении программы инициализации DOS резервирует  (выделяет)  в
старших доступных адресах блок  памяти  и  загружает  в  него  резидентную
программу. Это наиболее простая часть создания резидентной программы.
     Более сложная часть включает программирование  механизма  активизации
резидентной программы, которая хотя и присоединена к DOS, но  не  является
внутренней программой DOS, как DIR, COPY или CLS.  Общим подходом является
модификация таблицы векторов прерываний таким образом,  чтобы  резидентная
программа, получала управление при  нажатии  определенных  клавиш  или  их
комбинаций, а все остальные передавала через себя.  Резидентная  программа
обычно (но не обязательно) состоит из следующих частей:

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

               -  замены  адреса  в  таблице  векторов    прерываний    на
          собственный адрес;
               - установки размера части программы, которая  должна  стать
          резидентной;
               - использования прерывания DOS для завершения  программы  и
          создания резидентной части по указанному размеру;

          3) процедуры, которая  остается  резидентной  и  активизируется,
     например, по вводу с клавиатуры или по сигналам таймера.

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

               Таблица векторов прерываний
               IВМВIO.СОМ и IBMDOS.COM
               COMMAND.СОМ
               Резидентная часть программы - остается в памяти
               Инициализирующая часть программы - перекрывается  следующей
               программой
               Остальная часть доступной памяти

__________________________________________________________________________

TITLE   RESIDENT (COM) Резидентная программа для очистки
;                      экрана и установки цвета при нажатии
;                      Alt+Left Shift
;----------------------------------------------------------
INTTAB  SEGMENT AT 0H         ;Таблица векторов прерываний:
        ORG     9H*4          ; адрес для Int 9H,
KBADDR  LABEL   DWORD         ; двойное слово
INTTAB  ENDS
;----------------------------------------------------------
ROMAREA SEGMENT AT 400H       ;Область параметров BIOS:
        ORG     17H           ; адрес флага клавиатуры,
KBFLAG  DB      ?             ; состояние Alt + Shift
ROMAREA ENDS
;----------------------------------------------------------
CSEG    SEGMENT PARA          ;Сегмент кода
        ASSUME  CS:CS
        ORG     100H
BEGIN:  JMP     INITZ         ;Выполняется только один раз
KBSAVE  DD      ?             ;Для адреса INT 9 BIOS
;               Очистка экрана и установка цветов:
;               ---------------------------------
COLORS  PROC    NEAR          ;Процедура выполняется
        PUSH    AX            ; при нажатии Alt+Left Shift
        PUSH    BX
        PUSH    CX            ;Сохранить регистры
        PUSH    DX
        PUSH    SI
        PUSH    DI
        PUSH    DS
        PUSH    ES
        PUSHF
        CALL    KBSAV         ;Обработать прерывание
        ASSUME  DS:ROMAREA
        MOV     AX,ROMAREA    ;Установить DS для
        MOV     DS,AX         ; доступа к состоянию
        MOV     AL,KB  AG     ; Alt+Left Shift
        CMP     AL,00001010B  ;Alt+Left Shift нажаты?
        JNE     EXIT          ; нет - выйти
        MOV     AX,0600H      ;Функция прокрутки
        MOV     BH,61H        ;Установить цвет
        MOV     CX,00
        MOV     DX,18 FH
        INT     10H
EXIT:
        POP     ES            ;Восстановить регистры
        POP     DS
        POP     DI
        POP     SI
        POP     DX
        POP     CX
        POP     BX
        POP     AX
        IRET                  ;Вернуться
COLORS  ENDP
;               Подпрограмма инициализации:
;               --------------------------
INITZE  PROC    NEAR            ;Выполнять только один раз
        ASSUME  DS:INTTAB
        PUSH    DS              ;Обеспечить возврат в DOS
        MOV     AX,INTTAB       ;Установить сегмент данных
        MOV     DS,AX
        CLI                     ;Запретить прерывания
                                ;Замена адреса обработчика:
        MOV     AX,WORD PTR KBADDR      ;Сохранить адрес
        MOV     WORD PTR KBSAVE,AX      ; BIOS
        MOV     AX,WORD PTR BADDR+2
        MOV     WORD PTR KBSAVE+2,AX
        MOV     WORD PTR KBADDR,OFFSET COLORS ;Заменить
        MOV     WORD PTR KBADDR+2,CS          ; адрес BIOS
        STI                      ;Разрешить прерывания
        MOV     DX,OFFSET INITZE ;Размер программы
        INT     27H              ;Завершить и остаться
INITZE  ENDP                     ; резидентом

CSEG    ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.23.2 Резидентная программа


     Пример  на  рис.23.2  иллюстрирует  резидентную  программу,   которая
устанавливает цвет экрана при одновременном  нажатии  клавиш  Alt  и  Left
Shift. Основные моменты, представляющие интерес:
     Сегмент INTTAB определяет таблицу векторов  прерываний,  начинающуюся
по адресу  0,  а  точнее  -  адрес  элемента  для  прерывания  9  (ввод  с
клавиатуры), названный в программе KBADDR.
     Имя ROMAREA определяет сегмент, начинающийся по адресу 400Н, и в  нем
флаговый байт клавиатуры (KBFLAG), который отражает состояние  клавиатуры.
Бит 3 в этом байте регистрирует нажатие клавиши Alt, а  бит  1  -  нажатие
клавиши Left Shift.
     Сегмент  CSEG  начинает  сегмент  обычной    COM-программы.    Первая
выполняемая команда  JMP  INITZE  обходит  резидентную  часть  и  передает
управление в процедуру  инициализации  (INITZE)  в  конце  программы.  Эта
процедура устанавливает в регистре DS адрес  таблицы  векторов  прерывания
(INTTAB) и передает адрес элемента таблицы  для  INT  9  (KBADDR)  в  поле
KBSAVE в  резидентной  процедуре.  Следующим  шагом  в  таблице  в  KBADDR
утанавливается адрес  резидентной  процедуры  (COLORS)  (первое  слово)  и
содержимое регистра CS (второе  слово).  Таким  образом,  KBADDR  содержит
теперь два измененных слова: смещение и значение адреса  из  регистра  CS,
которые вместе определяют адрес процедуры  COLORS  в  памяти,  куда  будут
направляться теперь все символы, поступающие с клавиатуры. Затем процедура
инициализации заносит в регистр DX размер процедуры COLORS  (адрес  INITZE
на один байт больше,  чем  адрес  конца  процедуры  COLORS)  и  прекращает
работу, используя INT 27H.
     Процедура COLORS является резидентной, и она получает управление  при
нажатии любой клавиши на клавиатуре.  Так как это  происходит  при  работе
других программ (например, DOS или  текстового  редактора),  то  процедура
должна сохранить все регистры, которые она использует (а  также  несколько
других на всякий случай).  Затем происходит вызов по адресу  KBSAVE,  т.е.
вызов подпрограммы обработки прерывания, после  чего  процедура  проверяет
флаг клавиатуры для определения нажатия клавиш Alt и Left Shift.  Если эти
клавиши  были  нажаты,  то  процедура  устанавливает  необходимые   цвета.
Завершающие  команды  включают  восстановление  всех  запомненных  вначале
регистров (в обратной последовательности) и выход из обработки  прерывания
по команде IRET.
     Поскольку приведенная программа  носит  иллюстративный  характер,  ее
можно  модифицировать  или  расширить  для  собственных  целей.  Некоторые
фирменные программы,  также  изменяющие  адрес  в  векторной  таблице  для
прерывания  9,  не  разрешают  конкурентное   использование    резидентных
программ, аналогичных рассмотренной в данной главе.


     ПОРТЫ
     ________________________________________________________________

     Порт представляет собой устройство,  которое  соединяет  процессор  с
внешним миром.  Через порт процессор получает сигналы с устройств ввода  и
посылает  сигналы  на  устройство  вывода.  Теоретически  процессор  может
управлять до 65 536 портами, начиная  с  нулевого  порта.  Для  управления
вводом-выводом непосредственно на уровне порта используются команды  IN  и
OUT:
          - Команда IN передает данные из  входного  порта  в  регистр  AL
     (байт) или в регистр АХ (слово). Формат команды:

               IN        регистр,порт

          - Команда OUT передает данные в порт из регистра AL  (байт)  или
     из регистра АХ (слово). Формат команды:

               OUT       порт,регистр

     Номер порта можно указывать статически или динамически:

          1. Статическое  указание  порта  возможно  при  непосредственном
     использовании значения от 0 до 255:

               Ввод:   IN     AL.порт#       ;Ввод одного байта
               Вывод:  OUT    порт#,АХ       ;Вывод одного слова

          2. Динамическое указание порта устанавливается в регистре DX  от
     0  до  65535.  Этот  метод  удобен  для  последовательной   обработки
     нескольких портов. Значение в регистре DX в этом случае увеличивается
     в цикле на 1. Пример ввода байта из порта 60Н:

               MOV     DX,60H  ;Порт 60Н (клавиатура)
               IN      AL,DX   ;Ввод байта

     Ниже приведен список некоторых  портов  (номера  в  шестнадцатиричном
представлении):

          21        Регистры маски прерывании.
          40...42   Таймер/счетчик
          60        Ввод с клавиатуры
          61        Звуковой порт (биты 0 и 1)
          201       Управление  играми
          3B0...3BF Монохромный дисплей и параллельный адаптер печати
          3D0...3DF Цветной/графический  адаптер
          3F0...3F7 Дисковый контроллер

     Если, например, программа  запрашивает  ввод  с  клавиатуры,  то  она
выдает команду прерывания INT 16H.  В этом  случае  система  устанавливает
связь с BIOS, которая с помощью команды IN вводит байт с порта 60Н.
     На практике  рекомендуется  пользоваться  прерываниями  DOS  и  BIOS.
Однако можно также успешно обойтись без BIOS  при  работе  с  портами  21,
40...42, 60 и 201. Листинги BIOS  в  техническом  руководстве  по  IBM  PC
содержат различные примеры команд IN и OUT.


     ГЕНЕРАЦИЯ ЗВУКА
     ________________________________________________________________

     Компьютер имеет возможность генерировать звук посредством встроенного
динамика с постоянным  магнитом.  Можно  выбрать  один  из  двух  способов
управления динамиком или использовать оба в комбинации:  1)  использование
бита  1  порта  21  Н  для   активизации    микросхемы    Intel    8255A-5
(программируемый периферийный интерфейс) (РР1); 2) использование  триггера
программируемого  интервального  таймера  Intel  8353-5  (PIT).    Часовой
генератор выдает сигнал с  частотой  1,19318  МГц.  Таймер  PPI  управляет
триггером 2 через бит 0 порта 61 Н.
     Программа на рис.23.3 генерирует серию звуковых  нот  с  возрастающей
частотой.  Значение в поле DURTION  формирует  продолжительность  звучания
каждой ноты, а значение в поле TONE определяет частоту звучания.  В начале
работы программа считывает содержимое порта 61 Н  и  сохраняет  полученное
значение.  Команда CLI сбрасывает флаг прерываний, обеспечивая равномерное
звучание.  Интервальный таймер генерирует 18,2 такта в секунду,  что  (при
отсутствии CLI) прерывает выполнение программы и вызывает появление звука.
     Значение поля TONE определяет частоту звука:  большие  значения  дают
низкую частоту, а малые - высокую.  После того, как  подпрограмма  BIOSPKR
исполнит очередную ноту, она увеличивает частоту звука посредством  сдвига
вправо на 1 бит значения в поле TONE (т.е. делит значение поля TONE на 2).
Так  как  уменьшение  TONE  в  данном  примере  приводит   к    сокращению
продолжительности звучания,  то  подпрограмма  также  увеличивает  DURTION
посредством сдвига его значения на один  бит  влево,  т.е.  удваивает  это
значение.
     Программа завершается, когда содержимое поля TONE уменьшится до нуля.
Начальные значения  в  полях  DURTION  и  TONE  не  имеют  принципиального
значения.  Можно  поэкспериментировать  с  другими  значениями,  а   также
испытать  выполнение  без  команды  CLI.  Можно  изменить  программу   для
генерации звуков с уменьшающейся частотой, установив для этого в поле TONE
значение 01, а в поле DURTION - некоторое большее значение. В каждом цикле
при этом необходимо увеличивать значение в поле TONE и уменьшать  значение
в поле. DURTION. При достижении нуля в DURTION программу можно завершить.
     Можно использовать любые варианты исполнения последовательности  нот,
например, для привлечения внимания пользователя.

__________________________________________________________________________

TITLE   SOUND   (COM) Процедура для генерации звука
SOUNSG  SEGMENT PARA 'Code'
        ASSUME  CS:SOUNG,DS:SOUNG,SS:SOUNG
        ORG     100H
BEGIN:  JMP     SHORT MAIN
; -------------------------------------------------------
DURTION DW      1000            ;Время звучания
TONE    DW      256H            ;Высота (частота) звука
; -------------------------------------------------------
MAIN    PROC    NEAR
        IN      AL,61H          ;Получить и сохранить
        PUSH    AX              ; данные порта
        CLI                     ;Запретить прерывания
        CALL    B10SPKR         ;Произвести звук
        POP     AX              ;Восстановить значение
        OUT     61H,AL          ; порта
        STI                     ;Разрешить прерывания
        RET
MAIN    ENDP

B10SPKR PROC    NEAR
B20:    MOV     DX,DURTION      ;Установить время звучания
B30:
        AND     AL,11111100B    ;Очистить биты 0 и 1
        OUT     61H,AL          ;Передать на динамик
        MOV     CX,TONE         ;Установить частоту
B40:
        LOOP    B40             ;Задержка времени
        OR      AL,00000010B    ;Установить бит 1
        OUT     61H,AL          ;Передать на динамик
        MOV     CX,TONE         ;становить частоту
B50:
        LOOP    B50             ;Задержка времени
        DEC     DX              ;Уменьшить время звучания
        JNZ     B30             ;Продолжать?
        SHL     DURTION,1       ; нет - увеличить время,
        SHR     TONE,1          ; сократить частоту
        JNZ     B20             ;Нулевая частота?
        RET                     ; да - выйти
B10SPKR ENDP

SOUNSG  ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.23.3 Генерация звука



ГЛАВА 24                          Справочник по директивам языка Ассемблер
__________________________________________________________________________

     Ц е л ь: подробно описать операторы и директивы языка Ассемблер.


     ВВЕДЕНИЕ
     ________________________________________________________________

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


     ИНДЕКСНАЯ АДРЕСАЦИЯ ПАМЯТИ
     ________________________________________________________________

     При прямой адресации памяти в одном из операндов команды  указывается
имя определенной переменной, например для переменной COUNTER:

               ADD  CX,COUNTER

     Во  время  выполнения  программы  процессор   локализует    указанную
переменную в памяти путем объединения величины смещения к этой  переменной
с адресом сегмента данных.
     При индексной адресации памяти ссылка на операнд  определяется  через
базовый или индексный регистр, константы, переменные  смещения  и  простые
переменные.  Квадратные скобки, определяющие операнды индексной адресации,
действуют  как  знак  плюс  (+).  Для  индексном  адресации  памяти  можно
использовать:

          - базовый регистр BX в виде [BX] вместе с  сегментным  регистром
     DS или базовый регистр BP в виде [BP] вместе с  сегментным  регистром
     SS. Например, с помощью команды

               MOV  DX,[BX]        ;Базовый регистр

     в регистр DX пересылается элемент, взятый по относительному адресу  в
     регистре BX и абсолютному адресу сегмента в регистре DS;
          - индексный регистр DI в виде [DI] или индексный  регистр  SI  в
     виде [SI], оба вместе с сегментным регистром DS.  Например, с помощью
     команды

               MOV  AX,[SI]        ;Индексный регистр

     в регистр AХ пересылается элемент, взятый по относительному адресу  в
     регистре SI и абсолютному адресу сегмента в регистре DS;
          - [константу],  содержащую  непосредственный  номер  или  имя  в
     квадратных скобках. Например, с помощью команды

               MOV  [BX+SI+4],AX   ;База+индекс+константа

     содержимое регистра АХ пересылается по адресу,  который  вычисляется,
     как сумма абсолютного адреса в регистре DS, относительного  адреса  в
     регистре BX, относительного адреса в регистре SI и константы 4;
          - смещение (+ или -) совместно с индексным операндом. Существует
     небольшое различие при использовании константы и смещения.  Например,
     с помощью команды

               MOV  DX,8[DI][4]    ;Смещение+индекс+константа

     в регистр DX пересылается элемент, взятый  по  абсолютному  адресу  в
     регистре DS, смещению  8,  относительному  адресу  в  регистре  DI  и
     константе 4.

     Эти операнды  можно  комбинировать  в  любой  последовательности.  Но
нельзя использовать одновременно два базовых регистра [BX +  BP]  или  два
индексных регистра [DI + SI].  Обычно индексированные адреса  используются
для локализации элементов данных в таблицах.


     ОПЕРАТОРЫ ЯЗЫКА АССЕМБЛЕР
     ________________________________________________________________

     Существует три  типа  ассемблерных  операторов:  операторы  атрибута,
операторы, возвращающие значение,  и  операторы.  специфицирующие  битовую
строку.  В  данном  разделе  рассмотрены  первые  два  типа    операторов.
Операторы, специфицирующие битовую строку, оператор MASK, счетчик сдвига и
оператор  WIDTH  относятся  к  директиве  RECORD  и  будет  рассмотрены  в
следующем разделе.


                             Оператор LENGTH
                            -----------------
     Оператор LENGTH возвращает число  элементов,  определенных  операндом
DUP. Например, следующая команда MOV заносит в регистр DX значение 10:

               TABLEA    DW     10 DUP(?)
                         ...
                         MOV    DX,LENGTH TABLEA

      Если операнд DUP отсутствует, то оператор LENGTH возвращает значение
01. См. операторы SIZE и TYPE в этом разделе.


                             Оператор  OFFSET
                            ------------------
     Оператор OFFSET возвращает относительный адрес переменной  или  метки
внутри сегмента данных или кода. Оператор имеет следующий формат:

               OFFSET переменная или метка

     Например, команда

               MOV  DX,OFFSET TABLEA

устанавливает в регистре DX относительный адрес (смещение) поля  TABLEA  в
сегменте данных. (Заметим, что команда LEA выполняет аналогичное действие,
но без использования оператора OFFSET.)


                              Оператор  PTR
                             ---------------
     Оператор PTR используется совместно с атрибутами типа BYTE, WORD  или
DWORD для локальной отмены определенных  типов  (DB,  DW  или  DD)  или  с
атрибутами NEAR или FAR для отмены значения дистанции по умолчанию. Формат
оператора следующий:

               тип  PTR  выражение

В поле "тип" указывается новый атрибут,  например  BYTE.  Выражение  имеет
ссылку на переменную или константу.  Приведем несколько примеров оператора
PTR:

          FLDB DB        22H
               DB        35H
          FLDW DW        2672H               ;0бьектный код 7226
               MOV       AН,BYTE PTR FLDW    ;Пересылает 1-й байт (72)
               ADD       BL,BYTE PTR FLDW+1  ;Прибавляет 2-й байт (26)
               MOV       BYTE PTR FLDW,05    ;Пересылает 05 в 1-й байт
               MOV       AX,WORD PTR FLDB    ;3аносит в АХ байты (2235)
               CALL      FAR PTR[BX]         ;Длинный вызов процедуры

     Директива LABEL, описанная в следующем  разделе,  выполняет  функцию,
аналогичную оператору PTR.


                               Оператор SEG
                              --------------
     Оператор  SEG  возвращает  адрес  сегмента,  в  котором   расположена
указанная переменная или метка. Наиболее подходящим является использование
этого  оператора  в  программах,  состоящих   из    нескольких    отдельно
ассемблируемых сегментов. Формат оператора:

               SEG переменная или метка

     Примеры применения оператора SEG в командах MOV:

               MOV     DX,SEG FLOW    ;Адрес сегмента данных
               MOV     DX,SEG A20     ;Адрес сегмента кода


                              Оператор SHORT
                             ----------------
     Назначение оператора SHORT - модификация атрибута NEAR в команде JMP,
если переход не превышает границы +127 и -128 байт:

               JMP     SHORT метка

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


                              Оператор SIZE
                             ---------------
     Оператор SIZE возвращает произведение длины  LENGTH  и  типа  TYPE  и
полезен  только  при  ссылках  на  переменную  с  операндом  DUP.   Формат
оператора:

               SIZE переменная

     См. пример для оператора TYPE.


                              Оператор TYPE
                             ---------------
     Оператор TYPE возвращает число  байтов,  соответствующее  определению
указанной переменной:

               Определение    Число байтов

               DB             1
               DW             2
               DD             4
               DQ             8
               DT             10
               STRUC          Число байтов, определённых в STRUC
               NEAR метка     FFFF
               FAR метка      FFFE

Формат оператора TYPE:

               TYPE      переменная или метка

Ниже приведены примеры, иллюстрирующие применение операторов TYPE,  LENGTH
и SIZE:

FLDB      DB   ?
TABLEA    DW   20 DUP(?)           ;Определение 20 слов
          ...
          MOV  AX,TYPE FLDB        ;AX = 0001
          MOV  AX,TYPE TABLEA      ;AX = 0002
          MOV  CX,LENGTH TABLEA    ;CX = 000A (10)
          MOV  DX,SIZE TABLEA      ;DX = 0014 (20)

     Так как область TABLEA определена как DW, то оператор TYPE возвращает
0002Н, LENGTH - 000АН (соответственно операнду DUP) и SIZE -  произведение
типа и длины, т.е. 14Н (20).


     ДИРЕКТИВЫ АССЕМБЛЕРА
     ________________________________________________________________

     В данном разделе описано большинство ассемблерных  директив.  В  гл.5
были подробно рассмотрены директивы  для  определения  данных  (DB,  DW  и
проч.).


                             Директива ASSUME
                            ------------------
     Назначение директивы ASSUME - установить для ассемблера  связь  между
сегментами и сегментными регистрами CS, DS, ES и SS. Формат директивы:

          ASSUME    сегментный_регистр:имя   [, ... ]

     В директиве указываются имена сегментных регистров, групп  (GROUP)  и
выражений SEG. Одна директива ASSUME может назначить до четырех сегментных
регистров в любой последовательности, например:

          ASSUME    CS:CODESG,DS:DATASG,SS:STACK,ES:DATASG

     Для отмены любого ранее назначенного в директиве  ASSUME  сегментного
регистра необходимо использовать ключевое слово NOTHING:

          ASSUME    ES:NOTHING

     Если, например, регистр DS оказался не назначен или отменен  ключевым
словом NOTHING, то для ссылки к элементу из  сегмента  данных  в  командах
используется операнд со ссылкой к регистру DS:

          MOV       AX,DS:[BX]     ;Использование индексного адреса
          MOV       AX,DS:FLDW     ;Пересылка содержимого поля FLDW

     Конечно, регистр DS должен содержать правильное значение  сегментного
адреса.

                             Директива EXTRN
                            -----------------
     Назначение директивы EXTRN - информировать ассемблер о  переменных  и
метках, которые определены в других модулях, но имеют  ссылки  из  данного
модуля. Формат директивы:

          EXTRN     имя: тип [, ... ]

Директива EXTRN подробно рассмотрена в гл.21.


                             Директива GROUP
                            -----------------
     Программа может  содержать  несколько  сегментов  одного  типа  (код,
данные, стек).  Назначение директивы GROUP - собрать  однотипные  сегменты
под одно имя так, чтобы они поместились в один сегмент объемом  64  Кбайт,
формат директивы:

               имя     GROUP  имя сегмента  [, ... ]

     Следующая директива GROUP объединяет SEG1 и SEG2 в одном ассемблерном
модуле:

               GROUPX         GROUP          SEG1,SEG2
               SEG1           SEGMENT        PARA 'CODE'
               ASSUME         CS:GROUPX
               SEG1           ENDS
               SEG2           SEGMENT        PARA 'CODE'
               ASSUME         CS:GROUPX
               SEG2           ENDS


                            Директива INCLUDE
                           -------------------
     Отдельные  фрагменты  ассемблерного  кода  или  макрокоманды    могут
использоваться  в  различных  программах.  Для  этого  такие  фрагменты  и
макрокоманды  записываются  в  отдельные  дисковые  файлы,  доступные  для
использования  из  любых  программ.    Пусть    некоторая    подпрограмма,
преобразующая ASCII-код в двоичное представление, записана на  диске  С  в
файле по имени CONVERT.LIB.  Для доступа к этому файлу необходимо  указать
директиву

               INCLUDE C:CONVERT.LIB

причем в том  месте  исходной  программы,  где  должна  быть  закодирована
подпрограмма преобразования  ASCII-кода.  В  результате  ассемблер  найдет
необходимый файл на диске и вставит его содержимое в  исходную  программу.
(Если файл не будет найден, то ассемблер выдаст соответствующее  сообщение
об ошибке и директива INCLUDE будет игнорирована.)
     Для каждой вставленной строки ассемблер выводит  в  LST-файл  в  30-й
колонке символ С (исходный текст в LST-файле начинается с 33-й колонки).
      В гл.20 (Макрокоманды) дан практический пример директивы  INCLUDE  и
дано объяснение, каким образом можно использовать эту директиву  только  в
первом проходе ассемблера.


                             Директива LABEL
                            -----------------
     Директива LABEL позволяет переопределять атрибут определенного имени.
Формат директивы:

               имя  LABEL     тип

В  качестве  типа  можно  использовать  BYTE,  WORD    или    DWORD    для
переопределения областей данных  или  имен  структур  или  битовых  строк.
Директивой LABEL можно переопределить выполнимый код, как  NEAR  или  FAR.
Эта директива позволяет, например, определить некоторое поле и как  DB,  и
как DW. Ниже проиллюстрировано использование типов BYTE и WORD:

               REDEFB  LABEL  BYTE
               FIELDW  DW     2532H
               REDEFW  LABEL  WORD
               FIELDB  DB     25H
                       DB     32H
                       MOV    AL,REDEFB      ;Пересылка первого байта
                       MOV    BX,REDEFW      ;Пересылка двух байтов

     Первая команда MOV пересылает только первый байт поля FIELDW.  Вторая
команда MOV пересылает два байта, начинающихся по адресу FIELDB.  Оператор
PTR выполняет аналогичные действия.


                              Директива NAME
                             ----------------
     Директива NAME обеспечивает другой способ назначения имени модулю:

               NAME  имя

Ассемблер выбирает имя модуля в следующем порядке:

          1) если директива NAME присутствует, то  ее  операнд  становится
     именем модуля;
          2) если директива  NAME  отсутствует,  то  ассемблер  использует
     первые шесть символов из директивы TITLE;
          3) если обе директивы NAME и TITLE отсутствуют, то именем модуля
     становится имя исходного файла.

     Выбранное имя передается ассемблером в компоновщик.


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

          Смещение    Имя     Операция     Операнд     Адресный счетчик

             00       FLDA      DW          2542H             02
             02       FLDB      DB          36H               03
             03       FLDC      DW          212EH             05
             05       FLDD      DD          00000705H         09

     Начальное значение  адресного  счетчика  -  00.  Так  как  поле  FLDA
занимает два байта, то для получения адреса следующего  элемента  адресный
счетчик увеличивается до значения 02. Поле FLDB занимает один байт, значит
значение адресного счетчика увеличивается  до  значения  03  и  т.д..  Для
изменения значения адресного счетчика и соответственно  адреса  следующего
определяемого элемента используется директива ORG. Формат директивы:

               OR6  выражение

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

          Смещение    Имя   Операция    Операнд      Адресный счетчик

                              ORG          0                00
             00       FLDX    DB           ?                01
             01       FLDY    DW           ?                02
             03       FLDZ    DB           ?                04
                              ORG          $+5              09

     Первая директива ORG возвращает адресный счетчик в нулевое  значение.
Поля FLDX, FLDY и FLDZ определяют те же области памяти, что и  поля  FLDA,
FLDB и FLDC:

            Смещение:  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
                         |       |   |       |
                       FLDA    FLDB FLDC   FLDD
                         |   |       |
                       FLDX FLDY    FLDZ

     Операнд, содержащий символ доллара ($), как во второй директиве  ORG,
имеет текущее значение адресного  счетчика.  Таким  образом,  операнд  $+5
устанавливает адресный счетчик равным 04 + 5 = 09, что представляет  собой
то же значение, что и после определения поля FLDD.
     Метка FLDC указывает на поле длиной  в  одно  слово,  находящееся  по
смещению 03, а метка FLDZ  указывает  на  однобайтовое  поле  по  тому  же
смещению:

               MOV    AX,FLOC        ;Одно слово
               MOV    AL,FLDZ        ;Oдин байт

     Директиву ORG можно использовать для переопределения областей памяти.
При этом следует правильно устанавливать адресный счетчик и учитывать  все
переопределяемые адреса памяти.  Кроме того, новые  переменные  не  должны
определять  константы,  так  как  при  этом  будут  перекрыты   константы,
определенные ранее.  Директиву ORG нельзя использовать внутри  определения
STRUCT.


                              Директива PROC
                             ----------------
     Любая процедура представляет собой совокупность  кодов,  начинающуюся
директивой PROC и завершающуюся  директивой  ENDP.  Обычно  эти  директивы
используются для  подпрограмм  в  кодовом  сегменте.  Ассемблер  допускает
переход на процедуру с помощью команды JMP, но обычной практикой  является
использование команды CALL для  вызова  процедуры  и  RET  для  выхода  из
процедуры.
     Процедура, находящаяся в  одном  сегменте  с  вызывающей  процедурой,
имеет тип NEAR:

               имя-процедуры  PROC    [NEAR]

Если операнд опущен, то ассемблер принимает значение  NEAR  no  умолчанию.
Если процедура является внешней по отношению к вызывающему сегменту, то ее
вызов может осуществляться только командой CALL, а сама  процедура  должна
быть объявлена  как  PUBLIC.  Более  того,  если  в  вызываемой  процедуре
используется другое значение ASSUME CS, то необходимо  кодировать  атрибут
FAR:

                              PUBLIC  имя-процедуры,
               имя-процедуры  PROC    FAR

     При  вызове  любой  процедуры  с  помощью  команды  CALL   необходимо
обеспечить возврат по команде RET.


                             Директива PUBLIC
                            ------------------
Назначение директивы PUBLIC - информировать ассемблер,  что  на  указанные
имена имеются ссылки из других ассемблерных модулей. Формат директивы:

               PUBLIC имя [,...]

     Директива PUBLIC подробно описана в гл.21.


                             Директива RECORD
                            ------------------
     Директива  RECORD  позволяет  определять  битовые  строки.  Одно   из
назначений  этой  директивы  -  определить  однобитовые  или  многобитовые
переключатели. Формат директивы:

               имя RECORD имя-поля:ширина [=выражение] [, ... ]

Имя  директивы  и  имена   полей    могут    быть    любыми    уникальными
идентификаторами.  После каждого имени поля следует двоеточие (:) и размер
поля в битах, которое может быть от 1 до 16 бит:

               Число определенных битов      Принимаемый размер

                         1...8                         8
                         9...16                       16

     Любой размер поля до 8 бит представляется восемью битами, а от  9  до
16 бит - представляется шестнадцатью  битами,  выровненными  справа  (если
необходимо). Рассмотрим следующую директиву RECORD:

               BITREC RECORD BIT1:3,BIT2:7,BIT3:6

Имя BIT1 определяет первые 3 бит поля BITREC, BIT2 -  следующие  7  бит  и
BIT3 - последние 6 бит.  Общее число битов - 16, т.е.  одно  слово.  Можно
инициализировать поле BITREC, например, следующим образом:

          BITREC2 RECORD BIT1:3=101B,BIT2:7=0110110B,BIT3:011010B

     Предположим, что директива RECORD находится перед  сегментом  данных.
Тогда внутри сегмента данных должен быть другой оператор, который  отводит
память под данные.  Для этого необходимо определить  уникальное  имя,  имя
директивы RECORD и операнд, состоящий из угловых скобок (символы меньше  и
больше):

               DEFBITS BITREC <>

Данное определение генерирует объектный код AD9A. который записывается как
9AAD в сегмент  данных.  В  угловых  скобках  может  находиться  значение,
переопределяющее BITREC.
     Программа на  рис.24.1  иллюстрирует  определение  BITREC  директивой
RECORD,  но без начальных значений. В этом случае соответствующий оператор
в сегменте данных инициализирует каждое поле операндом в угловых скобках.
     Дополнительно к директиве RECORD  имеются  операторы  WIDTH,  MASK  и
фактор  сдвига.  Использование  этих   операторов    позволяет    изменять
определение директивы RECORD без изменения команд, которые имеют ссылки на
директиву RECORD.


     О п е р а т о р  WIDTH.  Оператор  WIDTH  возвращает  число  битов  в
директиве RECORD или в одном из ее полей.  На  рис.24.1  после  метки  А10
имеется два примера  оператора  WIDTH.  Первая  команда  MOV  загружает  в
регистр BH число битов во всем поле RECORD BITREC (16 бит); вторая команда
MOV загружает в регистр AL число битов  в  поле  BIT2  (7  бит).  В  обоих
случаях ассемблер генерирует для числа битов непосредственный операнд.

__________________________________________________________________________

                       TITLE   RECORD (COM) Проверка директивы RECORD
0000            CODESG SEGMENT PARA 'Code'
                       ASSUME  CS:CODESG,DS:CODESG,SS:CODESG
0100                   ORG     100H
0100 EB 02      BEGIN:         JMP    SHORT MAIN
                ; -----------------------------------------------------
                BITREC RECORD  BIT1:3,BIT2:7,BIT3:6    ;Определить запись
0102 9A AD      DEFBITS BITREC <101B,0110110B,011010B> ;Инициализировать биты
                ; -----------------------------------------------------
0104            MAIN   PROC    NEAR
0104            A10:                             ;Ширина:
0104 B7 10             MOV     BH,WIDTH BITREC   ; записи (16)
0106 B0 07             MOV     AL,WIDTH BIT2     ; поля (07)
0108            B10:                             ;Величина сдвига:
0108 B1 0D             MOV     CL,BIT1           ; шест.0D
010A B1 06             MOV     CL,BIT2           ;      06
010C B1 00             MOV     CL,BIT3           ;      00
010E            C10:                             ;Маска:
010E B8 E000           MOV     AX,MASK BIT1      ; шест.E000
0111 BB 1FC0           MOV     BX,MASK BIT2      ;      1FC0
0114 B9 003F           MOV     CX,MASK BIT3      ;      003F
0117            D10:                             ;Выделение BIT2:
0117 A1 0102 R         MOV     AX,DEFBITS        ; получить запись,
011A 25 1FC0           AND     AX,MASK BIT2      ; очистить BIT1 и BIT3,
011D B1 06             MOV     CL,BIT2           ; получить сдвиг 06,
011F D3 E8             SHR     AX,CL             ; сдвинуть вправо
0121            E10:                             ;Выделение BIT1:
0121 A1 0102 R         MOV     AX,DEFBITS        ; получить запись,
0124 B1 0D             MOV     CL,BIT1           ; получить сдвиг 13,
0126 D3 E8             SHR     AX,CL             ; сдвинуть вправо
0128 C3                RET
0129                   MAIN    ENDP
0129           CODESG  ENDS
                       END     BEGIN
_____________________________________________________________________

Structures and records:
               N a m e           Widht  # fields
                                        Shift   Widht   Mask    Initial
   BITREC . . . . . . . . . . .  0010   0003
   BIT1 . . . . . . . . . . . .  000D   0003    E000    0000
   BIT2 . . . . . . . . . . . . .       0006    0007    1FC0    0000
   BIT3 . . . . . . . . . . . .  0000   0006    003F    0000

Segments and Groups:
                N a m e          Size   Align   Combine Class
CODESG . . . . . . . . . . . .   0129   PARA    NONE    'CODE'

Symbols:
                N a m e         Type    Value   Attr
A10. . . . . . . . . . . . . . L NEAR   0104    CODESG
B10. . . . . . . . . . . . . . L NEAR   0108    CODESG
BEGIN. . . . . . . . . . . . . L NEAR   0100    CODESG
C10. . . . . . . . . . . . . . L NEAR   010E    CODESG
D10. . . . . . . . . . . . . . L NEAR   0117    CODESG
DEFBITS. . . . . . . . . . . . L WORD   0102    CODESG
E10. . . . . . . . . . . . . . L NEAR   0121    CODESG
MAIN . . . . . . . . . . . . . N PROC   0104    CODESG  Length =0025
__________________________________________________________________________

     Рис.24.1. Использование диpективы RECORD


     Ф а к т о р  с д в и г а. Прямая ссылка на элемент в RECORD,например:

               MOV    CL,BIT2

в действительности не имеет отношения к  содержимому  BIT2.  Вместо  этого
ассемблер генерирует непосредственный операнд,  который  содержит  "фактор
сдвига",  помогающий  изолировать  необходимое   поле.    Непосредственное
значение представляет собой число, на которое необходимо сдвинуть BIT2 для
выравнивания справа.  На рис.24.1 после метки  В10  имеются  три  команды,
которые загружают в регистр CL фактор сдвига для полей BIT1, BIT2 и BITЗ.

     О п е р а т о р  MASK.  Оператор MASK возвращает "маску" из единичных
битовых  значений,  которые  представляют  специфицированное  поле,  иными
словами, определяют битовые  позиции,  которые  занимает  поле.  Например,
оператор MASK  для  каждого  из  полей,  определенных  в  области  BITREC,
возвращает следующие значения:

               Поле      Двоичное значение   Шестнадцатиричное значение

               В1Т1      1110000000000000              Е000
               В1Т2      0001111111000000              1FC0
               В1ТЗ      0000000000111111              003F

     На рис.24.1 три команды после метки С10 загружают в регистры значения
оператора MASK для полей BIT1, BIT2 и BITЗ.  Команды после меток D10 и Е10
иллюстрируют выделение  значений  полей  BIТ2  и  BIТ1  соответственно  из
области BITREC.  После метки D10 в регистр  АХ  загружается  все  значение
области, определенной директивой RECORD,  а  затем  из  этого  значения  с
помощью оператора MASK выделяются только биты поля BIТ2:

               Область RECORD:     101 0110110 011010
               AND MASK BIТ2:      000 1111111 000000
               Результат:          000 0110110 000000

     В результате сбрасываются все биты, кроме принадлежащих к полю  BIТ2.
Следующие две команды приводят к сдвигу содержимого регистра АХ  на  шесть
битов для выравнивания справа:

               0000000000110110       (0036Н)

     После метки Е10  в  регистр  AХ  загружается  все  значение  области,
определенной директивой RECORD, и так как BIТ1 является самым левым полем,
то в примере используется только фактор для сдвига значения вправо  на  13
бит:

               0000000000000101       (0005Н)


                            Директива SEGMENT
                           -------------------
     Ассемблерный модуль может состоять из  одного  или  более  сегментов,
части сегмента или даже частей нескольких сегментов. Формат директивы:

          имя_сегмента SEGMENT [выравнивание]  [объединение] [класс]
                           .
                           .
                           .
          имя_сегмента   ENDS

Все  операнды  являются  необязательными.  Ниже  описаны   операнды    для
выравнивания, объединения и указания класса.

     В ы р а в н и в а н и е.  Операнд выравнивания  определяет  начальную
границу сегмента, например

               PAGE   = xxx00
               PARA   = хххх0 (граница по умолчанию)
               WORD   = ххххe (четная граница)
               BYTE   = ххххх

где х - любая шестнадцатиричная цифра,
    е - четная шестнадцатиричная цифра.

     О б ъ е д и н е н и е. Операнд объединения указывает способ обработки
сегмента, при компоновке:

     NONE: Значение по умолчанию. Сегмент должен быть логически отделен от
     других  сегментов,  хотя  физически   он    может    быть    смежным.
     Предполагается, что сегмент имеет собственный базовый адрес;

     PUBLIC: Все PUBLIC  -  сегменты,  имеющие  одинаковое  имя  и  класс,
     загружаются компоновщиком в смежные области. Все такие сегменты имеют
     один общий базовый адрес;

     STACK: Для компоновщика операнд STACK аналогичен операнду  PUBLIC.  В
     любой компонуемой программе должен быть  определен  по  крайней  мере
     один сегмент STACK.  Если объявлено более одного стека,  то  стековый
     указатель (SP) устанавливается на начало первого стека;

     COMMON:  Для  сегментов  COMMON  с  одинаковыми  именами  и  классами
     компоновщик устанавливает один общий базовый  адрес.  При  выполнении
     происходит наложение второго сегмента на первый. Размер общей области
     определяется самым длинным сегментом;

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

               VIDEO_RAM      SEGMENT AT 0B800H

     Класс:  Операнд  класс  может  содержать  любое    правильное    имя,
     заключенное  в  одиночные  кавычки.  Данный   операнд    используется
     компоновщиком для обработки сегментов,  имеющих  одинаковые  имена  и
     классы. Типичными примерами являются классы 'STACK' и 'CODE'.

     Следующие два сегмента объединяются компоновщиком в  один  физический
сегмент при одном значении сегментного регистра:

                         --------------------------------
          Ассемблерный   SEG1 SEGMENT   PARA PUBLIC 'CODE'
          модуль 1              ASSUME  CS:SEG1
                                ...
                         SEG1   ENDS
                         --------------------------------
          Ассемблерный   SEG2 SEGMENT   PARA PUBLIC 'CODE'
          модуль 2              ASSUME  CS:SEG1
                                ...
                         SEG2   ENDS
                         --------------------------------

     Сегменты могут быть вложенными один в другой:

                         SEG1   SEGMENT
                                ...               Начало SEG1
                         SEG2   SEGMENT
                                ...               Область SEG2
                         SEG2   ENDS
                                ...               Конец SEG1
                         SEG1   ENDS

     Для объединения сегментов в группы используйте директиву GROUP.


                             Директива STRUC
                            -----------------
     Директива STRUC  обеспечивает  определение  различных  полей  в  виде
структуры.  Данная директива не поддерживается  в  малом  ассемблере  ASM.
Формат директивы:

               Имя-структуры  STRUC
                              ...
                              [определение полей данных]
                              ...
               Имя-структуры  ENDS

     Структура  начинается  собственным  именем  в  директиве   STRUC    и
завершается таким же именем в директиве ENDS.  Ассемблер записывает  поля;
определенные в структуре, одно за другим от начала структуры.  Правильными
операторами определения полей являются DB, DW, DD и DT  с  указанием  имен
или без них.
     На рис.24.2 директива STRUC определяет список параметров PARLIST  для
ввода имени с клавиатуры.  Следующий далее оператор  выделяет  память  под
данную структуру:

               PARAMS    PARLIST <>

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

               MOV       AL,PARAMS.ACTLEN

     Используя оператор выделения памяти, можно переопределить  содержимое
полей внутри  структуры.  Правила  для  практического  использования  этой
возможности можно найти в руководстве по Ассемблеру.

__________________________________________________________________________

                        TITLE   DSTRUC  (COM) Определение структуры
0000                    CODESG  SEGMENT PARA 'Code'
                                ASSUME  CS:CODESG,DS:CODESG,SS:CODESG
0100                            ORG     100H
0100 EB 29              BEGIN:  JMP     SHORT MAIN
                        ; ---------------------------------------------
                        PARLIST         STRUC           ;Список параметров
0000 19                 MAXLEN  DB      25              ;
0001 ??                 ACTLEN  DB      ?               ;
0002    19 [ 20 ]       NAMEIN  DB      25 DUP(' ')     ;
001B                    PARLIST         ENDS
                                                        ;
0102 19                 PARAMS  PARLIST <>              ;Область структуры
0103 ??
0104    19 [ 20 ]
011D 57 68 61 74 20 69  PROMPT  DB      'What is name?', 'S'
     73 20 6E 61 6D 65
     3F 24
                        ; ---------------------------------------------
012B                    MAIN    PROC    NEAR
012B B4 09                      MOV     AH,09            ;Выдать запрос
012D 8D 16 011D R               LEA     DX,PROMPT
0131 CD 21                      INT     21H
0133 B4 0A                      MOV     AH,0AH           ;Получить ввод
0135 8D 16 0102 R               LEA     DX,PARAMS
0139 CD 21                      INT     21H
013B A0 0103 R                  MOV     AL,PARAMS.ACTLEN ;Длина ввода
                        ;       ...
013E C3                         RET
013F                    MAIN    ENDP
013F                    CODESG  ENDS
                                END     BEGIN


Structures and records:
                N a m e          Width  # fields
                                 Shift  Width   Masc    Initial
PARLIST. . . . . . . . . . . . . 001B   0003
  MAXLEN . . . . . . . . . . . . 0000
  ACTLEN . . . . . . . . . . . . 0001
  NAMEIN . . . . . . . . . . . . 0002

Segments and Groups:
                N a m e          Size   Align   Combine Class
CODESG . . . . . . . . . . . . . 013F   PARA    NONE    'CODE'

Symbols:
                N a m e          Type   Value   Attr
BEGIN. . . . . . . . . . . . . L NEAR   0100    CODESG
MAIN . . . . . . . . . . . . . N PROC   012B    CODESG  Length =0014
PARAMS . . . . . . . . . . . . L 001B   0102    CODESG
PROMPT . . . . . . . . . . . . L BYTE   011D    CODESG
__________________________________________________________________________

     Рис.24.2. Пpимеp опpеделения стpуктуpы



ГЛАВА 25                            Справочник по командам языка Ассемблер
__________________________________________________________________________

     Ц е л ь: описать набор команд  Ассемблера  и  объяснить  их  машинные
коды.


     ВВЕДЕНИЕ
     ________________________________________________________________

     В данной главе приведены объяснения машинных кодов  и  перечислены  в
алфавитном порядке символические коды команд с указанием их назначений.
     Многие  специфические  команды  имеют  однобайтовые  машинные   коды,
например:

     Объектный код:      Символические команды:
          40             INC  AX        ;Увеличение AX на 1
          50             PUSH AX        ;Запись AХ в стек
          С3             RET  (short)   ;Короткий возврат из процедуры
          CB             RET  (far)     ;Длинный возврат из процедуры
          FD             STD            ;Остановка флага направления

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


     ОБОЗНАЧЕНИЕ РЕГИСТРОВ
     ________________________________________________________________

     Команды, использующие регистр, могут содержать три бита,  указывающих
на конкретный регистр, и один бит "w", определяющий размер регистра:  байт
или слово.  Кроме того,  лишь  некоторые  команды  обеспечивают  доступ  к
сегментным регистрам. На рис.25.1 показана полная идентификация регистров.
     Рассмотрим команду MOV с однобайтовым непосредственным операндом:

               MOV    АН,00   10110 100 00000000
                                  |   |
                                  w  rеg = AН

__________________________________________________________________________

                 Основные, базовые и индексные регистры:

                      Биты:       w = 0       w = 1
                       000          AL          AX
                       001          CL          CX
                       010          DL          DX
                       011          BL          BX
                       100          AH          SP
                       101          CH          BP
                       110          DH          SI
                       111          BH          DI

                        Биты:  Сегментный регистр:
                           00               ES
                           01               CS
                           10               SS
                           11               DS
__________________________________________________________________________

     Рис.25.1. Обозначение регистров


     В данном случае первый байт машинного кода указывает на  однобайтовый
размер (w = 0) и на регистр  AН  (100).  Следующая  команда  MOV  содержит
непосредственный двухбайтовый операнд:

               MOV     AX,00  10111 000 00000000 00000000
                                  |   |
                                  w  reg = AX

Первый байт машинного кода указывает на размер в одно  слово  (w=1)  и  на
регистр AХ  (000).  Не  следует  обобщать  приведенные  примеры,  так  как
указание регистра и бита w может быть в различных позициях кода.


     БАЙТ СПОСОБА АДРЕСАЦИИ
     ________________________________________________________________

     Байт способа адресации, если он присутствует,  занимает  второй  байт
машинного кода и состоит из следующих трех элементов:

          1) mod - двухбитового кода, имеющего значения 11 для  ссылки  на
     регистр и 00, 01 и 10 для ссылки на память;
          2) reg - трехбитового указателя регистра;
          3) r/m  -  трехбитового  указателя  регистра  или  памяти  (r  -
     регистр, m - адрес памяти).

     Кроме того, первый байт  машинного  кода  может  содержать  бит  "а",
который указывает направление потока между операндом 1 и операндом 2.
     Рассмотрим пример  сложения  содержимого  регистра  АХ  с  содержимым
регистра BX:

               ADD    BX,AX   00000011  11 011 000
                                    dw mod reg r/m

     В этом примере d=1 означает, что  mod  (11)  и  reg  (011)  описывают
операнд 1, а r/m (000) описывает операнд 2. Так как  бит  w=1,  то  размер
равен одному слову.  Таким образом, команда должна прибавить AX (OOQ) к BХ
(011).
     Второй байт команды в объектном коде указывает  большинство  способов
адресации памяти.  В следующем разделе способы  адресации  будут  подробно
рассмотрены.


                                 Биты MOD
                                ----------
     Два  бита  mod  определяют  адресацию  регистра  или  памяти.    Ниже
поясняется их назначение:

     00   биты г/m дают абсолютный  адрес,  байт  смещения  (относительный
          адрес) отсутствует;
     01   биты г/m дают  абсолютный  адрес  памяти  и  имеется  один  байт
          смещения;
     10   биты г/m дают абсолютный адрес и имеется два байта смещения;
     11   биты  г/m  определяют  регистр.  Бит  w  (в байте кода операции)
          определяет ссылку на восьми- или шестнадцатибитовый регистр.


                                 Биты REG
                                ----------
     Три бита  reg  (вместе  с  битом w) определяют конкретный восьми- или
шестнадцатибитовый регистр.


                                 Биты R/M
                                ----------
     Три бита г/m  (регистр/память)  совместно  с  битами  mod  определяют
способ адресации, как показано на рис.25.2.

__________________________________________________________________________

          r/m   mod=00    mod=01         mod=10      mod=1.1    mod=11
                                                       w=0        w=1
          000   BX+SI     BX+SI+disp     BX+SI+disp    AL         AX
          001   BX+DI     BX+DI+disp     BX+DI+disp    CL         CX
          010   BP+SI     BP+SI+disp     BP+SI+disp    DL         DX
          011   BP+DI     BP+DI+disp     BP+DI+disp    BL         BX
          100    SI        SI+disp         SI+disp     AH         SP
          101    DI        DI+disp         DI+disp     CH         BP
          110   Direct     BP+disp         BP+disp     DH         SI
          111    BX        BX+disp         BX+disp     BH         DI
__________________________________________________________________________

     Рис.25.2. Биты r/m


     ДВУХБАЙТОВЫЕ КОМАНДЫ
     ________________________________________________________________

     Рассмотрим пример сложения содержимого регистров BХ и AХ:

               ADD    BX,AX    0000 0011  11 011 000
                                      dw mod reg r/m

     d    1 означает,  что биты reg и w описывают операнд  1 (BХ),  а биты
          mod, r/m и w - Операнд 2 (AХ);
     w    1 определяет размер регистров в одно слово,
     mod  11 указывает, что операнд 2 является регистром;
     reg  011 указывает, что операнд 1 является регистром BХ;
     r/m  000 указывает, что операнд 2 является регистром AX.

     Рассмотрим пример умножения регистра AL на регистр BL:

               MUL    BL       11110110  11 100 011
                                      w mod reg r/m

Команда  MUL  предполагает,  что  регистр  AL  содержит  множимое.  Размер
регистра равен  одному  байту  (w  =  0),  mod  указывает  на  регистровую
операцию, г/m = 011 указывает на регистр BL.  В данном случае reg = 100 не
имеет смысла.


     ТРЕХБАЙТОВЫЕ КОМАНДЫ
     ________________________________________________________________

     Следующая команда MOV генерирует три байте машинного кода:

               MOV     mem,AX  10100001 dddddddd dddddddd

     Для команды пересылки из регистра AХ или AL необходимо знать, сколько
байтов участвует в операции: один или два. В данном примере w = 1 означает
слово, следовательно, предполагается 16-битовый регистр AХ.  Использование
во втором операнде регистра AL приведет к значению бита w = 0. Байты 2 и 3
содержат относительный адрес памяти. Команды, использующие регистры АХ или
AL, часто генерируют более эффективный (короткий) машинный код.


     ЧЕТЫРЕХБАЙТОВЫЕ КОМАНДЫ
     ________________________________________________________________

     Рассмотрим  пример  умножения  регистра  AL  на  значение  в  памяти.
Процессор  предполагает,  что  множимое  находится  в  регистре  AL    для
однобайтового умножения и в регистре AХ для Двухбайтового умножения:

               MUL    mem_byte         11110110  00 100 110
                                              w mod reg r/m

Для данной команды reg всегда имеет значение 100, mod =  00  указывает  на
операцию с памятью, a r/m=110  -  на  прямой  способ  адресации.  Машинная
команда также содержит два  следующих  байта,  определяющих  относительный
адрес памяти.
     Рассмотрим еще  один  пример,  иллюстрирующий  команду  LEA,  которая
всегда специфицирует двухбайтовый адрес:

               LEA     DX,mem 10001101  00 010 110
                                 LEA   mod rеg r/m

     Reg =010 означает регистр DX.  Mod =00 и  r/m=110  определяют  прямой
способ адресации памяти.  В следующих двух байтах содержится относительный
адрес.


     КОМАНДЫ В АЛФАВИТНОМ ПОРЯДКЕ
     ________________________________________________________________

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

addr           адрес памяти;
addr-high      первый байт адреса (старший);
addr-low       левый (младший) байт. адреса;
data           непосредственный операнд (8 бит при w=0 и 16 бит при w= 1);
data-high      правый (старший) байт непосредственного операнда;
data-low       левый (младший) байт непосредственного операнда;
disp           смещение (относительный адрес);
rеg            ссылка на регистр.


                AAA: Коррекция ASCII-формата для сложения
               -------------------------------------------
     О п е р а ц и я: Корректирует сумму двух ASCII-байтов в регистре  AL.
Если правые четыре бита регистра AL имеют значение больше 9  или  флаг  AF
установлен в 1,  то  команда  AAA  прибавляет  к  регистру  АН  единицу  и
устанавливает флаги AF и CF.  Команда всегда очищает четыре левых  бита  в
регистре AL.

     Ф л а г и: Команда воздействует на флаги AF и CF (флаги OF, PF, SF  и
ZF не определены).

     О б ъ е к т н ы й  к о д: 00110111 (без операндов).


                 AAD: Коррекция ASCII-формата для деления
                ------------------------------------------
     О п е р а ц и я: Корректирует ASCII-величины для деления. Команда AAD
используется перед делением неупакованных десятичных чисел в  регистре  AХ
(удаляет тройки ASCII-кода).  Эта команда корректирует делимое в  двоичное
значение в регистре AL для последующего двоичного деления.  Затем умножает
содержимое регистра AН на 10. прибавляет результат к содержимому  регистра
AL и очищает AН. Команда AAD не имеет операндов.

     Ф л а г и: Команда воздействует на флаги PF, CF, ZF (флаги AF CF и OF
не определены).

     О б ъ е к т н ы й  к о д: |11010101|00001010|.


                AAМ: Коррекция ASCII-формата для умножения
               --------------------------------------------
     О п е р а ц и я: Команда AAM используется  для  коррекции  результата
умножения двух неупакованных десятичных чисел.  Команда  делит  содержимое
регистра AL на 10, записывает частное в регистр AН, а  остаток  в  регистр
AL.

     Ф л а г и: Команда воздействует на флаги PF, SF и ZF (флаги AF  CF  и
OF не определены).

     О б ъ е к т н ы й  к о д: |11010100|00001010| (без операндов).


                AAS: Коррекция ASCII-формата для вычитания
               --------------------------------------------
     О п е р а ц и я: Корректирует разность двух ASCII-байтов  в  регистре
AL. Если первые четыре бита имеют значение больше 9 или флаг CF установлен
в 1, то команда AAS вычитает 6 из регистра AL и 1 из регистра АН, флаги AF
и CF при этом устанавливаются в 1. Команда  всегда  очищает  левые  четыре
бита в регистре AL.

     Ф л а г и: Команда воздействует на флаги AF и CF (флаги OF PF SF и ZF
не определены).

     О б ъ е к т н ы й  к о д: 00111111 (без операндов).


                        ADC: Сложение с переносом
                       ---------------------------
     О п е р а ц и я:   Обычно  используется  при  сложении   многословных
величин для учета бита переполнения в  последующих  фазах  операции.  Если
флаг CF установлен в 1, то команда ADC сначала прибавляет 1 к операнду  1.
Команда всегда прибавляет операнд 2 к операнду 1, аналогично команде ADD.

     Ф л а г и: Команда воздействует на флаги AF, CF, OF, PF, SF и ZF.

     О б ъ е к т н ы й  к о д (три формата):

          Регистр плюс регистр или память:
               |000100dw|modregr/m|
          Регистр АХ (AL) плюс непосредственное значение:
               |0001010w|-- data--|data, если w=1|
          Регистр или память плюс непосредственное значение:
                y100000sw|mod010r/m|--data--|data, если sw=01|


                       ADD: Сложение двоичных чисел
                      ------------------------------
     О п е р а ц и я: Прибавляет  один  байт  или  одно  слово  в  памяти,
регистре или непосредственно к содержимому регистра  или  прибавляет  один
байт или слово в регистре или непосредственно к памяти.


Страницы книги разрезаны по 70Кб, чтобы они не были гигантскими и недолго грузились, так что нажмите "Далее" чтобы читать дальше.
Назад  Далее

Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS