Обработка строк
Известно, что в ПЗУ BIOS, сегментный адрес которого составляет F000h (см. рис. 1.5), наряду с программами управления аппаратурой компьютера, хранятся еще и некоторые идентификаторы. Так, в восьми байтах ПЗУ, начиная с адреса F000h:FFFSh, записана в кодах ASCII дата разработки ПЗУ. В примере 3.6 выполняется чтение этой даты, сохранение ее в памяти и вывод на экран для контроля. Поскольку интересующая нас дата хранится в ПЗУ BIOS в кодах ASCII, никаких преобразований содержимого этого участка ПЗУ перед выводом на экран не требуется.
В программе осуществляется настройка всех необходимых для выполнения команды movs регистров (DS:SI, ES:DI, CX и флага DF) и одной командой movsb с префиксом rep содержимое требуемого участка ПЗУ переносится в поле bios. Перенос строки байтами подчеркивает ее формат (в строке записаны байтовые коды ASCII), однако в нашем примере, при четном числе переносимых байтов, более эффективно осуществить перенос по словам. В этом варианте команда movs будет фактически повторяться не 8 раз, а только 4. Для этого достаточно занести в СХ число 4 (вместо 8) и использовать вариант команды niovsw.
Для выполнения команды movs нам пришлось настроить сегментный регистр DS на сегмент BIOS. Если в дальнейшем предполагается обращение к полям данных программы, как это имеет место в примере 3-6, в регистр DS следует занести сегментный адрес сегмента данных. После этого, настроив остальные регистры для вызова функции 40h, прочитанную из BIOS строку можно вывести на экран.
В рассмотренном примере неявно предполагалось, что программа будет в дальнейшем как-то использовать полученную из BIOS информацию. Если задача программы заключается просто в выводе на экран даты выпуска BIOS, то нет необходимости сначала копировать эту дату из BIOS в поля данных программы, а потом выводить ее на экран. Можно было поступить гораздо проще: настроив регистр DS на сегмент BIOS, а регистр DX на адрес строки с датой, вызвать функцию 40h и вывести на экран текст непосредственно из сегмента BIOS. Тогда содержательная часть программы сократится в два раза и примет такой вид:
mov AX,0F00h; Настроим DS mov DS,AX; на сегмент BIOS mov AH,40h; Функция вывода mov BX,1; Дескриптор экрана mov CX,8; Вывести 8 байт mov DX,0FFFSh; Смещение к дате int 21h; Вызов DOS
Приведенный фрагмент не имеет отношения к данному разделу, так как в нем уже нет команд обработки строк. В то же время он подчеркивает важность сегментных регистров и гибкость сегментной адресации. Функция 40h ожидает найти адрес выводимой на экран строки в регистрах DS:DX, и никакие другие регистры в этом случае использовать нельзя. С другой стороны, эти регистры можно настроить на любой участок памяти и вывести на экран (а также и на принтер, в файл или в последовательный порт) данные откуда угодно.
Рассмотрим теперь пример работы с командами lods и stos, которые можно использовать как по отдельности, так и в паре друг с другом. Эти команды очень удобны, в частности, для прямого обращения к видеопамяти.
К экрану, как и к любому другому устройству, входящему в состав компьютера, можно обращаться тремя способами: с помощью функций DOS (прерывание 21h), с использованием прерывания BIOS (для управления экраном используется прерывание 10h) и, наконец, путем прямого программирования аппаратуры, в данном случае видеобуфера (видеопамяти).
Функции DOS позволяют выводить только черно-белый текст и имеют ряд других ограничений (нельзя очистить экран, нет средств позиционирования курсора); при использовании прерывания BIOS все эти ограничения снимаются, однако программирование с помощью средств BIOS весьма трудоемко; наконец, прямая запись в видеопамять, предоставляя возможность вывода цветного текста в любую точку экрана, является процедурой очень простой и, к тому же, повышает скорость вывода (по сравнением с использованием системных средств) в десятки и сотни раз. Прямое обращение к видеобуферу удобно использовать, например, в обработчиках прерываний, где запрещен вызов функций DOS и имеются ограничения на обращение к средствам BIOS.