Программа типа.ЕХЕ
Характерные особенности программ типа .ЕХЕ подробно рассматривались в предыдущих главах. Приведем еще несколько обобщающих соображений.
Структура типичной программы на языке ассемблера выглядит следующим образом.
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, эти описатели будут опускаться.