18 января 2002
167

СДВИГ



ПОЛНЫЙ ТЕКСТ И ZIР НАХОДИТСЯ В ПРИЛОЖЕНИИ

- 228 -

Раздел 5. Сдвиг экрана и страницы.

Сдвиг экрана и разбиение на страницы - это два способа перено-
са блока информации из памяти на экран. При сдвиге одна из границ
экрана сдвигается внутрь, стирая информацию на противоположной
стороне. Затем освободившаяся область заполняется из памяти.
Повторение этого действия строка за строкой создает иллюзию сдви-
га экрана.
С другой стороны, разбиение на страницы основано на одновре-
менном хранении нескольких экранов информации в видеобуфере и
переключении вывода с одной страницы на другую. Использование
дисплейных страниц невозможно на монохромном адапторе, поскольку
его памяти хватает только для одного символьного экрана. Другие
видеосистемы в большинстве экранных режимов могут работать с
несколькими страницами. Использование страниц дисплея особенно
полезно при построении сложных картин `за кулисами`; после того
как эта работа завершена, новый экран выводится моментально.
Процедура, имитирующая работу со страницами для монохромного
адаптора приведена в. Она особенно полезна, когда Вы
имеете дело с медленным выводом на экран в Бейсике.

- 229 -

4.5.1 Вертикальный сдвиг текстового экрана.

Когда текстовый экран сдвигается вверх, то строки со 2-й по
25-ю переписываются на строки с 1-й по 24-ю, а следующая строка
данных выводится в 25-й строке. При этом верхняя строка, поверх
которой осуществлется вывод теряется, хотя она продолжает су-
ществовать в памяти. Сдвиг вниз устроен аналогично.

Высокий уровень.

Бейсик утомительно медлителен при своих манипуляциях с экра-
ном. Для быстрого сдвига Вы можете пожелать использовать процеду-
ру на машинном языке, которая не делает ничего другого, кроме как
использует прерывание 10Н, как описано ниже в пункте средний
уровень. Процедура позволяет сдвигать весь экран или любое окно в
нем. Приложение Г показывает как включать подпрограммы на машин-
ном языке в Ваши программы. Ваша программа на Бейсике должна
указывать координаты верхнего левого и нижнего правого углов
окна, которые могут лежать в диапазоне от 0 до 24 и от 0 до 79.
Требуется также параметр, указывающий направление сдвига: вверх
или вниз (6 и 7, соответственно), число строк на которое нужно
сдвинуть (если 0, то окно очищается) и значение байта атрибутов
для очищаемых строк (для `нормальных` - 7). Используйте для них
целые переменные. В нижеприведенно примере экран сдвигается вниз
на одну строку, а затем освободившаяся строка освобождается.

100 ```данные для подпрограммы
110 DАТА &Н55, &Н8В, &НЕС, &Н8В, &Н76, &Н12, &Н8А
120 DАТА &Н24, &Н8В, &Н76, &Н10, &Н8А, &Н04, &Н8В
130 DАТА &Н76, &Н0Е, &Н8А, &Н2С, &Н8В, &Н76, &Н0С
140 DАТА &Н8А, &Н0С, &Н8В, &Н76, &Н0А, &Н8А, &Н34
150 DАТА &Н8В, &Н76, &Н08, &Н8А, &Н14, &Н8В, &Н76
160 DАТА &Н06, &Н8А, &Н3С, &НСD, &Н10, &Н5D, &НСА
170 DАТА &Н0Е, &Н00
180 ```помещаем данные в сегмент &Н2000
190 DЕF SЕG = &Н2000 `помещаем данные начиная с &Н2000
200 FОR N = 0 ТО 43 `44 байта
210 RЕАD Q `читаем один байт
220 РОКЕ N,Q `помещаем его в память
230 NЕХТ `следующий

300 ```в программе
310 GОSUВ 500 `сдвигаем на строку
320 LОСАТЕ 1,1: РRINТ ТЕХТ$(LINЕРТR); `выводим строку текста

