Рисунки, не использующие палитру. Рисунки, подготовленные в стандарте BMP.
Выполнение примера 7.25 начинается с сохранения в стеке содержимого "всех" регистров. Команда pusha не сохраняет сегментные регистры, поэтому содержимое fs и переменной cur_win сохраняет макровызов pushReg.
Для чтения данных вызывается подпрограмма Readf, текст которой приведен в примере 3.23. Она размещает данные в буфере обмена, начиная с адреса, указанного в swpoffs. Для максимального использования пространства буфера эта переменная предварительно очищается, а в регистр fs записывается сегмент буфера обмена из SwpSeg.
После этого выполняются подготовительные действия, смысл и назначение которых описаны выше. Три первые команды вычисляют константу для коррекции адресов строк, ее значение помещается в регистр bx и используется в основном цикле. Следующие восемь команд формируют значения переменных fwidth и rmndr. Затем шесть команд вычисляют значения переменных part и numbyte. Последние десять команд формируют адрес начала последней строки рисунка в видеопамяти и устанавливают окно, которому он принадлежит.
Основной цикл имеет метку NewPart. Он практически совпадает с одноименным циклом примера 7.24. Отличие заключается в следующем. При переадресации строк видеопамяти вычисляется адрес начала предыдущей строки, поэтому содержимое регистра bx вычитается из содержимого регистра di, а в случае переполнения результата вычитания устанавливается предыдущее окно видеопамяти. Кроме того, для исключения "лишних" точек адрес буфера обмена, хранящийся в регистре si, увеличивается на величину rmndr. Ну и, конечно же, имя drawiine соответствует разным подпрограммам.
Подпрограммы для построения строк
В отличие от основного текста примера 7.25, тексты подпрограмм построения строк существенно зависят от установленного задачей видеорежима. Это связано с необходимостью преобразования исходного формата bgr в формат Hi-color или True Color. Варианты подпрограмм для обоих режимов показаны в примере 7.26.
Пример 7.26. Варианты подпрограммы построения строки.
; Вариант 1 для работы в режимах True Color drawline: movs word ptr [di], f s: [si]; копируем коды синего и зеленого lods byte ptr fs:[si]; al = код красного цвета xor ah, ah очистка резервного байта stosw записываем старшее слово кода or di, di адрес в пределах сегмента? jnz @F › да, обход команды call NxtWin установка следующего окна @@: loop drawline управление повторами цикла ret возврат из подпрограммы
; Вариант 2 для работы в 15-разрядных режимах Hi-Color drawline: mov al, fs:[si+2] читаем код красного цвета в al shr al, 03 сокращаем его до 5-ти разрядов mov bh, fs:[si+1] читаем код зеленого цвета в bh shld ax, bx, 05 добавляем в ах код зеленого цвета mov bh, f s:[si] читаем код синего цвета в bh shld ax, bx, 05 сдвигаем и дополняем код в ах add si, 03 добавляем в ах код синего цвета stosw записываем код в видеопамять or di, di адрес в пределах сегмента? jnz @F › да, обход команды call NxtWin установка следующего окна @@: loop drawline управление повторами цикла ret возврат из подпрограммы
В предыдущих разделах описано преобразование цветов, хранящихся в палитрах, в форматы Hi-color и True Color. Отличие рассмотренного здесь случая в том, что исходные цвета расположены не в палитре, а в строке образа рисунка, находящейся в буфере обмена. Поэтому первый вариант примера 7.26 является циклом примера 7.19, а второй вариант примера 7.26 является циклом примера 7.18.
Таким образом, при построении полноцветных рисунков формата BMP текст основной подпрограммы не зависит, а вспомогательной (drawline) зависит от видеорежима. Исключить эту зависимость невозможно, но при использовании директив условного ассемблирования можно задавать признак для выбора нужной подпрограммы.