Работа с прямоугольными областями
Пересылка в видеопамять
При работе с графикой достаточно часто приходится сохранять и восстанавливать содержимое видеопамяти. Это делается, например, при каждом перемещении курсора.
В примере 7.14 приведен текст подпрограммы, выполняющей копирование содержимого оперативной памяти в видеопамять. Входными параметрами подпрограммы являются размер прямоугольной области и адреса операндов источника и приемника. Ширина прямоугольной области помещается в регистр dx, а высота в регистр сх. Адрес оперативной памяти (источника) указывается в регистрах fs:si. Адрес видеопамяти (приемника) помещается в регистр di и устанавливается окно видеопамяти, которому принадлежит этот адрес. В регистре es должен находиться код видеосегмента (A000h).
Пример 7.14. Подпрограмма пересылки из оперативной в видеопамять.
Rstreg: PushReg <bx, ex, di, si, Cur_win>; сохранение в стеке call calloffs; вычисление константы offsline mvsr: push сх сохранение значения счетчика строк mov ex, dx задание количества точек в строке call drawline копируем очередную строку add di, bx адрес начала следующей строки jnc @F › адрес в пределах окна call Nxtwin установка следующего окна @@: pop сх восстановление счетчика строк loop mvsr управление повторами цикла PopReg <Cur_win, si, di, ex, bx>; восстановление из стека call setwin восстановление исходного окна ret возврат из подпрограммы
Текст примера не требует особых пояснений – подобные циклы мы описывали неоднократно, например,(подпрограмма draw). Поговорим о том, что явно не следует из текста.
Зависимость от установленного видеорежима в данном примере скрыта в подпрограммах calloffs и drawline. Если вы выберете второй вариант подпрограммы calloffs примера 7.13 и подпрограмму drawline, текст которой описан в примере 7.12, то подпрограмма Rstreg будет выполняться в любом видеорежиме, независимо от размера кода точки.
Размер прямоугольной области, выраженный в байтах, не должен превышать размера стандартного сегмента памяти, т. е. 65 536 байтов. Это ограничение связано с тем, что пересылаемые данные находятся в оперативной памяти, которая сегментирована так же, как и видеопамять, а в примере 7.14 отсутствует контроль значения адресов оперативной памяти.
Способы контроля значений адресов оперативной и видеопамяти ничем не отличаются друг от друга, но существенно различаются способы переключения сегментов, которые зависят еще и от типа оперативной памяти. Они подробно описаны в приложении Б данной книги. Там же приведен пример подпрограммы, выполняющей сохранение или восстановление содержимого всего пространства видеопамяти отображаемого на экране (см. примеры Б.7 и Б.8).
Пересылка из видеопамяти
Для сохранения исходного содержимого видеопамяти производится его копирование (пересылка) в оперативную память. Нас интересуют универсальные процедуры пересылки, основанные на применении строковых операций. Однако у строковых операций фиксированы регистры, содержащие адреса операндов источника и приемника. Поэтому при пересылке в обратном направлении в es:di должен находиться адрес оперативной памяти, а в fs-.si – адрес видеопамяти. Для удобства лучше сохранить единообразный способ указания адресов в регистрах и изменять его в подпрограмме на время пересылки.
Заметим, что и после перестановки адресов использовать подпрограмму drawiine из примера 7.12 нельзя. При ее составлении предполагалось, что адрес видеопамяти находится в регистре di, а он оказался в регистре si. Поэтому надо сделать копию примера 7.12, присвоить ей новое имя, например saveiine, и заменить в двух командах копии имя регистра di именем регистра si. В результате получится универсальная подпрограмма, выполняющая сохранение строки видеопамяти в оперативной памяти.