500 ```подпрограмма сдвига
510 DЕFINТ А-Z `используем целые переменные
520 ТLR = 0 `левая верхняя строка
530 ТLС = 0 `левый верхний столбец
540 ВRR = 24 `нижняя правая строка
550 ВRС = 79 `нижний правый столбец
560 NUМRОWS = 1 `число строк сдвига
570 DIR = 7 `направление сдвига вниз
580 FILL = 7 `заполнение обычным атрибутом
590 DЕF SЕG = &Н2000 `указываем на подпрограмму
600 SСRОLL = 0 `начинаем с 1-го байта
610 САLL SСRОLL(DIR,NUМRОWS,ТLR,ТLС,ВRR,ВRС,FILL)
620 RЕТURN `все сделано

- 230 -

Средний уровень.

Функция 6 прерывания 10Н сдвигает любую часть экрана вверх, а
функция 7 - вниз. В обоих случаях АL содержит число строк сдвига,
а когда АL = 0, то весь экран чистится, а не сдвигается. СН:СL
содержат строку и столбец левого верхнего угла, а DН:DL - содер-
жат координаты правого нижнего угла. Появлящиеся из-за сдвига
строки чистые и они выводятся с кодом атрибутов из ВН.

;---сдвиг вверх на одну строку
МОV АН,6 ;номер функции сдвига вверх
МОV АL,1 ;число строк сдвига
МОV СН,0 ;строка левого верхнего угла
МОV СL,0 ;столбец левого верхнего угла
МОV DН,24 ;строка правого нижнего угла
МОV DL,79 ;столбец правого нижнего угла
МОV ВН,7 ;атрибуты очищаемой строки
INТ 10Н ;делаем сдвиг

Низкий уровень.

Вертикальный сдвиг всего экрана это тривиальная задача, пос-
кольку правая граница одной строки в памяти продолжается левой
границей следующей строки. Сдвиг всего содержимого видеобуфера на
160 байт вверх по памяти (80 символов в строке * 2 байта на сим-
вол) приводит к сдвигу экрана вниз на одну строку. Если Вы пишете
свою собственную процедуру сдвига экрана, использующую прямое
отображение в память, то не забывайте об интерференции, которая
возникает на цветном дисплее и РСjr. Эта проблема обсуждается в
. Обычное решение этой проблемы состоит в проверке статус-
ного байта, ожидая пока он разрешит запись в видеобуфер. Вам
придется поэкспериментировать, чтобы определить сколько данных Вы
можете записать за один цикл.
Другое решение этой проблемы состоит в выключении экрана на
время операции сдвига, а затем в его восстановлении. `Выключение
экрана` подразумевает, что вывод содержащихся в видеобуфере дан-
ных запрещен, но сам буфер при этом не изменяется. Этот процесс
используется функцией сдвига ВIОS, использованной выше. Хотя это
не очень приятно для глаз, но все-таки не так плохо, как уже
упоминавшаяся интерференция.
Для выключения экрана у цветного графического дисплея надо
сбросить бит 3 порта с адресом 3D8Н. Изменение бита назад на 1
моментально включает экран обратно. Этот адрес порта соответст-
вует регистру выбора режима цветного графического адаптора. Этот
однобайтный регистр только для записи, поэтому программа не может
просто прочитать его, изменить значение бита 3 и вернуть прочи-
танный байт. Вместо этого Вам необходимо определить также пра-
вильную установку всех остальных битов (перечисленных в).
Для РСjr этот бит расположен в регистре управления режимом 1
массива ворот дисплея. В объяснено как получить доступ и
запрограммировать этот регистр.

- 231 -

4.5.2 Сдвиг текстового экрана горизонтально.

Горизонтальный сдвиг иногда требуется в специальных программах
обработки текста, таких как текстовые редакторы. Операционная
система не имеет для этого специальных средств. По этой причине
данная задача немного сложнее чем вертикальный сдвиг - но несу-
щественно. Рассмотрим случай, когда Вы хотите, чтобы экран сдви-
гался влево на 5 позиций. При этом левые 5 столбцов исчезнут,
весь остальной текст сдвигается влево, а самые правые 5 столбцов
должны быть очищены. Поскольку видеобуфер представляет из себя
одну длинную строку, то если каждый символ буфера сдвинуть на 10
байтов вниз, то суммарный эффект будет состоять в том, что самые
левые 5 символов каждой строки будут передвинуты в последние 5
позиций предыдущей строки. Таким образом, весь экран будет сдви-
нут влево на 5 позиций, передвигая 5 ненужных столбцов в правую
часть экрана. Все что после остается - это очистить правые 5
столбцов. Это легко делается с помощью процедуры вертикального
сдвига, которая может выполняться для любой части экрана
и которая очищает указанную область если указать сдвиг на 0
строк. Рисунок 4-6 иллюстрирует этот метод.

