Тема: Структура EXE- и COM- программы. Вывод на экран.
Цель работы: Изучение структуры EXE- и COM-программы. Получение навыков вывода данных на экран монитора.
Задание: Разработать EXE-программу вывода символа на экран, и COM- программу вывода на экран строки.
Структура программы. Исходный программный модуль состоит из команд и директив. Команды управляют работой процессора, а директивы указывают ассемблеру и редактору связей, каким образом следует объединять, команды для создания модуля, который и станет работающей программой.
Команда на языке ассемблера состоит не более чем из четырех полей. Ниже приведен формат и пример команды с указанием названия его полей:
Метка Код операции Операнды; Комментарий
MET: MOVE AX, BX; Пересылка
Единственное обязательное поле – поле кода операции, определяющее команду, которую должен выполнить микропроцессор. Поле операндов определяется кодом операции и содержит дополнительную информацию о команде. Метка содержит в символическом виде адрес команды, что необходимо для организации переходов (ссылок). Поле комментария служит для удобства программиста и компилятором игнорируется.
|
|
Оператор директивы состоит из символического имени, кода псевдооперации, поля операндов и комментария. Структура директивы аналогична структуре команды. Второе поле – код псевдооперации определяет смысловое содержание директивы. Как и команды, у директивы есть операнды, причем их может быть один или несколько и они отделяются друг от друга запятыми. Допустимое число операндов в директиве определяется кодом псевдооперации. Например:
DB 0, 0, 0, 0, 0
END START
Директива может быть помечена символическим именем и содержать поле комментария. Символическое имя, стоящее в начале директивы распределения памяти, называется переменной. В отличие от метки команды после символического имени директивы двоеточие не ставиться.
Программа на языке ассемблера состоит из программных модулей, содержащихся в различных файлах. Каждый модуль, в свою очередь, состоит из операндов или директив ассемблера и заканчивается директивой END. Метка, стоящая после кода псевдооперации END, является точкой входа в программу.
Каждый модуль разбивается на отдельные части директивами сегментации, определяющими сегменты.
Каждый сегмент может быть также разбит на части. В общем случае информационные сегменты SS, ES и DS состоят из определений данных, а программный сегмент CS – из команд и директив, группирующих команды в блоки.
Программный сегмент может разбиваться на части директивами определения процедур – некоторых выделенных блоков программы. Как и для определения сегмента, имеются две такие директивы – директива начала PROC и директива конца ENDP. Процедура имеет имя, которое должно включаться в обе директивы, процедуры в сегменте могут располагаться последовательно одна за другой, могут быть также вложенными одна в другую.
|
|
Принципиальной особенностью COM-программы является то, что в отличие от EXE-программы, которая содержит отдельные сегменты данных, стека и кода, COM-программ, в большинстве случаев, может содержать лишь один основной сегмент (сегмент кода), в котором размещаются и код и данные и стек. Кроме того, EXE-программа, в отличие от COM-программы, содержит так называемый EXE-заголовок (256 байт), при помощи которого загрузчик выполняет настройку ссылок на сегменты в загруженном модуле, а так как и COM- и EXE- программа должна загружаться с адреса PSP:0100h (100h=256), COM-программа должна содержать в начале сегмента кода директиву позволяющую осуществить такую загрузку (ORG 100H).
Более подробно со структурой программ на языке ассемблера можно познакомиться в разделе «4.9. Структура программы на языке Ассемблера».
Ниже приведены примеры, иллюстрирующие основные особенности структуры EXE- и COM-программ, написанных на языке ассемблера:
Пример 2.1. Структура EXE-программы:
.MODEL SMALL
;Определение сегмента стека
.STACK 100h
;Определение сегмента данных
.DATA
SYMB DB '#';Описание переменной с именем SYMB
;типа Byte и со значением «#»
...;Определение других переменных
;Определение сегмента кода
.CODE
;Определение подпрограммы
PROC1 PROC
...;Текст подпрограммы
PROC1 ENDP
START:
XOR AX,AX;Точка входа в программу START
MOV AX, @data;и обязательная инициализация
MOV DS,AX;регистра DS в начале программы
CALL PROC1;Пример вызова подпрограммы
...;Текст программы
MOV AH,4CH;Операторы завершения программы
INT 21H
END START
END
Пример 2.2. Структура COM-программы:
.MODEL TINY
;Определение сегмента кода
.CODE
ORG 100H;Начало необходимое для COM-программы
START:
...;Текст программы
MOV AH,4CH
INT 21H;Операторы завершения программы
;===== Data =====
BUF DB 6;Определение переменной типа Byte
...;Определение других переменных
END START
END
Вывод на экран. Вывод информации в ассемблерных программах осуществляется обычно при помощи сервисных функций DOS (прерывание 21h) или BIOS (прерывание 10h). Процесс вывода состоит в следующем:
- определенные регистры микропроцессора загружаются выводимой информацией или адресом буфера, содержащего выводимую информацию;
- в регистр AH заносится номер используемой для операции вывода функции;
- инициируется прерывание.
Ниже представлен перечень функций прерывания 21h и 10h, использующихся для вывода информации.
Прерывание 21h.
Функция 02h
Вывод на дисплей.
Вход: AH=02h
DL=выводимый символ
Выход: нет
Описание: Посылает символ из DL на стандартный вывод. Обрабатывает символ Backspace (ASCII 8), перемещая курсор влево на одну позицию и оставляя его в новой позиции.
Функция 05h
Вывод на принтер.
Вход: AH=05h
DL= символ, записываемый на стандартный принтер
Выход: нет
Описание: Посылает символ в DL на стандартное устройство принтера, обычно LPT1. Команда DOS MODE может перенаправить этот вывод в последовательный порт.
Функция 09h
Выдать строку.
Вход: AH=09h
DS:DX=адрес строки, заканчивающейся символом '$'.
Выход: нет
Описание: Строка, исключая завершающий ее символ '$', посылается на стандартный вывод. Символы Backspace обрабатываются как в функции 02h. Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 13H и ASCII 0aH). Строки, содержащие '$', можно выдать через 40h (BX=0), которая посылает символ в DL на стандартное устройство принтера, обычно LPT1.
Прерывание 10h.
Функция 02h
Вход: AH=02h
BH = видео страница
DH,DL = строка, колонка (считая от 0)
Выход: нет
Описание: Устанавливает курсор в позицию DH,DL. Установка курсора на строку 25 делает курсор невидимым.
|
|
Функция 09h
Писать символ/атрибут в текущей позиции курсора.
Вход: AH=09h
BH = номер видео страницы
AL = записываемый символ
CX = счетчик (сколько экземпляров символа записать)
BL = видео атрибут (текст) или цвет (графика)
Выход: нет
Описание: Выводит на экран в текущую позицию курсора символ с заданным атрибутом.
Функция 0ah
Писать символ в текущей позиции курсора.
Вход: AH=0ah
BH = номер видео страницы
AL = записываемый символ
CX = счетчик (сколько экземпляров символа записать)
Выход: нет
Описание: Выводит на экран в текущую позицию курсора заданный символ.
Функция 13h
Вывод строки.
Вход: AH=13h
ES:BP – выводимая строка
CX = длина строки (подсчитываются только символы)
DH,DL = позиция (строка, колонка) начала вывода
BH = номер страницы
AL = код подфункции:
0=атрибут в BL; курсор без изменения
1=атрибут в BL; курсор – в конец строки
2=формат строки: char,attr,...; курсор без изменения
3=формат строки: char,attr,...; курсор – в конец строки
Выход: нет
Описание: Выдает строку в позиции курсора. Символы 0dH (CarRet), 0aH (LineFeed), 08H (backspace) и 07H (Beep) трактуются как команды управления и не высвечиваются.
Некоторые функции прерывания 10h используют для вывода атрибут символа. Для адаптеров цветной графики в текстовом режиме атрибут определен следующим образом:
fgB | background | brt | foreground |
foreground – цвет переднего плана (от 0 до 0fH)
brt – интенсивность: 1=передний план яркий
background – фоновый цвет (от 0 до 7)
fgB – мерцание: 1=передний план мерцает
Видеоадаптер поддерживает следующие цвета:
00H черный 01H синий 02H зеленый 03H голубой 04H красный 05H розовый 06H коричневый 07H серый | 08H темно-серый 09H ярко-синий 0aH светло-зеленый 0bH светло-голубой 0cH светло-красный 0dH светло-розовый 0eH желтый 0fH белый |
Вычислить значение атрибута можно, используя следующее выражение:
(фон * 16) + передний план + (128 для мерцания)
Приведенный ниже фрагмент программы иллюстрирует процесс вывода строки на экран.
MOV AH,09H;Выбор функции прерывания
MOV DX,OFFSET STR;Занесение в DX адреса выводимой строки
|
|
INT 21H
...
STR DB 10,13,'Hello$';Описание строки