Воспроизведение не сжатых рисунков
Текст подпрограммы, выполняющей построение рисунка произвольного размера, приведен в примере 3.22. Перед ее вызовом в регистре di надо указать адрес левой верхней точки рисунка в видеопамяти и установить окно, которому принадлежит этот адрес. Напоминаем, что регистр es должен содержать код видеосегмента (содержимое переменной vbuff).
Пример 3.22. Построение рисунка произвольного размера.
SwpOf fs | dw 0 | адрес (смещение) в буфере обмена |
SwpSeg | dw 0 | значение сегмента, содержащего буфер обмена |
iwidth | dw 0 | ширина строки рисунка |
iheight | dw 0 | количество строк в рисунке |
numbyte | dw 0 | количество байтов в считываемой порции данных |
part | dw 0 | количество строк в считываемой порции данных |
remline | dw 0 | остающееся не выведенным количество строк |
jnc sucread | › чтение без ошибок | |
i | Здесь должны выполняться действия при ошибке чтения | |
sucread: | mov ex, part | сх = стандартное количество строк |
cmp remline, ex | осталось меньше строк? | |
jae @F | › нет, обходим команду пересылки | |
mov ex, remline | сх = оставшееся число строк | |
@@: | sub remline, ex | уменьшаем оставшееся число строк |
xor si, si | адрес начала в буфере обмена | |
drwout: | push ex | сохраняем счетчик повторов |
mov ex, iwidth | задаем размер строки рисунка | |
call drawline | построение очередной строки | |
pop ex | восстанавливаем счетчик повторов | |
add di, bx | адрес начала следующей строки | |
jnc @F | › адрес в пределах сегмента | |
call NxtWin | установка следующего окна | |
@@: | loop drwout | управление повторами цикла |
cmp remline, 0 | все строки выведены? | |
jne NewPart | › нет, продолжаем построение | |
PopReg <Cur win, fs> | восстановление Cur win и fs | |
popa | восстановление всех регистров | |
call setwin | восстановление исходного окна | |
ret | возврат из подпрограммы |
Выполнение подпрограммы примера 3.22 начинается с подготовительных действий. Две первые команды сохраняют в стеке содержимое используемых регистров и значение переменной Cur_win. Затем в регистр fs помещается сегмент буфера обмена, а переменная Swpoffs очищается для расположения считываемых из файла данных с начала буфера обмена. Следующие восемь команд формируют значение переменных part, numbyte, и remline, последняя является счетчиком еще не выведенных строк, поэтому ее исходное содержимое равно высоте рисунка. Остается сформировать в регистре bx константу horsize – iwidth для коррекции адресов строк в видеопамяти.
Построение рисунка выполняют два вложенных цикла. Внешний имеет метку NewPart, а внутренний – drwout. Во внешнем цикле производится чтение из файла очередной порции данных, уточнение размера прочитанной порции (содержимого регистра сх), оставшегося количества строк (переменная remline) и очистка регистра si. После этого выполняется внутренний цикл, выводящий на экран прочитанную порцию строк.
Внутренний цикл полностью совпадает с аналогичным циклом примера 3.21, поэтому мы опустим его описание.
По окончании работы внутреннего цикла проверяется значение переменной remline и если оно отлично от нуля, то происходит возврат на начало внешнего цикла. Если все строки выведены на экран, то восстанавливаются сохраненные в стеке величины, исходное окно видеопамяти и происходит возврат на вызывающий модуль.