Optron
#41
19 ноября 2000 |
|
Ликбез - Ассемблеp - взгляд издалека: работа с графикой.
Ассемблеp - взгляд издалека. Продолжение. Начало в || 20, 21, 24, 25, 28-30, 32, 33, 35, 36 {} Инфарх, 2000 Вот мы и снова встретились! После рас- сказа о распределении памяти Speccy вы на- верняка полны желания использовать полу- ченную информацию по назначению, написав какую-нибудь программу; в этом я вам пос- тараюсь помочь. Не секрет, что каждый программист желает видеть, как работает его программа. Для этого он должен организовать в своей прог- рамме интерфейс общения с пользователем. Начаать надо со средств вывода, а именно - с экрана. Итак... Общая организация экрана Не исключено, что по Бейсику вы уже зна- комы с делением экрана на строки, знако- места и т.д. Но если вы всё-таки этого не знаете, то прочитайте этот раздел внима- тельно. Минимальной единицей экрана является од- на его точка - пиксел (от англ. "picture element", pixel - элемент изображения). Собранные в матрицу 8х8, точки образуют знакоместо. В нём размещается стандартный символ. Для знакоместа также определяется атрибут - цвет пиксела установленного и цвет пиксела, сброшенного в знакоместе. Экран содержит 24 строки по 32 знакомес- та в каждой. Если необходимо указать коор- динаты определённого знакоместа, то отсчёт ведётся от верхнего левого угла экрана. Расположеное там знакоместо имеет коорди- наты 0, 0. Знакоместо справа от него имеет координаты 1, 0, а снизу - 0, 1. Знакомес- то в нижнем правом углу имеет кординаты 31, 23. Перейдём к графике. На более низком уровне экран делится на столбцы (верти- кальные) и линии (горизонтальные). Всего экран содержит 192x256 пиксел. Пиксел сле- ва вверху имеет координаты 0, 0, а справа внизу - 255, 191. Младшие три бита коорди- наты Х определяют, какой бит в байте адре- са соответствует данному пикселу. А теперь посмотрим, как всё это выводит- ся на экран. В Спектруме его экрану соответствует об- ласть памяти, начинающаяся с адреса #4000. В её начале определяется графика, а затем - атрибуты. Каждый байт в области графики определяет состояние восьми пикселов экра- на. Пиксел будет изображён на экране, если в байте будет установлен соответствующий бит. Например, возьмём байт %10011101. Пе- решлём его по адресу #4000 и посмотрим на экран. Видите, в самой верхней линии у ле- вого края экрана появились точки? Они име- ют вот такой вид: █ ░ ░ █ █ █ ░ █ ░ - нет точки █ - есть точка Легко понять соответствие битов и точек, сравнив пересланый в экран бит и получен- ное изображение: каждый байт в экранной области памяти соответствует 8-ми точкам и равен ширине знакоместа. Зная, что экран состоит из 32 х 24 = 768 знакомест, причём каждое знакоместо имеет по вертика- ли 8 линий (8 байт), нетрудно получить размер области графики в байтах: 32 х 24 х 8 = 6144 (#1800) байт Теперь - об атрибутах. Их область памяти расположена сразу за графической областью, начиная с адреса #5800. Т.к. атрибут зада- ётся для целого знакоместа (а знакомест у нас - 768) и каждый атрибут занимает один байт, то нетрудно вывестии и размер облас- ти атрибутов - 768 байт. Вот как этот байт определяет состояние экрана: - три младших бита (D2, D1, D0) задают цвет чернил (INK, установленныe пикселы); - биты D5, D4, D3 - цвет бумаги (PAPER, пикселы сброшенные); - бит D6 определяет яркость (BRIGHT); если он установлен, то информация на экра- не для данного знакоместа отображается с повышеной яркостью. Остался бит D7 - бит мерцания (FLASH). Если он включен, то через каждые 16/50 до- лей секунды ULA меняет местами цвет бумаги и чернил для данного знакоместа. Рассмотим байт атрибута в общей форме: Paper ┌────┐ ┌──┬──┬──┬──┬──┬──┬──┬──┐ │D7│D6│D5│D4│D3│D2│D1│D0│ └──┴──┴──┴──┴──┴──┴──┴──┘ │ │ └────┘ │ └Bright Ink └Flash Цвета для экрана Спектрума имеют следую- щее соответствие кодов: 0 чёрный 1 ███ синий 2 ███ красный 3 ███ малиновый 4 ███ зелёный 5 ███ циан 6 ███ жёлтый 7 ███ белый Организация экранной памяти Ознакомившись с экранной памятью Спек- трума, не подумайте, что она организована линейно! Её структура более сложная, в чём мы сейчас и убедимся. Наберите и запустите такую программу: LD HL,#4000 ; Очищаем экран LD DE,#4001 LD BC,#1800 LD (HL),L LDIR LD BC,#2FF ; И устанавливаем ; его атрибут LD (HL),7 ; ink=7, paper=0 LDIR LD HL,#4000 ; Начало экранной ; памяти LD DE,#1800 ; Размер ; графической ; области SCR LD (HL),#FF ; Пересылаем ; в экран INC HL ; Следующий байт ; экрана ; Задержка 1/10 секунды для наглядности LD B,5 PAUSE HALT DJNZ PAUSE ; Повторяем для всей области графики DEC DE LD A,D OR E JR NZ,SCR RET Назначение этой, весьма простой про- граммы - последовательное заполнение об- ласти памяти графики экрана значением #FF, что соответствует одной закрашеной линии знакоместа. Кстати, если вы испoльзуете ассембер XAS, запускайте эту программу, используя комбинацию клавиш CS+R, - и вы сможете после завершения работы программы лицезреть получившееся изображение столь- ко, сколько угодно. Лишь после нажатия "any key" (не путать с RESET) вы вернётесь в редактор. Теперь рассмотрим специфику работы све- женабранной программы более подробно. Итак, первые 32 байта экранной памяти соответствуют первой линии первой строки знакомест. Впрочем, вы это видели. Навер- ное, вы подумали, что далее следует вторая линия первой строки? А вот и нет! Далее следует первая линия второй строки! И так последовательно заполняются все 8 строк - от первой до восьмой. Можно предположить, что следующий байт будет соответствовать первой линии девятой строки... Но это опять-таки неверно. Оче- редь заполнения возвращается к первой строке, на этот раз - ко второй линии. И вот так, по линии из каждой строки знако- мест, заполняются все восемь строк. Как вы уже могли заметить, экран разде- ляется на трети и переход на следующую треть происходит только после заполнения предыдущей. Конечно, такая организация эк- рана создаёт определённые сложности для программиста, но при некоторой ловкости рук это легко решается. О технических под- робностях поговорим потом, а сейчас зай- мёмся областью атрибутов. Честно говоря, особо заниматься ею и не придётся. В отличие от графики, атрибуты организованы совершенно линейно. Сначала последовательно (слева направо) заполняет- ся нулевая строка, далее очередь переходит к первой, и так до конца экрана. Дабы про- иллюстрировать всё вышесказанное, обратим- ся опять-таки к программе. В предыдущем примере удалите последнюю команду (RET) и с этой позиции введите та- кие строки: LD DE,#300 ; Размер области ; атрибутов ATTR LD (HL),2 INC HL LD B,5 PAUSE1 HALT DJNZ PAUSE1 DEC DE LD A,D OR E JR NZ,ATTR RET Вот вам наглядная демонстрация всего вы- шесказанного! Как видите, работа с атрибу- тами весьма проста. А теперь отвлечёмся на некоторое время от освоения экрана и глянем повнимательнее на ту программу, которую вы только что набрали. Естественно, она не идеальна. Ведь это только пример, в котором нагляд- ность - важнее всего. А вот давайте попро- буем записать его так, чтобы он был как можно более компактным. Тем более, что все команды ассемблера вам уже известны. Итак... LD HL,#4000 PUSH HL LD DE,#4001 LD BC,#1800 PUSH BC LD (HL),L LDIR LD BC,#2FF LD (HL),7 LDIR POP BC POP HL LD E,#FF CALL FILL LD E,2 LD BC,#300 FILL LD (HL),E INC HL LD D,5 WAIT HALT DEC D JR NZ,WAIT DEC BC LD A,B OR C JR NZ,FILL RET Проанализировав на досуге эту програмку, вы наверняка поймёте её принцип работы. А мы вернёмся к экранным операциям. Узнав методику распределения экранной памяти, следует научиться и тому, как на- ходить в экране адрес необходимого байта (пока только байта, до пикселей мы добе- рёмся позже). Вычислить адрес первого байта первого знакоместа в строке, номер которой переда- ётся через регистр А, вам позволит такая программа: LD H,A ; В "А" находится ; номер строки RRCA RRCA RRCA AND #E0 LD L,A LD A,H AND #18 OR #40 LD H,A ; На выходе в HL адрес первого байта ; заданной строки Вот и вся сложность. Не забудьте только, что если вы хотите использовать процедуру как подпрограмму, то в конце необходимо добавить команду RET. Если вы проследите за выполнением процедуры пошагово, причём, обращая внимание на содержимое аккумулято- ра в двоичной форме, то без труда поймёте принцип работы. А теперь попробуем несколько изменить пример, чтобы получить возможность расчёта адреса с учётом ещё и столбца. Если в пре- дыдущем примере мы в качестве аргумента использовали номер строки в регистре А, то здесь надо будет использовать ещё и номер столбца в регистре L. Смотрите: LD H,A RRCA RRCA RRCA AND #E0 ADD A,L ; Добавленная строка LD L,A LD A,H AND #18 OR #40 LD H,A Как видите, путём добавления всего одной команды пример был доработан до более сложного. Попробуйте теперь сделать так, чтобы расчитывался адрес любой линии экра- на (0..191). Наверняка это окажется полез- ным упражнением. Ну, поехали дальше... Очень редко бывает необходимо что-либо делать в пределах одной линии пикселей. Обычно изображение занимает по вертикали гораздо больше места. И для того, чтобы перейти на следующую линию, вовсе не обя- зательно заново высчитывать её адрес. На- пример, если вам нужна следующая линия в пределах знакоместа (при печати символа), достаточно провести инкремент старшего байта адреса. На тот случай, если переход должен быть осуществлён без привязки к знакоместу, а просто на следующую строку в пределах эк- рана, предлагаю вашему вниманию небольшую подпрограмму: DOWN_HL INC H LD A,H AND 7 RET NZ LD A,L ADD A,#20 LD L,A RET C LD A,H SUB 8 LD H,A RET На входе сия процедура получает адрес байта в экране, а на выходе выдаёт адрес байта, расположенного под ним. Заметьте, это вовсе не должен быть первый байт ли- нии. Если вы предпочитаете использовать не регистр HL, а нечто иное, то просто заме- ните соответствующие регистры в процедуре. А заодно, раз уж зашёл разговор на эту те- му, посмотрите и на процедуру, выполняющую действие прямо противоположное - рассчиты- вает адрес строки предыдущей: UP_HL DEC H LD A,H AND 7 CP 7 RET NZ LD A,L SUB #20 LD L,A RET C LD A,H ADD A,8 LD H,A RET Иногда бывает нужно пересчитать адрес в экране в адрес, соответствующий данному знакоместу в области атрибутов. Сделать это можно так: SCR_ATR LD A,H RRCA RRCA RRCA AND 3 OR #58 LD H,A RET Ну, на этот раз пока хватит. До следующего урока попробуйте позани- маться написанием программ для рисования графических примитивов - для практики это весьма полезно. Удачи! Продлжение следует... ──══════════──
Другие статьи номера:
4 килобайта - номер посвящен Сhaos Constructions'2000. |
Рубрика X - рассуждения о Chaos Constructions'000 и обзор дем. |
ZX-обоз - Партийная жизнь (окончание). |
Ликбез - Ассемблеp - взгляд издалека: работа с графикой. |
Стихи - "Выбор". |
Реклама - обьявления для Львова. |
https://govoritel.ru очень полезная вещь громкоговорители на пояс. |
Похожие статьи:
В этот день... 21 ноября