тор будет иметь вид DRAW "X" + VARPTR$(S$) или DRAW "C=" +
VARPTR$(PCOLOR). Сложные рисунки могут быть сохранены в массиве и
затем возвращены на экран в любой момент. Обсуждение этого вопро-
са см. в [4.4.6].

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

Нижеприведенная процедура использует алгоритм Брезенхэма для
вывода прямой линии, соединяющей любые две точки. Она использует
функцию BIOS установки точек и ее можно убыстрить если заменить
эту функцию на встроенную процедуру, использующую прямое отобра-
жение в память. Как и все быстрые алгоритмы данная процедура
избегает операций умножения и деления. Линия рассматривается как
набор сегментов двух типов: тех которые расположены диагонально и
тех, которые расположены горизонтально или вертикально. Для линий
с наклоном больше 1 прямые сегменты вертикальны, в противном
случае они горизонтальны; первая задача алгоритма состоит в вы-
числении наклона. Затем вычисляется выравнивающий фактор, который
следит чтобы некоторое число прямых сегментов имело большую дли-


ну, чем остальные. И, наконец, сложный цикл поочередно выводит
диагональные и прямые сегменты. BX поочередно принимает то поло-
жительные, то отрицательные значения, отмечая какой тип сегмента
выводится. Ниже готовятся данные для вывода диагонали из одного
угла экрана в противоположный:

;---в сегменте данных
START_X DW 0
END_X DW 319
START_Y DW 0
END_Y DW 199
COLOR DB 2
DIAGONAL_Y_INCREMENT DW ?
DIAGONAL_X_INCREMENT DW ?
SHORT_DISTANCE DW ?
STRAIGHT_X_INCREMENT DW ?
STRAIGHT_Y_INCREMENT DW ?
STRAIGHT_COUNT DW ?
DIAGONAL_COUNT DW ?

;---установка режима дисплея
MOV AH,0 ;функция установки режима
MOV AL,4 ;цветной 320*200
INT 10H ;установка режима
;---установка начальных инкрементов для каждой позиции точки
MOV CX,1 ;инкремент для оси x
MOV DX,1 ;инкремент для оси y
;---вычисление вертикальной дистанции
MOV DI,END_Y ;вычитаем координату начальной
SUB DI,START_Y ;точки из координаты конечной
JGE KEEP_Y ;вперед если наклон < 0
NEG DX ;иначе инкремент равен -1
NEG DI ;а дистанция должна быть > 0
KEEP_Y: MOV DIAGONAL_Y_INCREMENT,DX
;---вычисление горизонтальной дистанции
MOV SI,END_X ;вычитаем координату начальной
SUB SI,START_X ;точки из координаты конечной
JGE KEEP_X ;вперед если наклон < 0
NEG CX ;иначе инкремент равен -1
NEG SI ;а дистанция должна быть > 0
KEEP_X: MOV DIAGONAL_Y_INCREMENT,CX
;---определяем горизонтальны или вертикальны прямые сегменты
CMP SI,DI ;горизонтальные длиннее?
JGE HORZ_SEG ;если да, то вперед
MOV CX,0 ;иначе для прямых x не меняется
XCHG SI,DI ;помещаем большее в CX
JMP SAVE_VALUES;сохраняем значения
HORZ_SEG: MOV DX,0 ;теперь для прямых не меняется y
SAVE_VALUES: MOV SHORT_DISTANCE,DI ;меньшее расстояние
MOV STRAIGHT_X_INCREMENT,CX ;один из них 0,
MOV STRAIGHT_Y_INCREMENT,DX ;а другой - 1.


