Иллюстрированный самоучитель по SVGA

Построение рисунков. Варианты построения строк.

Ускорение цикла построения

Для ускорения построения строки используется микропрограммный цикл пересылки, аналогичный описанному в примере 3.8. Мы просто перепишем этот пример, изменив в нем две строковые операции (пример 3.16). Входные параметры указываются так же, как для подпрограммы примера 3.15.

Пример 3.16. Ускоренное построение строки рисунка.

drawline: push dx сохранение содержимого регистра dx
mov dx, di копирование адреса в регистр dx
add dx, ex сумма текущего адреса и количества точек
jc @F › прямая расположена в двух окнах
xor dx, dx очистка регистра dx
@@: sub ex, dx вычисляем количество точек в текущем окне
rep movs byte p:r [di], fs:[sil; строим строку или ее часть
or di, di адрес в пределах текущего окна?
jne dhl out › да, строка построена полностью
call NxtWin установка следующего окна
mov ex, dx количество не построенных точек
rep movs byte p:r [di], fs:[si]; строим остаток строки
dhl out: pop dx восстановление содержимого dx
ret возврат из подпрограммы

Для дальнейшего ускорения выполнения построения строки нужно использовать пересылку одновременно двух или четырех байтов. В примерах 3.9 и 3.10 показаны изменения, которые позволяли это сделать при рисовании линии. Аналогичные изменения надо внести и в пример 3.16, только не забудьте заменить строковые операции следующими:

stosb на movs byte ptr [di], fs:[si]
stosw на movs word ptr [di], fs:[si]
stosd на movs dword ptr [di], fs:[si]

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

Следует заметить, что если образ рисунка находится в файле, то время, затрачиваемое на чтение и предварительные действия, значительно больше чистого времени, построения всех его строк. В таком случае целесообразность ускорения построения строк весьма проблематична.

Кроме 256-цветных рисунков довольно широко распространены 16- и 2-цветные. Они используются, например, Windows и ее приложениями для оформления рабочей области экрана и в других целях. Такие рисунки хранятся в упакованном виде и перед записью в видеопамять должны быть распакованы. Способ упаковки является общепринятым и не зависит от конкретного стандарта, в котором подготовлен файл. При распаковке надо учесть, что в зависимости от количества точек в исходной строке последний байт упакованной строки может быть заполнен частично.

Распаковка 16-цветных строк

Код 16-цветного рисунка занимает 4 разряда, и для сокращения размера файла в одном байте располагаются коды двух точек. Перед записью в видеопамять находившиеся в одном байте коды точек надо расположить в младших разрядах двух разных байтов. Эта операция достаточно проста, и ее целесообразно выполнять в процессе построения строки. Тем более что при предварительной распаковке рисунка его размер увеличится в два раза.

Подпрограмма для распаковки строки в процессе построения 16-цветного рисунка приведена в примере 3.17. Перед обращением к ней надо установить окно видеопамяти, в котором должны располагаться точки строки, а адрес первой точки указать в регистре di. Пара регистров fs:si должна содержать адрес оперативной памяти, начиная с которого хранится упакованная строка. В регистре сх указывается количество точек в строке.

Пример 3.17. Подпрограмма построения строки 16-цветного рисунка.

rwlin4: mov al, fs:[si] читаем в al код пары точек
shr al, 04 выделяем код старшей точки
stosb записываем его в видеопамять
or di, di начало нового сегмента?
jne @F › нет, обход команды call NxtWin
call NxtWin установка следующего окна
@: lods byte ptr fs [si]; повторное чтение кода пары точек
dec ex сх = сх -1
je dr4ret если сх = 0, то конец строки
and al, OFh выделяем код младшей точки
stosb записываем его в видеопамять
or di, di начало нового сегмента?
jne @F › нет, обход команды call NxtWin
call NxtWin установка следующего окна
@: loop drwlin4 управление повторами цикла
r4ret: ret выход из подпрограммы

В примере 3.17 сначала выделяется и записывается в видеопамять код старшей тетрады очередного байта упакованной строки, а затем код его младшей тетрады. После записи кода старшей тетрады содержимое сх уменьшается на 1 и проверяется значение результата. Если оно равно нулю, то построение строки завершено. Указанные действия нужны потому, что в последнем байте упакованной строки при нечетном количестве точек в строке будет заполнена только одна (старшая) тетрада.

После каждой записи в видеопамять проверяется значение адреса, хранящегося в регистре di. Если он равен нулю, то произошел выход за пределы сегмента и надо изменить текущее окно видеопамяти. Если адрес не равен нулю, то выполнение команды call Nxtwin исключается.

Последняя команда loop управляет повторами цикла, если строка содержит четное количество точек, то именно она завершит выполнение подпрограммы. При нечетном количестве точек в строке выполнение подпрограммы завершит команда je dr4ret.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.