Программа типа.ЕХЕ
Приведем в качестве еще одного примера простую законченную программу типа .ЕХЕ, которая выясняет букву – обозначение текущего диска и выводит ее на экран с поясняющей надписью.
Пример 3.1. Получение текущего диска.
; Опишем сегмент команд assume CS:code,DS:data code segment main proc move AX, data; Настроим DS mov DS,AX; на сегмент данных mov AH,19h; Функция DOS получения int 21h; текущего диска add disk,AL; Преобразуем номер в код ; ASCII mov AH,09h; Функция DOS вывода на экран mov DX,offset msg; Адрес строки int 21h; Вызов DOS mov AH,01h; Функция DOS ввода символа int 2 In; Вызов DOS mov AX,4C00h; Функция DOS завершения int 21h; программы code ends ;Опишем сегмент данных data segment use16 msg db "Текущий диск"; Выводимый на экран текст disk db " A:",13.10,"$"; Продолжение текста data ends ; Опишем сегмент стека stk segment stack db 256 dup(U); Стек stk ends end main
Рассмотрим текст приведенного примера. После настройки сегментного регистра DS на сегмент данных, вызывается функция DOS с номером 19h, которая позволяет получить код текущего диска. У этой функции нет никаких параметров, а результат своей работы она возвращает в регистре AL в виде условного кода. 0 обозначает диск А:, 1 диск В:, 2 диск С: и т.д. Если, например, пользователь работает на диске F, то функция 19h вернет в AL код 5.
Для преобразования кода диска в его буквенное обозначение, мы воспользовались широко распространенным приемом. В полях данных определена символьная строка, которая будет выводиться на экран. Для удобства работы она разделена на две части, каждая из которых имеет свое имя. Началу строки присвоено имя msg, а той ее части, которая начинается с обозначения диска А:, имя disk (разумеется, имена выбраны произвольно). Если посмотреть на таблицу кодов ASCII, то можно заметить, что код каждой следующей буквы алфавита на 1больше предыдущей. Таким образом, если к коду латинской буквы A (41h) прибавить 1, получится код буквы В, а если прибавить, например, 5, получится код буквы F. Именно эта операция и выполняется в предложении:
add disk,AL; Преобразуем номер в код ASCII
Где к байту с адресом disk прибавляется код, возвращенный функцией DOS.
Выполнив модификацию строки, мы выводим ее на экран уже знакомой нам функцией DOS 09h. Она выводит все символы строки, пока не встретится с символом $, которым наша строка и завершается. Перед знаком $ в строке имеются два числа: 13 и 10. При выводе текстовой строки на экран любой функцией DOS код 13 трактуется DOS, как команда вернуть курсор в начато строки ("возврат каретки"), а код 10 – как команда на перевод строки. Два эти кода переводят курсор в начало следующей строки экрана. В данном случае, когда на экран ничего больше не выводится, можно было обойтись и без этих кодов, которые включены лишь в познавательных целях.
Между прочим, правильная работа программы основана на том предположении (безусловно правильном), что ассемблер расположит наши данные в памяти в точности в том же порядке, как они описаны в программе. Именно это обстоятельство и позволяет дробить единую строку на части, не опасаясь, что в память они попадут в разные места, что привело бы, разумеется, к непредсказуемому результату. После вывода на экран сообщения о текущем диске в программе вызывается функция DOS с номером 01h. Эта функция вводит с клавиатуры один символ. Если символов нет (мы после запуска программы не нажимали на клавиши), функция 01h ждет нажатия фактически любой клавиши (более точно – любой алфавитно-цифровой или функциональной клавиши). Такой весьма распространенный прием позволяет остановить выполнение программы до нажатия клавиши, что дает возможность программисту посмотреть, что вывела программа на экран, и оценить правильность ее работы.
Наконец, последнее действие носит, как уже отмечалось, сакраментальный характер. Вызовом функции DOS 4Ch программа завершается с передачей управления DOS.
Взглянем еще раз на текст программы 3.1. Если не считать первых предложений инициализации регистра DS, то в программе имеется лишь одна строка, носящая, можно сказать, вычислительный характер – это прибавление полученного кода диска к содержимому байта памяти. Все остальные строки служат для вызова тех или иных функций DOS – получения информации о текущем диске, вывода строки на экран, остановки программы и, наконец, ее завершения. Это подтверждает высказанное выше утверждение о важности изучения системных средств и широком использовании их в программах на языке ассемблера.
Разумеется, в программе могут быть и сколь угодно сложные и протяженные участки обработки данных и других вычислений, но такие операции, как ввод с клавиатуры, вывод на экран, работа с файлами, получение, как в нашем примере, системной информации и многое другое выполняется исключительно с помощью вызова тех или иных функций DOS (или BIOS). Программу на языке ассемблера просто невозможно написать без использования системных средств.