;---вычисляем выравнивающий фактор
MOV AX,SHORT_DISTANCE ;меньшее расстояние в AX
SHL AX,1 ;удваиваем его
MOV STRAIGHT_COUNT,AX ;запоминаем его
SUB AX,SI ;2*меньшее - большее
MOV BX,AX ;запоминаем как счетчик цикла
SUB AX,SI ;2*меньшее - 2*большее
MOV DIAGONAL_COUNT,AX ;запоминаем
;---подготовка к выводу линии
MOV CX,START_X ;начальная координата x
MOV CX,START_Y ;начальная координата y
INC SI ;прибавляем 1 для конца
MOV AL,COLOR ;берем код цвета
;---теперь выводим линию
MAINLOOP: DEC SI ;счетчик для большего расстояния
JZ LINE_FINISHED ;выход после последней точки
MOV AH,12 ;функция вывода точки
INT 10H ;выводим точку
CMP BX,0 ;если BX < 0, то прямой сегмент
JGE DIAGONAL_LINE ;иначе диагональный сегмент
;---выводим прямые сегменты
ADD CX,STRAIGHT_X_INCREMENT ;определяем инкре-
ADD DX,STRAIGHT_Y_INCREMENT ;менты по осям
ADD BX,STRAIGHT_COUNT ;фактор выравнивания
JMP SHORT MAINLOOP ;на следующую точку
;---выводим диагональные сегменты
DIAGONAL_LINE: ADD CX,DIAGONAL_X_INCREMENT ;определяем инкре-
ADD DX,DIAGONAL_Y_INCREMENT ;менты по осям
ADD BX,DIAGONAL_COUNT ;фактор выравнивания
JMP SHORT MAINLOOP ;на следующую точку
LINE_FINISHED:



    4.4.6 Заполнение областей экрана.



Тщательное обдумывание позволяет исключить много излишней
медлительности, которая свойственна многим программам заполнения
областей для графического экрана. Когда заполнение основано на
простых вычислениях, которые действуют по очереди для каждой
точки, то требуются расходующие много времени битовые операции.
Более экономный код может определять все ли битовые позиции опре-
деленного байта видеобуфера должны иметь один и тот же цвет и
когда это условие выполняется, то этому байту присваивается зара-
нее заготовленное значение, которое устанавливает все точки в
правильный цвет. При этом нет необходимости повторять операции
над одним и тем же байтом, каждый раз устанавливая биты только
для одной из точек, информацию о которой содержит данный байт.
В [4.3.4] объяснено как создать описание символа в виде матри-
цы 8*8 точек, имеющего требуемый Вам вид. Хотя такие символы
могут выводиться только в стандартные символьные позиции, но их
использование может существенно облегчить заполнение графиков.
Образец высвечивающий все 8*8 точек может быть выведен в интерва-
ле нескольких строк и столбцов, заполняя область намного быстрее,
чем это достигается при поточечной зарисовке. Этот тип графичес-
ких символов может использоваться совместно с точечной графикой.
Псевдографические символы могут использоваться также для вывода
вращающихся или колеблющихся объектов.

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

Бейсик предоставляет оператор PAINT для заполнения замкнутой
фигуры произвольной формы. Вам необходимо указать только точку
внутри области, а об остальном позаботится процедура. Может быть
указан цвет палетты, которым надо заполнить область, например,
PAINT (100,110),2 заполняет область цветом 2 палетты. Закраска
ведется начиная от указанной точки до тех пор, пока не встретятся
точки с цветом, отличающимся от фонового. Вы можете, наоборот,
указать цвет границы и закраска будет продолжаться во всех нап-
равлениях, пока не будут встречены точки указанного цвета. При
такой закраске линии других цветов, находящиеся внутри границы,
могут быть также закрашены. Код цвета границы следует за кодом
цвета заполнения, таким образом PAINT (100,180),2,3 закрашивает
область цветом 2 до линий цвета 3. Отметим, однако, что эта про-
цедура не заполняет области, находящиеся "за углом", т.е. если
вдоль какой-либо горизонтальной или вертикальной траектории
встретилась точка, имеющая цвет границы, то все последующие точки
вдоль этой траектории не заполняются, даже если фигура имеет
причудливую форму и эти точки принадлежат внутренней части фигу-
ры. В следующем примере выводятся две перекрывающихся рамки цве-
тами циан и магента, а затем последняя рамка заполняется белым
цветом. Сегменты первой рамки, которые попадают в закрашенную
область также заполняются белым.

100 LINE (50,70)-(270,130),1,B 'рисуем рамку цветом циан
110 LINE (100,30)-(220,170),2,B 'рисуем рамку цветом магента
120 PAINT (101,31),3,2 'заполняем вторую рамку белым


