Линии, строки и прямоугольные области. Подпрограммы для рисования линий.
Ускоренное рисование линии
В подпрограмме baselp, текст которой приведен в примере 7.6, работу с видеопамятью выполняет одна команда, поэтому сразу после нее возможна переадресация операнда. Если при этом шаг переадресации совпадает с размером операнда, то вместо команды пересылки можно использовать строковую операцию. В таком случае тело цикла пересылки сокращается до одной команды rep stosw, которую надо вставить вместо call baselp. Это и сделано в примере 7.7.
Пример 7.7. Ускоренное рисование линии в режимах Hi-Color.
horline: push dx сохраняем содержимое регистра dx mov dx, di копируем адрес в регистр dx shl ex, 01!! для True Color – shl ex, 02 add dx, ex сумма исходного адреса и размера линии jc hrl 1 › прямая расположена в двух окнах xor dx, dx очистка регистра dx hrl_l: sub ex, dx количество точек в текущем окне shr ex, 01!! для True Color – shr ex, 02 rep stosw!! для True Color – stosd or di, di адрес в пределах текущего окна? jne hrl exit › да, линия нарисована полностью call NxtWin установка следующего окна mov ex, dx количество не нарисованных точек shr ex, 01!! для True Color – shr ex, 02 rep stosw!! для True Color – stosd hrl exit: pop dx восстановление содержимого dx ret возврат из подпрограммы
Обратите внимание на то, что во второй части примера 7.7 проверяется только содержимое регистра di и не проверяется оставшееся количество точек. Это допустимо потому, что если регистр сх очищен, то цикл rep stosw не будет выполняться и предварительная проверка содержимого сх не обязательна.
В комментариях к примерам 7.6 и 7.7 указано, как надо изменить переменные команды для использования подпрограмм в режимах True Color, в таком случае код цвета линии помещается в регистр еах.
Условное ассемблирование
Тексты трех приведенных примеров рисования линий являются стандартными заготовками, у которых от видеорежима зависит лишь несколько команд. Исключить эту зависимость и сделать подпрограммы универсальными невозможно. Однако их исходный текст можно подготовить так, чтобы Макроассемблер выбирал нужный вариант команды в зависимости от заданного вами признака. Это упростит вашу работу и позволит включать в текст задачи заранее подготовленные и отлаженные исходные тексты подпрограмм.
Признак (условие для выбора) описывается как обычная константа и располагается в начале текста программы перед описанием первого сегмента.
Предположим, что ему присвоено имя variant, а значения равны 1 для режимов Hi-color и 2 для режимов True color. Описание выглядит так:
variant = 1; Описание признака "variant" для режимов Hi-Color
В текст подпрограммы, приведенной в примере 7.8, вместо переменной команды вставлен условный блок, в котором описаны варианты выбора.
Пример 7.8. Выбор варианта команды по заданному признаку.
IF variant EQ 1; проверка условия выбора mov es:[di], ax; основной вариант команды ELSE; признак альтернативного варианта mov es:[di], eax; альтернативный вариант команды ENDIF; конец условного блока
При выполнении примера 7.8 Макроассемблер выберет вариант команды пересылки в зависимости от значения признака variant. Если variant=2, то будет выбрана команда, записанная после ELSE.
Дополнительно отметим, что в условных блоках альтернативный вариант может отсутствовать, если он не нужен, и в обоих вариантах может быть задана не одна, а несколько команд.
Значения признака variant выбраны не случайно. При таких значениях в примерах 7.6 и 7.7 в операциях сдвига можно заменить 1 на имя variant. Тогда в примере 7.6 останется только одна переменная команда, а в примере 7.7 – две. Соответственно, в текст примера 7.6 понадобится включить один условный блок (описанный в примере 7.8), а в текст примера 7.7 – два для выбора вариантов команд rep stosw или rep stosd.
Таким образом, при создании подпрограмм для видеорежимов direct color можно использовать условное ассемблирование и специальные признаки. Это позволяет включать в исходные тексты задач заранее подготовленные заготовки подпрограмм, выполняющих нужные действия.