Иллюстрированный самоучитель по Assembler

Программа типа.ЕХЕ

Характерные особенности программ типа .ЕХЕ подробно рассматривались в предыдущих главах. Приведем еще несколько обобщающих соображений.

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

0.586; Размещение трансляции всех
; команд (386-486-Pentium)
code segment usee16; Начало сегмента команд
; 16-разрядное приложение
assume CS:code, DS: data
main proc; Начало главной процедуры
mov AX, data; Инициализация
mov DS, AX; сегментного регистра DS
…; Текст главной процедуры
mov AX,4C00h; Вызов функции DOS
int 2 In; Завершение программы
main endp; Конец главной процедуры
code ends; Конец сегмента команды
data segments use16; Начало сегмента данных
…; Определения данных
data ends; Конец сегмента данных
stk segment stack; Начало сегмента данных
db 256 dup(0); Стек
stk ends; Конец сегмента стека
end main; Конец программы и точка входа

Программа начинается с директивы ассемблера 0.586, разрешающей использовать в тексте программы весь набор команд процессора Pentium (кроме привилегированных). Если программа будет использовать только базовый набор команд МП 86, указание этой директивы не обязательно.

С другой стороны, ее указание не обязывает нас обязательно использовать команды Pentium. Если в программе предполагается использовать лишь дополнительные команды процессоров 486 или 386, то вместо 0.586 можно написать 0.486 или 0.386.

Указание любого номера 32-разрядного процессора приведет к тому, что по умолчанию программа будет транслироваться, как 32-разрядное приложение, в то время как нам нужно создать обычное 16-разрядное приложение. Для того, чтобы все адреса в программе рассматривались, как 16-битовые, необходимо придать сегментам команд и данных описатели use16. Для сегмента стека этот описатель не нужен, так как в стеке нет поименованных ячеек.

Программа состоит из трех сегментов – команд, данных и стека. Имена сегментов выбраны произвольно. Собственно программа обычно состоит из процедур. Деление на процедуры не обязательно, но повышает ее наглядность и облегчает передачу управления на подпрограммы. В рассматриваемом примере сегмент команд содержит единственную процедуру main, открываемую оператором ргос (от procedure, процедура) и закрываемую оператором endp (end procedure, конец процедуры). Перед обоими операторами указывается имя процедуры, которое в дальнейшем может использоваться в качестве относительного адреса процедуры (в сущности, относительного адреса первого выполнимого предложения этой процедуры). У нас это имя выступает в качестве параметра завершающей программу директивы end. Имена процедур, так же, как и имена сегментов, выбираются произвольно.

Если программа имеет сегмент данных с какими-либо данными, то для того, чтобы к этим данным можно было обратиться, необходимо занести сегментный адрес сегмента данных в один из сегментных регистров. Обычно в качестве такого регистра выбирают DS. Таким образом, предложения, с которых начался текст главной процедуры:

mov AX,data; Инициализация
mov DS,АХ; сегментного регистра DS

Где data – имя, данное сегменту данных, практически являются обязательными для любой программы.

Точно также обязательными являются и завершающие предложения:

mov AX,4C00h; Вызов функции DOS
int 21h; завершения программы

В которых вызывается функция DOS с номером 4Ch. Эта функция, как уже отмечалось, завершает программу, освобождает занимаемую ею память и передает управление командному процессору COMMAND.COM. Еще два замечания следует сделать относительно процедуры трансляции и компоновки программы. Если сегмент данных расположить после сегмента команд, как это сделано в нашем примере, то у транслятора возникнут сложности при обработке встречающихся в программных предложениях имен полей данных, так как эти имена еще неизвестны транслятору. Для того, чтобы такие, как говорят, "ссылки вперед" могли правильно обрабатываться, следует в команде вызова транслятора TASM заказать два прохода. Это делается указанием ключа /m2.

С другой неприятностью мы столкнемся, если попытаемся включить в программу операции с 32-разрядными операндами (даже и с командами МП 86). Компоновщик TASM по умолчанию запрещает такого рода операции. Чтобы преодолеть этот запрет, следует в команде вызова компоновщика указать ключ /3.

Таким образом, приведенный в гл. 1 командный файл должен выглядеть (для подготовки программы TASM) следующим образом:

tasm /z /zi /n /m2 p,p,p
tlink /x /v /3 p,p

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

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.