Помните, что команда LINE может сама заполнить рамку, если Вы
укажете в качестве параметра 'BF', а не 'B'. Смотрите [4.4.5].
Оператор PAINT имеет "орнаментальные" возможности, которые
позволяют Вам заполнять области указанной картинкой. Элементы
орнамента, которые в режиме умеренного разрешения имеют размер 4
точки в ширину и 8 в высоту (8*8 для высокого разрешения) повто-
ряются по всей указанной области. Рисунок описывается набором
байтов, содержащих цепочку битов для последовательных рядов эле-
мента орнамента. В режиме умеренного разрешения цепочка битов
10000011 описывает 4 точки, первая из которых имеет цвет 2, сле-
дующие 2 - фоновый цвет, а последняя - цвет 3. Эта цепочка соот-
ветствует числу 131 или &H83 (см. приложение Б, в котором обсуж-
даются битовые операции в Бейсике). Обращение этой цепочки в
11000010 даст 193 (&HC1). Они могут быть объединены в элемент
орнамента шириной в 4 точки и высотой в 2 строкой CHR$(&H83) +
CHR$(&HC1). В такую строку могут включаться до 8 байтов, доводя
высоту до 8 точек. Такая строка используется в операторе PAINT
вместо цвета. Вот вывод квадрата, заполненного описанным орнамен-
том:

100 LINE (100,110)-(150,150),1,B 'рисуем рамку
110 PAINT (125,125),CHR$(&H83)+CHR$(&HC1),1 'заполняем ее

Отметим, что нерегулярности элемента орнамента могут приводить к
тому, что процедура PAINT завершается, не закончив заполнения
области. Бейсик решает эту проблему указанием параметра фона для
оператора PAINT. Если у Вас возникнут проблемы, обращайтесь к
руководству по Бейсику за деталями.
Оператор DRAW, позволяющий рисовать сложные линии, также может
заполнять области. Он обсуждается в [4.4.5]. "Текущая точка" (из
которой будет рисоваться следующий сегмент линии) должна быть
помещена внутрь области, ограниченной границей указанного цвета.
В строку оператора DRAW надо поместить кодовую букву P, за кото-
рой должен следовать код цвета закраски и код цвета границы. Для
вывода рамки цветом 1 палетты, а затем ее заполнения цветом 3
напишите DRAW "U10R10D10L10BH1P3,1". Здесь первые четыре кода
рисуют границы рамки, затем код 'BH' перемещает текущую точку
внутрь рамки, не рисуя линии, а затем код 'P' приводит к заполне-
нию рамки. Таким образом могут быть заполнены и более сложные
формы. Отметим, что необязательно при перемещении точки внутрь
области отменять рисование линии вдоль этого пути. Однако, в этом
случае надо использовать для этого сегмента код цвета, отличный
от цвета заполняемой границы.
Бейсик имеет также возможность заполнения областей экрана
заранее подготовленным изображением. Изображение может быть любо-
го размера, может быть выведено в любой позиции экрана и хранится
в массиве. Обычно, изображение создается с помощью всех доступных
средств, а затем запоминается в массиве оператором GET. Массив
может быть помещен в последовательный файл [5.4.3], из которого
программа может загрузить его и вывести изображение. Оператор GET
перечисляет координаты левого верхнего и правого нижнего угла
рамки, содержащей изображение, причем сначала идет номер столбца,
а затем номер строки для каждой пары координат. Затем должно
следовать имя массива, которое не заключается в кавычки. Напри-
мер, GET (80,40)-(120,60),ARRAY3 помещает все точки, находящиеся


