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

Работа с расширенной памятью

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

Способ пересылки большого блока

При выполнении графических задач может потребоваться сохранение содержимого всего рабочего пространства видеопамяти. Учитывая его большие размеры, сохранение в обычной памяти либо не целесообразно, либо просто невозможно, для этого лучше подходит расширенная память.

Размер рабочего пространства видеопамяти зависит от установленного видеорежима, он вычисляется умножением размера строки в байтах на количество строк на экране (bperiine versize). Для временного хранения произведения нужна переменная, состоящая из двух слов (но не одно двойное слово), назовем ее bisize. В первом слове будет храниться старшая часть произведения, а во втором слове – младшая. Старшая часть указывает количество полных окон видеопамяти, а младшая часть – количество байтов в последнем окне, оно может быть равно нулю.

Если в результате умножения в первом слове bisize окажется число N, а во втором bisize+2 число м, то размер отображаемой части видеопамяти составляет N* 6553б + м байтов, т. е. надо переслать N полных сегментов и еше м байтов. Поэтому перед пересылкой очередного фрагмента данных необходимо уточнять его размер.

Кроме того, перед пересылкой каждого фрагмента производится отображение очередной группы логических страниц блока, выделенного в расширенной памяти на физические с помощью подпрограммы mapseg, приведенной в примере Б.6 Для исключения лишних проверок можно каждый раз отображать по 4 страницы. В процессе отображения mapseg изменяет номера логических страниц (содержимое регистра bx), поэтому при работе с ней достаточно задать номер исходной страницы и в дальнейшем просто не изменять текущее содержимое регистра bx.

Для упрощения и ускорения пересылки нужен микропрограммный цикл на основе строковой операции movs, работающей с двойными словами.

Подпрограмма пересыки блока

Программная реализация пересылки показана в примере Б.7. Перед вызовом подпрограммы в регистрах es и fs указываются коды видеобуфера и сегмента EMS, в примере Б.8 показано, как это делается.

Предполагается, что в разделе данных задачи описана переменная bisize, а в расширенной памяти зарезервирован блок, размер которого не меньше размера отображаемой части видеопамяти.

Пример Б.7. Пересылка содержимого рабочей области экрана.

movebl: push Cur_win pusha
mov ax, BaseWin
mov Cur_win, ax
call Setwin
mov ax, bperline
mul versize
mov bisize, dx
mov blsize+2, ax
xor bx, bx
mov dx, Ehndlr
xor di, di
xor si, si
сохраняем текущее окно видеопамяти
сохраняем "все" регистры
ах = BaseWin (или ах = 0)
Cur_win = BaseWin
установка нулевого окна видеопамяти
ах = размер строки в байтах
dx:ax = bperline * versize
bisize = число полных окон
bisize +2 = размер последнего окна
bx = исходная логическая страница
dx = идентификатор файла
di = 0 исходный адрес
si = 0 исходный адрес
mloop: mov ex, 4000h 0.25 размера стандартного сегмента
dec blsize уменьшаем количество сегментов
jns sc I › пересылка полного окна
mov ex, blsize+2 ex = размер последнего окна
shr ex, 02 уменьшаем его в 4 раза
je sc__2 › окно пустое, пересылка окончена
sc I: call mapseg отображаем очередные 4 страницы
rep movs dword ptr [di], fs:[si]; цикл пересылки
call Nxtwin следующее окно видеопамяти
cmp blsize, – 1 пересылка завершена?
jne mloop › нет, продолжаем пересылку
sc_2: pop Cur_win исходное значение видеоокна
рора восстановление "всех" регистров
call Setwin восстановление исходного окна
ret возврат из подпрограммы

Выполнение примера Б.7 начинается с сохранения исходного окна видеопамяти, содержимого всех регистров и установки базового окна. Если переменная Basewin в задаче не используется, то надо просто установить нулевое окно. Затем вычисляется размер отображаемой области видеопамяти, и результат сохраняется в словах bisize и bisize+2. В регистр bx помещается номер нулевой логической странице, а в dx – идентификатор блока. Содержимое этих двух регистров использует только подпрограмма mapseg. Подготовка оканчивается очисткой содержимого индексных регистров si и di.

Основной цикл имеет метку mloop. Его первые шесть команд определяют размер фрагмента пересылаемых данных. Он составляет 16 384 двойных слова, если окно заполнено полностью, или равен значению слова bisize+2, уменьшенному в 4 раза, если окно заполнено частично.

Команда, имеющая метку sc_i, отображает очередные четыре страницы блока на сегмент EMS. Затем микропрограммный цикл пересылает очередной фрагмент данных. Он выполняет основную работу, все остальные команды примера Б. 7 являются вспомогательными.

После пересылки очередного фрагмента проверяется содержимое bisize, и работа подпрограммы продолжается до тех пор, пока его значение не окажется равным "-1". В этом случае из стека выталкиваются значения переменной Cur_win и сохраненных регистров, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.

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