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 и если оно отлично от нуля, то происходит возврат на начало внешнего цикла. Если все строки выведены на экран, то восстанавливаются сохраненные в стеке величины, исходное окно видеопамяти и происходит возврат на вызывающий модуль.
Подпрограмма чтения с диска. Во внешнем цикле происходит обращение к подпрограмме Readf. Она считывает в буфер обмена порцию данных, размер которой (в байтах) задается в регистре сх. Ниже (см. пример 3.23) приведен один из возможных примеров такой подпрограммы.