Низкий уровень.

В этом примере осуществляется сдвиг на 5 позиций влево. Легко
изменить его для сдвига вправо или для другого значения позиций
сдвига. При использовании прямого отображения в память этот метод
дает практически моментальный сдвиг экрана.

;---сдвигаем все вниз на 10 байтов
МОV АХ,0В000Н ;указываем на буфер монохромного
МОV ЕS,АХ ;дисплея
МОV DS,АХ ;
МОV SI,10 ;сдвигаем из SI ...
МОV DI,0 ;... в DI
МОV СХ,1995 ;сдвигаем все кроме последних 5 байт
RЕР МОVSW ;осуществляем сдвиг
;---очищаем правый край
МОV АН,6 ;функция вертикального сдвига
МОV АL,0 ;сдвиг на 0 строк чистит окно
МОV СН,0 ;строка левого верхнего угла
МОV СL,75 ;столбец левого верхнего угла
МОV DН,24 ;строка правого нижнего угла
МОV DL,79 ;столбец правого нижнего угла
МОV ВН,7 ;атрибут для очищаемых позиций
INТ 10Н ;чистим окно

- 232 -

4.5.3 Переключение между текстовыми страницами.

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

Режим Тип Число страниц Начало буфера

0 алфавитноцифровой 8 В800
1 алфавитноцифровой 8 В800
2 алфавитноцифровой 8 В800
3 алфавитноцифровой 8 В800
4 графический 1 В800
5 графический 1 В800
6 графический 1 В800
7 алфавитноцифровой 1/8 В800
8 графический переменное В800
9 графический переменное В800
А графический переменное В800
D графический 2/4/8 А000
Е графический 1/2/4 А000
F графический 1/2 А000
10 графический 1/2 А000

Режимы 8-А - графические режимы РСjr; число страниц для них ме-
няется в зависимости от того, сколько оперативной памяти отведено
под видеобуфер. Размер страницы равен 2К или 4К для алфавитноциф-
ровых режимов, 32К - для четырех цветов при высоком разрешении
или 16 цветов при умеренном разрешении и 16К - для всех остальных
режимов. Режимы D-10 поддерживаются ЕGА. Количество страниц ме-
няется в зависимости от установленной памяти. Режимы F и 10 тре-
буют наличия не менее 128К памяти. Режим 7 разрешает одну страни-
цу для монохромного адаптора и 8 страниц для ЕGА.
Монохромный адаптор не имеет памяти для дополнительных стра-
ниц. Однако нет никаких причин, по которым часть основной памяти
нельзя было бы использовать как буфер дисплея. В этом случае
страничная организация осуществляется за счет быстрого обмена
всего содержимого буфера в памяти с видеобуфером (адрес которого
В000:0000). Буфер в основной памяти можно рассматривать как
`псевдостраницу`. Хотя это и не настоящее разбиение на страницы,
но результат будет почти такой же, если для пересылки данных Вы
будете использовать ассемблерную процедуру.
При использовании страниц надо позаботиться о том, чтобы опе-
рации вывода на экран направлялись на нужную страницу. Программа
не обязана выводить данные на ту страницу, которая в данный мо-
мент изображается на экране. На самом деле, часто наоборот жела-
тельно конструировать экран `за кулисами`, а затем моментально
выводить уже готовое изображение. Этот метод особенно полезен,
когда необходимо конструировать сложный вывод в Бейсике, у кото-
рого вывод очень медленный. ВIОS хранит в своей области данных
однобайтную переменную, указывающую, какая из страниц выводится в
данный момент. Диапазон значений этой переменной от 0 до 7. Она
расположена по адресу 0040:0062.

