Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Финогенов-основы_языка_ассемблера.doc
Скачиваний:
26
Добавлен:
17.09.2019
Размер:
3.35 Mб
Скачать

Глава 3

Команды и алгоритмы

101

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

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

нет поименованных ячеек.

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

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

mov AX,data Инициализация

mov DS,AX ;сегментного регистра DS ;

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

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

mov AX,4COOh lut 21h

;Вызов функции DOS ;завершения программы

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

ложениях имен полей данных, так как эти имена еще неизвестны транс­лятору. Для того, чтобы такие, как говорят, «ссылки вперед» могли пра­вильно обрабатываться, следует в команде вызова транслятора TASM за­казать два прохода. Это делается указанием ключа /т.2.

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

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

tasm /z /zi /n /nil p,p,P tlink /x /v /3 p,p

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

Приведем в качестве еще одного примера простую законченную про-

. грамму типа .ЕХЕ, которая выясняет букву-обозначение текущего диска

!.и выводит ее на экран с поясняющей надписью.

;Пример 3-1. Получение текущего диска ;Опишем сегмент команд assume CS:codc,DS:data code segment main ргос

AX,data ;Настроим DS

DS,AX ;на сегмент данных

mov AH,19h ;Функция DOS получения

int 2 Hi ;текущсго диска

add disk,AL Преобразуем номер в код

;ASCII

mov AH,09h ;Функция DOS вывода на ; экран

DX,offset rnsg ;Адрес строки

21h ; Вызов DOS

АН,0 Hi ;Функция DOS ввода символа

21h ;Вызов DOS

AX,4C001i ;Функция DOS завершения

21h ; программы

mov

mov hit mov int mov int code ends


mov

Глава з

102

;Опишем сегмент данных

data segment use 16

;Выводимый на экран текст Продолжение текста

msg db "Текущий диск "

disk db "A:",13,10,T

data ends

;Опишем сегмент стека

stk segment stack

:Стек

db 256 dup (0) stk ends

end main

Рассмотрим текст приведенного примера. После настройки сегмент­ного регистра DS на сегмент данных, вызывается функция DOS с номе­ром 19h, которая позволяет получить код текущего диска. У этой функции нет никаких параметров, а результат своей работы она возвращает в реги­стре AL в виде условного кода. О обозначает диск А:, 1 диск В:, 2 диск С: и т.д. Если, например, пользователь работает на диске F, то функция I9h вернет в AL код 5.

Для преобразования кода диска в его буквенное обозначение, мы вос­пользовались широко распространенным приемом. В полях данных опре­делена символьная строка, которая будет выводиться на экран. Для удоб­ства работы она разделена на две части, каждая из которых имеет свое имя. Началу строки присвоено имя msg, а той ее части, которая начинает­ся с обозначения диска А:, имя disk (разумеется, имена выбраны произ­вольно). Если посмотреть на таблицу кодов ASCII (рис. 3.1), то можно заметить, что код каждой следующей буквы ачфавита на 1 больше преды­дущей. Таким образом, если к коду латинской буквы A (41h) прибавить 1, получится код буквы В, а если прибавить, например, 5, получится код буквы F. Именно эта операция и выполняется в предложении

add disk,AL ;Преобразусм номер в код ASCII

где к байту с адресом disk прибавляется код, возвращенный функцией DOS.

Выполнив модификацию строки, мы выводим се на экран уже знако­мой нам функцией DOS 09h. Она выводит все символы строки, пока не встретится с символом S, которым наша строка и завершается. Перед зна­ком S в строке имеются два числа: 13 и 10. При выводе текстовой строки на экран любой функцией DOS код 13 трактуется DOS, как команда вер­нуть курсор в начало строки («возврат каретки»), а код 10 —• как команда на перевод строки. Два эти кода переводят курсор в начало следующей строки экрана. В данном случае, когда на экран ничего больше не выво­дится, можно было обойтись и без этих кодов, которые включены лишь в познавательных целях.

Между прочим, правильная работа программы основана на том пред­положении (безусловно правильном), что ассемблер расположит наши данные в памяти в точности в том же порядке, как они описаны в про­грамме. Именно это обстоятельство и позволяет дробить единую строку на

анды и алгоритмы

103

00

10

20

30

40

50

60

70

80

90

АО

ВО

СО

DO

ЕО

FO

00 01 02 03 04 05 06 07 08 09 OAOBOCODOEOF

0123456789: ;< = >? 0ABCDEFGHIJKLMNO PQRSTUUWX¥Z[4]^_ abcdefghijklnno pqrstuvu х у 2: { I > ~ л

АБВГДЕЖЗИЙКЛМНОП РСТУФХЦЧЫЩЪЫЬЭЮЯ абагдемзий клмноп

h

_ л _ I? - II

II

лт

I I

Т

т « I t J

И Р с т

И Ф х цчыщъыьэ w я

«"-=-% ° • • -S № От

Рис. 3.1. Таблица кодов символов.

части, не опасаясь, что в память они попадут в разные места, что привело бы, разумеется, к непредсказуемому результату.

После вывода на экран сообщения о текущем диске в программе вы­зывается функция DOS с номером Olh. Эта функция вводит с клавиатуры один символ. Если символов нет (мы после запуска программы не нажи­мали на клавиши), функция Olh ждет нажатия фактически любой клави­ши (более точно — любой алфавитно-цифровой или функциональной кла­виши). Такой весьма распространенный прием позволяет остановить вы­полнение программы до нажатия клавиши, что даст возможность программисту посмотреть, что вывела программа на экран, и оценить правильность ее работы.

Наконец, последнее действие носит, как уже отмечалось, сакрамен­тальный характер. Вызовом функции DOS 4Ch программа завершается с передачей управления DOS.

Взглянем еще раз на текст программы 3-1. Если не считать первых предложений инициализации регистра DS, то в программе имеется лишь одна строка, носящая, можно сказать, вычислительный характер — это прибавление полученного кода диска к содержимому байта памяти. Все остальные строки служат для вызова тех или иных функций DOS — полу­чения информации о текущем диске, вывода строки на экран, остановки программы и, наконец, се завершения. Это подтверждает высказанное выше утверждение о важности изучения системных средств и широком использовании их в программах на языке ассемблера. Разумеется, в про­грамме могут быть и сколь угодно сложные и протяженные участки обра-

104