внутри указанной области в массив с именем ARRAY3.
Одномерные массивы, как и все остальные, должны быть предвари-
тельно описаны оператором DIM. Массив может содержать элементы
любой точности. Для вычисления требуемых размеров массива надо
сначала определить сколько байтов потребуется для хранения изоб-
ражения. Это можно вычислить по формуле 4 + INT ((x*битовнаточку
+ 7)/8)* y. Здесь "битовнаточку" равно 1 для высокого разрешения
и 2 - для умеренного разрешения. Буквы x и y относятся к числу
точек вдоль горизонтальной и вертикальной сторон блока изображе-
ния. INT обозначает целую часть числа. Наконец, надо определить
сколько элементов массива требуется для хранения данного числа
байтов. Каждый элемент занимает 2 байта в целом массиве, но 4 -
для чисел с обычной точностью и 8 - для чисел с двойной точно-
стью.
Для получения изображения из массива и вывода его на экран
используйте оператор PUT. Этот оператор требует только координаты
левого верхнего угла области экрана, в которую будет выводиться
изображение. За координатами должно быть указано имя массива.
Например, PUT (40,30),ARRAY1 помещает изображение, левый верхний
угол которого будет находиться в столбце 40 и строке 30. Оператор
PUT может иметь еще и необязательный параметр, определяющий цвет,
которым будет выводиться изображение. Если этот параметр опущен,
то изображение будет выводиться точно в том виде, в котором оно
было записано оператором GET. Это эквивалентно записи PUT
(40,30),ARRAY1,PSET. В противном случае имеются некоторые другие
возможности. Если Вы вместо PSET укажете PRESET, то цвет 0 палет-
ты будет заменен на цвет 3 и наоборот, а цвет 1 палетты - на цвет
2 и наоборот.
Имеются еще три случая, использующие логические операции AND,
OR или XOR. Как и PRESET эти слова могут заменять PSET в приве-
денном примере. Обсуждение этих трех операций смотрите в приложе-
нии Б. Каждая операция включает сравнение битов существующей
точки на экране с битами точки накладываемого изображения. В
режиме высокого разрешения, когда на точку отводится только 1 бит
операция простая. Но в режиме умеренного разрешения, в котором на
каждую точку отводится 2 бита, могут происходить различные транс-
формации цветов.
AND устанавливает бит только если он был установлен и у точки
экрана и у точки изображения (взятой из массива). В режиме высо-
кого разрешения это означает, что точка изображения появится на
экране только если соответствующая точка экрана уже "включена".
Все остальные точки области будут выключены. В режиме умеренного
разрешения операция производится над обоими битами. Если для
точки экрана установка битов 01, а для соответствующей точки
изображения - 10, то оба бита будут сброшены и точка экрана полу-
чит код 00, что соответствует фоновому цвету.
OR устанавливает бит, если он был установлен либо для точки
экрана, либо для точки изображения. В черно-белом режиме OR нак-
ладывает изображение на существующее изображение на экране. В
цветном режиме для определения эффекта Вы опять должны прибегнуть
к вычислениям. Комбинация кодов палетты 1(01) и 2(10) дает 3(11),
также как и комбинация 0(00) и 3(11).


И, наконец, XOR устанавливает бит, если из двух сравниваемых
только один был установлен. Применение этой операции для чер-
но-белого экрана с массивом единиц дает негативное изображение (1
и 1 дает 0, а 1 и 0 - дает 1). В режиме умеренного разрешения эта
операция меняет все цвета. В результате получаем наложение двух
изображений. Но более важно, что при повторении этой операции
экран принимает в точности такой же вид, который он имел первона-
чально. При этом изображение стирается. Эта техника полезна для
мультипликации, когда над изображением дважды производится опера-
ция XOR в одной позиции, затем в соседней и т.д.

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

Имеется много подходов к написанию процедур заполнения графи-
ческих объектов. Ни один из них не является идеальным, поскольку
всегда имеется конфликт между скоростью работы процедуры и слож-
ностью фигур, которые она может обрабатывать. Любая процедура,
которая заполняет область точку за точкой будет медленной, неза-
висимо от того, насколько элегантно она реализована. Имейте вви-
ду, что почти каждая модифицируемая точка расположена в байте,
все точки которого будут изменяться в тот же самый цвет. Получе-
ние доступа к одному и тому же байту с использованием сложных
процедур требует существенно больше времени, чем установка целого
байта за один доступ к ячейке видеобуфера. Например, поточечная
очистка экрана требует на IBM PC нескольких секунд при использо-
вании функции BIOS, в то время как прямой доступ в память произ-
водит эту операцию мгновенно:

MOV AX,0B800H ;ES указывает на буфер экрана
MOV ES,AX ;
MOV CX,8192 ;заполняем все байты
MOV AX,0 ;в каждый байт пишем 0
MOV DI,0 ;DI поочередно указывает на все байты
REP STOSW ;повторяем запись 8192 раза

Многие процедуры заполняют по одной горизонтальной строке,
проверяя на цвет границы справа и слева. Поскольку строки состоят
из смежных байтов данных, то надо поочередно брать байты из ви-
деобуфера и проверять присутствует ли в них цвет границы. Если
цвет границы отсутствует, то можно заменить сразу весь байт на
цвет заполнения. В противном случае к данному байту применяется
поточечный подход.
Имеется очень быстрый способ определения присутствует ли гра-
ничный цвет в данном байте видеобуфера. Предположим, что процеду-
ра ищет цвет 1 палетты в режиме умеренного разрешения с четырьмя
цветами. Этому цвету соответствует код 01, поэтому сначала запол-
ним весь байт этим кодом: 01010101. Затем используем операцию NOT
для обращения каждого бита, после чего байт примет вид 10101010.
Проделаем операцию XOR со значением взятым из видеобуфера; в
результате получим байт, у которого оба бита, относящиеся к одной
точке равны 1 только для точек, имеющих граничный цвет. Затем
снова используем операцию NOT с тем, чтобы пара битов, относящих-
ся к точке граничного цвета имела код 00. После этого используем
операцию TEST для нахождения полей со значением 00. Если такое