- 233 -

Высокий уровень.

Бейсик использует команду SСRЕЕN для установки страницы, на
которую будет идти вывод (активной страницы) и выводимой страницы
(видимой страницы). Страницы нумеруются от 0 до 3 для текстов с
80 символами в строке и от 0 до 7 для 40-символьных. Третий пара-
метр за командой SСRЕЕN устанавливает активную страницу.
SСRЕЕN,,2 приводит к тому, что все операторы РRINТ будут работать
со страницей 2. Четвертый параметр устанавливает видимую страни-
цу. SСRЕЕN,,,1 приводит к тому, что на экран будет выводиться
страница 1. Когда видимая страница не указывается, то автомати-
чески принимается, что она совпадает с активной.
Для выделения памяти под страницы на РСjr используется опера-
тор СLЕАR. Этот оператор устанавливает общее количество памяти,
отводимое под буфер экрана, которое при старте равно 16384 байта.
Чтобы добавить вторую страницу размером 16К, напишите
СLЕАR,,,32768. Добавочные текстовые страницы требуют 4096 байтов
каждая. При условии, что таким образом была отведена память,
команды оператора SСRЕЕN для работы со страницами работают опи-
санным образом. Только РСjr имеет добавочный параметр оператора
SСRЕЕN, который стирает страницу (т.е. переводит ее в цвет фона).
Детали описаны в руководстве по Бейсику. Оператор РСОРY также
уникален для РСjr. Он копирует изображение из одной страницы в
другую. Например, РСОРY 2,1 целиком копирует страницу 2 на стра-
ницу 1.
Хотя монохромный адаптор не имеет памяти для страниц дисплея,
однако имеется способ устроить своего рода `псевдостраницы`.
Нижеприведенная процедура на машинном языке рассматривает блок
памяти как дисплейную страницу. При вызове этой процедуры она
обменивает содержимое видеобуфера с содержимым этой области памя-
ти. В результате мы имеем как бы две дисплейные страницы. (В
приложении Г объясняется как включать подпрограммы на машинном
языке в программы на Бейсике.)
Вы должны отвести блок памяти размером 4000 байт для псевдост-
раницы, помимо памяти, содержащей программу на машинном языке. В
примере блок начинается с адреса сегмента &Н2000, а процедура
помещена по адресу &Н2200. Сегментный адрес блока содержится в
9-м и 10-м байтах машинного кода и Вы легко можете изменить его.
Видно, что адрес &Н2000 представлен как &Н00, &Н20 в операторе
DАТА. Это следствие того, что младшие цифры всегда размещаются в
младших ячейках памяти. Если Вы хотите разместить блок, скажем по
адресу 1234:0000, то надо изменить байты 9 и 10 на &Н34, &Н12.
Вам может потребоваться очистить псевдостарницу от всякой
ерунды, оставшейся от других программ. В строках 230-260 это
достигается за счет засылки символа пробела (АSСII 32) в каждый
байт (32 служит `нормальным` байтом атрибутов). Программа может
осуществлять вывод на экран обычным образом, а затем переносить
содержимое на псевдостраницу. Но если хотите, то Вы можете осу-
ществлять вывод прямо на псевдостраницу, используя прямое отобра-
жение в память.

- 234 -

100 ```машинный код
110 DАТА &Н1Е, &Н06, &НВ8, &Н00, &НВ0, &Н8Е, &НС0
120 DАТА &НВ8, (3&Н00, &Н20), &Н8Е, &НD8, &НВF, &Н00
130 DАТА &Н00, &НВЕ, &Н00, &Н00, &НFС, &НВ9, &НD0
140 DАТА &Н07, &Н26, &Н8В, &Н1D, &НАD, &НАВ, &Н89
150 DАТА &Н5D, &НFЕ, &НЕ2, &НF6, &Н07, &Н1F, &НСВ
160 ```помещаем код в память
170 DЕF SЕG = &Н2200 `указываем адрес процедуры
180 FОR N = 0 ТО 34 `начинаем с первого байта
190 RЕАD Q `читаем байт процедуры
200 РОКЕ N,Q `пишем его в память
210 NЕХТ `
220 ```чистим псведостраницу
230 DЕF SЕG = &Н2000 `адрес начала псевдостраницы
240 FОR N = 0 ТО 3999 `для каждого символа и атрибута
250 РОКЕ N,32 `помещаем код 32
260 NЕХТ `пока не очистим весь буфер

