Иллюстрированный самоучитель по SVGA

Построение рисунков. Варианты построения строк.

Распаковка 2-цветных строк

Если при построении рисунка использовано только два цвета, например черный и белый, то код точки помещается в одном разряде и может принимать только два значения 0 и 1. В таких случаях для сокращения размеров файла в одном байте располагаются коды восьми точек. В старшем разряде байта находится код первой точки, а в младшем – последней, поэтому выделять коды точек надо начиная со старшего разряда. В зависимости от количества точек в строке последний байт может быть заполнен частично. Не следует считать, что двухцветные рисунки обязательно черно-белые – их цвета зависят от кодов, находящихся в прилагаемой к файлу палитре.

Подпрограмма для распаковки строки в процессе построения 2-цветного рисунка приведена в примере 3.18. Перед ее вызовом устанавливается окно видеопамяти, в котором должна располагаться строящаяся строка, а адрес первой точки помещается в регистр di. Пара регистров fs:si должна содержать адрес оперативной памяти, начиная с которого хранится упакованная строка. В регистре сх указывается количество точек в строке.

Пример 3.18. Подпрограмма построения строки 2-цветного рисунка.

drwlinl: push bx сохраняем содержимое bp
  mov bx, ex bp = ex (количество точек в строке)
Ipdrwll: lods byte ptr fs: [si] читаем в al код очередного байта
  mov ah, al копируем коды из al в ah
  mov ex, 08 количество повторов цикла распаковки
outSpnt: xor al, al очищаем регистр al
  shl ah, 01 сдвигаем ah на разряд влево
  adc al, 00 прибавляем переполнение к al
  stosb   записываем код очередной точки
  or di, di начало нового сегмента?
  jne @F; › нет, обход команды call NxtWin
  call NxtWin; установка следующего окна
@@: dec bx bx = bx -1
  je drlret если bx = 0, то строка построена
  loop outSpnt управление внутренним циклом
  jmp short Ipdrwll › на обработку следующего байта
drlret: pop bx восстановление содержимого bx
  ret   выход из подпрограммы

Подпрограмма примера 3.18представляет собой два вложенных цикла. Имя внешнего цикла ipdrwii, а внутреннего – outSpnt.

Внешний цикл считывает очередной байт образа строки, копирует его в регистр ah и задает количество повторов внутреннего цикла.

Во внутреннем цикле производится распаковка очередной группы точек и запись их кодов в видеопамять. Распаковку выполняют три первые команды внутреннего цикла. Первая из них очищает регистр ai, вторая сдвигает содержимое регистра ah на разряд влево. При сдвиге старший разряд регистра ah переносится в С-разряд регистра флагов, поэтому если он содержал единицу, то вырабатывается признак переполнения. Третья команда (adc ai, оо) прибавляет содержимое С-разряда к регистру ai. В результате, в зависимости от кода очередной точки, в регистре ai окажется 0 или 1. Полученный код точки команда stosb записывает в видеопамять. Затем проверяется текущий адрес видеопамяти и при необходимости устанавливается следующее окно видеопамяти.

После записи каждой точки содержимое регистра bx уменьшается на 1 и если оно окажется равным нулю, то происходит переход на метку drlret для завершения подпрограммы. В противном случае команда loop управляет выводом восьми точек. После этого происходит короткий безусловный переход на начало внешнего цикла для обработки следующего байта.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.