Для работы со строками, или цепочками символов или чисел (т.е. попросту говоря,
с массивами произвольных данных) в МП предусмотрен ряд специальных команд: movs - пересылка строки; Эти команды очень удобны,
однако их использование сопряжено с некоторыми трудностями, так как процессор,
выполняя эти команды, неявным образом использует ряд своих регистров. Только
если все эти регистры настроены должным образом, команды будут выполняться правильно.
В результате включение в программу предложения с командой, например,
movs, требует
иной раз 6-7 дополнительных предложений, в которых осуществляется подготовка
условий для правильного выполнения этой команды. Пример 3-6. Чтение из ПЗУ BIOS
даты его выпуска ;В
программном сегменте main
proc mov
AX,0F000h ;Занесем в DS mov
DS,AX ;Сегментный
адрес ПЗУ BIOS mov
SI,0FFF5h ;Смещение к
интересующему нас полю mov
AX,data ;Настроим
RS mov
RS,AX ;на
сегмент данных программы mov
DI,offset bios ;Смещение к полю для хранения даты mov
CX,8
;Перенести 8 байт cld
;Движение по строке вперед rep
movsb
;Перенос байтов ;Выведем
полученную информацию на экран mov
AX,data ; Теперь
настроим DS mov
DS,AX ;на
сегмент данных программы mov
AH,40h ;Функция
вывода mov
BX,1
;Дескриптор экрана mov
CX,8
;Вывести 0 байт mov
DX,offset bios ;Смещение в строке int
21h
; Вызов DOS ;В
сегменте данных bios
db 8 dup (') ;Поле для хранения
даты Известно, что в ПЗУ
BIOS,
сегментный адрес которого составляет F000h (см. рис. 1.5), наряду с программами
управления аппаратурой компьютера, хранятся еще и некоторые идентификаторы.
Так, в восьми байтах ПЗУ, начиная с адреса F000h:FFFSh, записана в кодах ASCII
дата разработки ПЗУ. В примере 3.6 выполняется чтение этой даты, сохранение
ее в памяти и вывод на экран для контроля. Поскольку интересующая нас дата хранится
в ПЗУ BIOS в кодах ASCII, никаких преобразований содержимого этого участка ПЗУ
перед выводом на экран не требуется. 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, и никакие другие регистры в этом случае использовать нельзя. С другой
стороны, эти регистры можно настроить на любой участок памяти и вывести на экран
(а также и на принтер, в файл или в последовательный порт) данные откуда угодно. Пример 3-7. Вывод на экран
прямой записью в видеопамять
cmps - сравнение двух строк;
seas - поиск в строке заданного элемента;
lods - загрузка аккумулятора (регистров AL или АХ) из строки;
stos - запись элемента строки из аккумулятора (регистров АХ или
AL).
Хотя команды обработки строк, как правило, включаются в программу без явного
указания операндов, однако каждая команда, в действительности, использует два
операнда. Для команд seas и stos операндом-источником служит аккумулятор, а
операнд-приемник находится в памяти. Для команды
lods, наоборот, операнд-источник
находится в памяти, а приемником служит аккумулятор. Наконец, для команд movs
и cmps оба операнда, и источник, и приемник, находятся в памяти.
Все рассматриваемые команды, выполняя различные действия, подчиняются одинаковым
правилам, перечисленным ниже. Операнды, находящиеся в памяти, всегда адресуются
единообразно: операнд-источник через регистры
DS:SI, а операнд-приемник через
регистры ES:DI. При однократном выполнении команды обрабатывают только один
элемент, а для обработки строки команды должны предваряться одним из префиксов
повторения. В процессе обработки строки регистры SI и DI автоматически смещаются
по строке вперед (если флаг DF = 0) или назад (если флаг DF = 1), обеспечивая
адресацию последующих элементов. Каждая команда имеет модификации для работы
с байтами или словами (например, movsb и movsw).
Таким образом, для правильного выполнения команд обработки строк необходимо
(в общем случае) предварительно настроить регистры DS:SI и
ES:DI, установить
или сбросить флаг DF, занести в СХ длину обрабатываемой строки, а для команд
seas и stos еще поместить операнд-источник в регистр АХ (или AL при работе с
байтами).
Однако сама операция, после всей этой настройки, осуществляется одной командой,
которая обычно даже не содержит операндов, хотя может иметь префикс повторения.
Стоит подчеркнуть, что строки, обрабатываемые рассматриваемыми командами, могут
находиться в любом месте памяти: в полях данных программы, в системных областях
данных, в ПЗУ, в видеобуфере. Например, с помощью команды movs можно скопировать
массив данных из одной массивной переменной в другую, а можно переслать страницу
текста на экран терминала. Рассмотрим несколько примеров использования команд
обработки строк, ограничившись лишь теми фрагментами программ, которые имеют
отношение к рассматриваемому вопросу.
В программе осуществляется настройка всех необходимых для выполнения команды
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. Тогда содержательная часть программы сократится в два раза
и примет такой вид:
Рассмотрим теперь пример работы с командами lods и
stos, которые можно использовать
как по отдельности, так и в паре друг с другом. Эти команды очень удобны, в
частности, для прямого обращения к видеопамяти.
К экрану, как и к любому другому устройству, входящему в состав компьютера,
можно обращаться тремя способами: с помощью функций DOS (прерывание 21h), с
использованием прерывания BIOS (для управления экраном используется прерывание
10h) и, наконец, путем прямого программирования аппаратуры, в данном случае
видеобуфера (видеопамяти). Функции DOS позволяют выводить только черно-белый
текст и имеют ряд других ограничений (нельзя очистить экран, нет средств позиционирования
курсора); при использовании прерывания BIOS все эти ограничения снимаются, однако
программирование с помощью средств BIOS весьма трудоемко; наконец, прямая запись
в видеопамять, предоставляя возможность вывода цветного текста в любую точку
экрана, является процедурой очень простой и, к тому же, повышает скорость вывода
(по сравнением с использованием системных средств) в десятки и сотни раз. Прямое
обращение к видеобуферу удобно использовать, например, в обработчиках прерываний,
где запрещен вызов функций DOS и имеются ограничения на обращение к средствам
BIOS.
Пусть по ходу программы необходимо вывести в нижнюю строку экрана предупреждающее
сообщение. Для этого в программу надо включить следующие предложения:
;В полях данных, адресуемых через DS
msg db 'Измерения закончены'
msg_len=$-msg ;Длина строки
;В программном сегменте
mov SI,offset msg ;DS:31->выводимая строка
mov AX,OB800h ;Сегментный адрес видеобуфера
mov ES,AX ;Будем адресовать через ES
mov DI,25*80*2 ;Смещение к последней строке экрана
mov CX,msg_len ;Счетчик цикла вывода символов
eld ;DF=0 , движение по строке
; и по экрану вперед
mov AH,31h ;Атрибут символов-синий по
; голубому
outher: lodsb ;Взять символ из строки в AL
show ; Вывод на экран символа
; из AL и его атрибута из AH
loop outser ; Цикл
Регистры DS:SI настраиваются на адрес начата выводимой строки; регистры ES:DI - на адрес требуемой позиции в видеобуфере. В регистр СХ надо поместить длину строки в байтах, а флаг DF сбросить, чтобы двигаться по строке вперед. На экран будет выводиться содержимое регистра АХ, в младшем байте которого должен находиться код ASCII выводимого символа, а в старшем байте - атрибут символа, т.е. код цвета символа (в младшем полубайте) и код цвета фона (в старшем полубайте). В примере число 31h образует синие символы по бирюзовому фону. При желании можно выбрать другую комбинацию цветов, выбрав ее с помощью табл. 3.1.
Таблица 3.1. Коды цветов стандартной цветовой палитры
Код | Цвет | Код | Цвет |
0h | Черный | 8h | Серый |
1h | Синий | 9h | Голубой |
2h | Зеленый | 10h | Салатовый |
3h | Бирюзовый | 11h | Светло-бирюзовый |
4h | Красный | 12h | Розовый |
5h | Фиолетовый | 13h | Светло-фиолетовый |
6h | Коричневый | 14h | Желтый |
7h | Белый | 15h | Ярко-белый |
Выбирая цвета, следует
иметь в виду, что при стандартной настройке видеосистемы для цвета фона можно
использовать лишь значения из левого столбца таблицы; выбор любого яркого цвета
из правого столбца приведет в выводу мерцающего символа. Например, атрибут символа
Bill образует синий мерцающий символ на бирюзовом фоне (а не синий символ на
светло-бирюзовом фоне).
Содержательную часть цикла вывода образуют две команды lodsb и
stosw. Первая
команда загружает в регистр AL код очередного символа, вторая выводит его вместе
с атрибутом, хранящемся в АН, на экран. При этом после каждого выполнения команды
lodsb содержимое SI увеличивается процессором на 1, смещая адресацию к следующему
символу строки; в то же время каждое выполнение команды stosw увеличивает DI
на 2 (потому что команда stosw работает со словами), смещая адресацию на экране
на 2 байт, т.е. как раз к позиции следующего символа.
Примеры использования команд cmps и seas можно найти в Приложении.
Copyright © 2010-2011 | ||
---|---|---|
Хостинг : Narod.Yandex.ru | Соглашение | e-mail : softcreate@pochta.ru |