500 ```пишем прямо в псевдостраницу
510 DЕF SЕG = &Н2000 `указываем на ее адрес
520 S$ = `РSЕUDОРАGЕ` `выводим слово посреди страницы
530 М = LЕN(S$) `получаем длину строки
540 FОR N = 1 ТО М `для каждого символа строки
550 РОКЕ N*2+2000, АSС(МID$(S$,N,1)) `помещаем его в буфер
560 NЕХТ `

600 ```теперь используем процедуру
610 РRINТ `SСRRЕN 1` `печатаем сообшение на экран
620 DЕF SЕG = &Н2200 `указываем на процедуру
630 РSЕUDОРАGЕ = 0 `начинаем с начала процедуры
640 САLL РSЕUDОРАGЕ `обмениваем страницы
650 САLL РSЕUDОРАGЕ `повторяем обмен
660 ...

Средний уровень.

Функция 5 прерывания 10Н выбирает текущую страницу дисплея для
вывода. Надо просто поместить номер страницы в АL:

;---установка видимой страницы
МОV АН,5 ;номер функции
МОV АL,2 ;номер страницы (начиная с 0)
INТ 10Н ;устанавливаем страницу

Однако эта функция не устанавливает страницу, на которую будет
идти вывод. Любое из прерываний ВIОS, которые выводят на экран
(функции прерывания 10Н), требует чтобы номер страницы был указан
в качестве входного параметра в одном из регистров. Однако все
прерывания вывода на экран МS DОS пишут на текущую видимую стра-
ницу. Таким образом, для `закулисных` операций Вам необходимо
пользоваться прерыванием 10Н.
Для получения информации о текущей странице надо выполнить
функцию F прерывания 10Н, которая возвращает статус дисплея.
Номер страницы при этом возвращается в ВН.

- 235 -

Низкий уровень.

Дисплейные страницы выбираются за счет изменения точки видео-
памяти, начиная с которой монитор принимает данные. Эта точка
памяти устанавливается регистрами 12 (старший байт) и 13 (младший
байт) микросхемы 6845, которые называются регистрами стартового
адреса. Значения адресов раздела страниц для буфера, начинающего-
ся с В800 такие:

40 символов 80 символов

страница 0 0000Н 0000Н
1 0400Н 0800Н
2 0800Н 1000Н
3 0С00Н 1800Н
4 1000Н
5 1400Н
6 1800Н
7 1С00Н

В объясняется как программировать регистры микросхемы
6845, а в содержится пример программирования стартового
адреса. В последнем примере надо просто присвоить ВХ одно из
значений вышеприведенной таблицы. Конечно, при этом устанавли-
вается только выводимая страница. Для записи в определенную стра-
ницу на низком уровне надо использовать одно из значений таблицы
в качестве смещения в видеобуфере при прямом отображении в па-
мять.
Поскольку прямое отображение в память работает очень быстро,
то иллюзия страниц может быть легко создана на монохромном дисп-
лее. Выделите блок размером 4000 байтов для хранения страницы.
Хотя монохромный адаптор не может непосредственно читать из обыч-
ной памяти, содержимое этого буфера и видеобуфера можно обменять
настолько быстро, что никто не зметит разницы. Следующая процеду-
ра обменивает содержимое этих двух областей.

;---в сегменте данных
РРАGЕ DW 2000 DUР(720Н) ;заполняем буфер пробелами

;---пересылка между псевдостраницей и видеобуфером
МОV АХ,0В000Н ;указываем на видеобуфер
МОV ЕS,АХ ;
МОV АХ,SЕG РРАGЕ ;указываем на псевдостраницу
МОV DS,АХ ;
RЕРЕАТ: МОV DI,0 ;DI на начало видеобуфера
МОV SI,ОFFSЕТ РРАGЕ ;SI на начало псевдостраницы
СLD ;направление вперед
МОV СХ,2000 ;будем пересылать 2000 слов
;берем слово из видеобуфера в ВХ
LОDSW ;слово из псевдостраницы в АХ
SТОSW ;слово из АХ в видеобуфер
-2,ВХ ;слово из ВХ в псевдостраницу
LООР NЕХТ_WОRD ;

РСjr хранит регистр страницы в порте с адресом 3DFН. Значение
битов этого регистра следующее:

биты 2-0 какая страница выводится (от 0 до 7)
5-3 какая страница пишется (от 0 до 7) при выводе
по адресу сегмента В800Н
7-6 = 00 для всех текстовых режимов
= 01 для графических режимов с 16К
= 11 для графических режимов с 32К

- 236 -

4.5.4 Сдвиг между страницами текста.

Поскольку страницы текста прилегают друг к другу в видеобуфе-
ре, то небольшой текстовый массив может целиком помещаться в этой
памяти. В этом случае текст сдвигаться вверх и вниз по экрану не
передвигаясь реально в буфере. Вместо этого экран начинает пока-
зывать содержимое буфера, начиная с различных точек и тем самым
создавая иллюзию сдвига. Этот метод называется аппаратным сдви-
гом.
Аппаратный сдвиг достигается за счет изменения стартового
адреса дисплея, который является числом, указывающим на символ в
видеобуфере, который будет выводиться в левом верхнем углу экра-
на. Добавление 80 к этому числу `сдвигает` весь экран на одну
строку вверх, а вычитание 80 - на одну строку вниз. В режиме с 40
символами в строке надо вместо 80 прибавлять или вычитать 40. На
рис. 4-7 приведена диаграмма аппаратного сдвига.
Отметим, что регистр стартового адреса не считает байты атри-
бутов, поэтому Вы должны вычислять адреса памяти по-другому, чем
при прямом отображении в память. Имейте также ввиду, что несмотря
на наличие разрывов памяти между границами страниц (96 байтов
между 80-символьными страницами и 48 байтов между 40-символьными
страницами) микросхема 6845 пропускает эти области и сдвиг непре-
рывно происходит с одной страницы на следующую. Аппаратный сдвиг
происходит настолько быстро, что Вам может оказаться необходимым
вставить процедуру задержки, чтобы пользователь имел возможность
увидеть насколько сдвинулся экран.
ВIОS хранит текущее значение регистра стартового адреса в
переменной в своей области данных. Эта двухбайтная переменная
расположена по адресу 0040:004ЕН.

Низкий уровень.

Стартовый адрес содержится в регистрах 12 (старший байт) и 13
(младший байт) микросхемы 6845. В объясняется работа этой
микросхемы. Прежде чем адресуемый байт направляется в порт с
адресом 3D5Н, необходимо послать номер адресуемого регистра в
порт 3D4Н. В данном примере экран сдвигается вверх на одну стро-
ку. Переменная SТАRТ_АDDRЕSS содержит адрес первого символа теку-
щей верхней строки экрана.

МОV ВХ,SТАRТ_АDDRЕSS ;начинаем с начала буфера
АDD ВХ,80 ;сдвигаем на 1 строку (80 символов)
МОV DХ,3D4Н ;вывод в адресный регистр
МОV АL,12 ;адресуем регистр 12
ОUТ DХ,АL ;посылаем запрос
INС DХ ;теперь выводим в командный регистр
МОV АL,ВН ;старшее слово в АL
ОUТ DХ,АL ;посылаем его в регистр 12
DЕС DХ ;обратно к адресному регистру
МОV АL,13 ;адресуем регистр 13
ОUТ DХ,АL ;посылаем запрос
INС DХ ;снова командный регистр
МОV АL,ВL ;младшее слово в АL
ОUТ DХ,АL ;посылаем в регистр 13

ПОЛНЫЙ ТЕКСТ И ZIР НАХОДИТСЯ В ПРИЛОЖЕНИИ
Рейтинг всех персональных страниц

Избранные публикации

Как стать нашим автором?
Прислать нам свою биографию или статью

Присылайте нам любой материал и, если он не содержит сведений запрещенных к публикации
в СМИ законом и соответствует политике нашего портала, он будет опубликован