Текст процедуры приведен в примере А. 11, программы описаны ниже.
Пример А.11. Начало построения рисунка формата BMP
BmpShow: lea bx, mode_8 ; bx = адрес подпрограммы mode_8
cmp bitcnt, 08 ; bitcnt = 8 ?
je @F ; -> да, переход на локальную метку
lea bx, mode_4 bx = адрес подпрограммы mode_4
cmp bitcnt, 04 bitcnt = 4 ?
je @F -> да, переход на локальную метку
lea bx, mode__2 bx = адрес подпрограммы mode_2
@@: mov ax, fwidth ax = fwidth, размер строки в файле
Для того чтобы выполняемые в примере А. 11 действия имели смысл, в текстах примеров А.9 и А.10 надо заменить call drawiine на call bx, как указано в комментарии. Первые 7 команд примера А. 11 формируют в bх адрес подпрограммы обработки строки (примеры А.12—А.14), в зависимости от размера кода точки образа рисунка. После этого вычисляется размер образа рисунка, и если он помещается в одном сегменте (dx=o), то выбирается подпрограмма Smlbmp, в противном случае BigBmp.
Таким образом, для построения рисунка формата BMP задача должна обращаться к процедуре BmpShow, как к подпрограмме. Перед ее вызовом в регистре di указывается адрес левого верхнего угла рисунка в видеопамяти и устанавливается окно, которому принадлежит этот адрес. Регистр es должен содержать код видеосегмента (хранящийся в vbuff).
Для того чтобы тексты подпрограмм построения строк не зависели от установленного задачей видеорежима, преобразование кодов точек и их запись в видеопамять вынесены в подпрограммы outpnt, которые будут описаны ниже.
В примере А.12 приведена подпрограмма, выполняющая построение строки рисунка, у которого код точки занимает 1 байт. Ее отличие от описанных ранее вариантов только в том, что для записи кода точки вызывается вспомогательная подпрограмма outpnt.
Пример А.12. Вывод строки формата 8 бит на точку (256 цветов)
mode_8: lods byte ptr f s:[si] ; al = код очередной точки
call outpnt ; обращение к подпрограмме записи
loop mode_8 ; управление повторами цикла
ret ; возврат из подпрограммы
В примере А. 13 приведен текст подпрограммы, выполняющей распаковку точек
16-цветного рисунка в процессе построения строки.
Пример А.13. Вывод строки формата 4 бита на точку (16 цветов)
mode 4 : lods byte ptr fs: [si] al = код очередных 2-х
точек
push ax сохраняем содержимое ах
shr al, 04 выделяем код старшей тетрады
call outpnt обращение к подпрограмме записи
pop ax. восстанавливаем содержимое ах
dec ex сх = сх — 1, счетчик точек в строке
je @F -> все точки выведены
and al, OFh выделяем код младшей тетрады
call outpnt обращение к подпрограмме записи
loop mode 4 управление повторами цикла
§@: ret возврат из подпрограммы
Сравните текст примера А.13 с текстом подпрограммы drwiin4 (см. пример 3.17). В данном случае он упростился за счет использования вспомогательной подпрограммы outpnt.
Замечание
Напомним, что дополнительная коррекция и проверка значения счетчика повторов
цикла (сх) нужна потому, что при нечетном количестве точек в рисунке последний
байт содержит код только одной точки (младшую тетраду выводить на экран
нельзя).
В примере А. 14 приведен текст подпрограммы, выполняющей распаковку 2-цветных рисунков в процессе построения строки.
Пример А.14. Вывод строки формата 1 бита на точку (2 цвета)
mode 2 : lods byte ptr fs: [si] al = код очередных восьми
точек
mov ah, 80h ah = константа для выделения разряда
md 21: push ax сохраняем содержимое ах
and al, ah выделяем текущий разряд
je md_22 если нуль, то обходим одну команду
mov al, 01 иначе записываем в al единицу
md 22: call outpnt обращение к подпрограмме записи
pop ax восстанавливаем содержимое ах
dec ex сх = сх — 1, счетчик точек в строке
je md_23 -> все точки выведены
shr ah, 01 изменяем константу выделения
jne md_21 -> если обработаны не все точки
jmp short mode 2 -> если обработано 8 точек
md 23: ret возврат из подпрограммы
Сравните текст примера А. 14 с текстом подпрограммы drwiinl (см. пример 3.18).
Замечание
Напомним, что дополнительная коррекция и проверка значения счетчика повторов
цикла (сх) нужна потому, что в зависимости от количества точек в строке
последний байт может быть заполнен частично.
Подпрограммы записи кодов точек существенно зависят от видеорежима. Если задача установила один из видеорежимов PPG, то в самом простом случае выполняются действия, показанные в примере А. 15.
Пример А.15. Простой вывод точки в режимах PPG
outpnt: stosb ; запись кода точки в видеопамять
or di, di ; адрес ь пределах сегмента?
jne @F ; -> да
call NxtWin ; нет, установка следующего окна
@@: ret ; возврат из подпрограммы
Пример А. 15 рассчитан на те случаи, когда при записи кодов точек в видеопамять не требуются никакие дополнительные действия. К ним относится перекодировка точек, которая может потребоваться, по крайней мере, в двух случаях.
При работе в режимах PPG палитра может быть установлена с изменением исходного расположения базовых цветов. В разделе мы подробно обсуждали, в каких случаях и почему используется такая установка палитры. При любом изменении расположения цветов, описанных в палитре, требуется изменение кодов точек при их записи в видеопамять. Один из вариантов перекодировки был показан в примере 4.8.
При работе в режимах direct color перекодировка производится в тех случаях, когда используется таблица цветов. Вариант подготовки такой таблицы показан в примере А.8. Размер строки таблицы, а следовательно, и действия, выполняемые при перекодировке, зависят от установленного видеорежима. При режимах Hi-Color строка таблицы занимает 2 байта, а при режимах True color — 4 байта. В примере А. 16 приведена подпрограмма, выполняющая перед записью в видеопамять перекодировку точек по таблице цветов.
Пример А.16. Перекодировка точек в режимах direct color
outpnt : push eax ; сохранение содержимого еах
and eax, OFFh ; очистка старших разрядов еах shl ax, wrdppnt ; учет размера
строки таблицы
add e.x, GenOffs ; ax = смещение начала таблицы
mov ax, qs:[eax] ; !! или mov eax, gs:[eax] для True Color
stosw ; !! или stosd для режимов True Color
pop eax ; восстановление содержимого eax
ret ; возврат из подпрограммы
Текст примера А. 16 является простым повторением текста примера 7.22. Дополнительные подробности вы найдете в разделе.
Заключение.
Мы завершили описание работы с файлами формата BMP. В данном приложении
отсутствует описание построения полноцветных рисунков. Это объясняется
тем, что оно приведено в разделе
основной части книги вместе с текстом соответствующей подпрограммы (см.
пример 7.25).