поле найдено, то граничный цвет обнаружен и процедура переходит к
обычному поточечному анализу данного байта. Эту процедуру можно
еще убыстрить, если использовать словные данные.

MOV AL,ES:[BX] ;берем байт из видеобуфера
XOR AL,10101010B ;устанавливаем биты для цвета границы
NOT AL ;обращаем биты
TEST AL,11000000B ;проверяем биты 7-6
JZ FOUND_BOUND ;переход если граничный цвет
TEST AL,00110000B ;проверяем биты 5-4
JZ FOUND_BOUND ;переход если граничный цвет
TEST AL,00001100B ;проверяем биты 3-2
JZ FOUND_BOUND ;переход если граничный цвет
TEST AL,00000011B ;проверяем биты 1-0
JZ FOUND_BOUND ;переход если граничный цвет
MOV AL,FILL_COLOR ;граничного цвета нет, заполняем байт
MOV ES:[BX],AL ;возвращаем байт в видеобуфер
.
.
FOUND_BOUND:

Когда это возможно, постарайтесь, чтобы границы прямоугольных
областей Ваших картинок были выравнены на границу двух, четырех
или восьми точек, с тем чтобы прямое отображение в память имело
дело с целыми байтами. Другая возможность, хотя и не столь быст-
рая, состоит в создании определяемых пользователем псевдографи-
ческих символов [4.3.4] и выводе их на границе области заполне-
ния. Короче, в данной области Вы имеете все возможности проявить
сообразительность, а зачастую стоит подумать, а нужна ли Вам
столь сложная графика в данной задаче.



    4.4.7 Графический вывод с использованием символов псевдографики.



Когда Вы выводите изображение точка за точкой, то это отнимает
очень много времени, особенно когда создаются эффекты мультипли-
кации. Один из способов экономии времени состоит в сведении всех
или части выводимых форм к фигурам, которые могут быть построены
на матрице точек 8*8. Такие фигуры могут быть созданы, как опре-
деляемые пользователем символы, как показано в [4.3.4]. После
того, как эти символы определены они выводятся на экран очень
быстро и просто. Эти символы могут выводиться вперемешку с пото-
чечными графиками, как обычные буквы. Один из способов быстрого
заполнения фигуры состоит в последовательном выводе внутри фигуры
полностью закрашенного блока. Отметим, что эти символы всегда
располагаются в стандартных позициях курсора.

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

В этом примере рисуется фигура человека, занимающая 2 символа
в высоту и 2 символа в ширину. Как объяснено в [4.3.4] вектор
прерывания 1FH указывает на начало области данных, определяющих
символы. Четыре символа могут быть выведены обычными процедурами
DOS или BIOS. Легко создать другой набор символов, для вывода
фигуры с руками и ногами в другом месте экрана. Два набора симво-
лов могут поочередно меняться в соседних позициях курсора, созда-
вая иллюзию человека, идущего по экрану.

;---в сегменте данных
CHARACTER_DATA DB 00110000B ;левый верхний квадрант
DB 01100111B
DB 01100111B
DB 00110011B
DB 00011111B
DB 00001111B
DB 00001111B
DB 00000111B

DB 00000011B ;правый верхний квадрант
DB 10001100B
DB 10011000B
DB 00110000B
DB 11100000B
DB 11000000B
DB 11000000B
DB 10000000B

DB 00001111B ;левый нижний квадрант
DB 00011111B
DB 00011100B
DB 00011000B
DB 00011000B
DB 00110000B
DB 01100000B
DB 00010000B


DB 11000000B ;правый нижний квадрант
DB 11000000B
DB 11000000B
DB 11000000B
DB 01100000B
DB 01100000B
DB 00010000B
DB 00011110B
DB 00000000B

;---установка вектора прерывания
PUSH DS ;сохраняем DS
MOV DX,OFFSET CHAR_DATA ;смещение для данных в DX
MOV AX,SEG CHAR_DATA ;сегмент для данных в DS
MOV DS,AX ;
MOV AH,25H ;функция установки вектора
MOV AL,1FH ;номер вектора
INT 21H ;устанавливаем вектор
POP DS ;восстанавливаем DS

;---рисуем фигуру
;---позиционируем курсор на верхний ряд
MOV AH,2 ;функция установки курсора
MOV DH,13 ;строка 13
MOV DL,20 ;столбец 20
MOV BH,0 ;страница 0
INT 10H ;установка курсора
;---рисуем верхние два символа
MOV DL,128 ;берем символ 128
MOV AH,2 ;функция вывода/курсор вперед
INT 21H ;вывод символа
MOV DL,129 ;берем символ 129
INT 21H ;выводим его
;---позиционируем курсор на нижнюю строку
MOV DH,14 ;строка 14
MOV DL,20 ;столбец 20
MOV AH,2 ;функция установки курсора
INT 10H ;устанавливаем курсор
;---рисуем нижние два символа
MOV DL,130 ;берем символ 130
MOV AH,2 ;функция вывода/курсор вперед
INT 21H ;вывод символа
MOV DL,131 ;берем символ 131
INT 21H ;выводим его


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



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



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



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

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

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

100 '''данные для подпрограммы
110 DATA &H55, &H8B, &HEC, &H8B, &H76, &H12, &H8A
120 DATA &H24, &H8B, &H76, &H10, &H8A, &H04, &H8B
130 DATA &H76, &H0E, &H8A, &H2C, &H8B, &H76, &H0C
140 DATA &H8A, &H0C, &H8B, &H76, &H0A, &H8A, &H34
150 DATA &H8B, &H76, &H08, &H8A, &H14, &H8B, &H76
160 DATA &H06, &H8A, &H3C, &HCD, &H10, &H5D, &HCA
170 DATA &H0E, &H00
180 '''помещаем данные в сегмент &H2000
190 DEF SEG = &H2000 'помещаем данные начиная с &H2000
200 FOR N = 0 TO 43 '44 байта
210 READ Q 'читаем один байт
220 POKE N,Q 'помещаем его в память
230 NEXT 'следующий

300 '''в программе
310 GOSUB 500 'сдвигаем на строку
320 LOCATE 1,1: PRINT TEXT$(LINEPTR); 'выводим строку текста

500 '''подпрограмма сдвига
510 DEFINT A-Z 'используем целые переменные
520 TLR = 0 'левая верхняя строка
530 TLC = 0 'левый верхний столбец
540 BRR = 24 'нижняя правая строка
550 BRC = 79 'нижний правый столбец
560 NUMROWS = 1 'число строк сдвига
570 DIR = 7 'направление сдвига вниз
580 FILL = 7 'заполнение обычным атрибутом
590 DEF SEG = &H2000 'указываем на подпрограмму
600 SCROLL = 0 'начинаем с 1-го байта
610 CALL SCROLL(DIR,NUMROWS,TLR,TLC,BRR,BRC,FILL)
620 RETURN 'все сделано


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

Функция 6 прерывания 10H сдвигает любую часть экрана вверх, а
функция 7 - вниз. В обоих случаях AL содержит число строк сдвига,
а когда AL = 0, то весь экран чистится, а не сдвигается. CH:CL
содержат строку и столбец левого верхнего угла, а DH:DL - содер-
жат координаты правого нижнего угла. Появлящиеся из-за сдвига
строки чистые и они выводятся с кодом атрибутов из BH.

;---сдвиг вверх на одну строку
MOV AH,6 ;номер функции сдвига вверх
MOV AL,1 ;число строк сдвига
MOV CH,0 ;строка левого верхнего угла
MOV CL,0 ;столбец левого верхнего угла
MOV DH,24 ;строка правого нижнего угла
MOV DL,79 ;столбец правого нижнего угла
MOV BH,7 ;атрибуты очищаемой строки
INT 10H ;делаем сдвиг

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

Вертикальный сдвиг всего экрана это тривиальная задача, пос-
кольку правая граница одной строки в памяти продолжается левой
границей следующей строки. Сдвиг всего содержимого видеобуфера на
160 байт вверх по памяти (80 символов в строке * 2 байта на сим-
вол) приводит к сдвигу экрана вниз на одну строку. Если Вы пишете
свою собственную процедуру сдвига экрана, использующую прямое
отображение в память, то не забывайте об интерференции, которая
возникает на цветном дисплее и PCjr. Эта проблема обсуждается в
[4.3.1]. Обычное решение этой проблемы состоит в проверке статус-
ного байта, ожидая пока он разрешит запись в видеобуфер. Вам
придется поэкспериментировать, чтобы определить сколько данных Вы