ZX-Ревю 1993 №9-10 1992 г.

Применение ассемблера для создания быстроработающих программ - продолжение, начало см. с. 9-12, 48-61, 97-103, 183-188. Команды ATTRIBUTE, SCREEN$ и POINT.


Темы статьи: Программирование  

ПРИМЕНЕНИЕ АССЕМБЛЕРА ДЛЯ СОЗДАНИЯ БЫСТОРАБОТАЮЩИХ ПРОГРАММ

Перевод с английского Пашорина В.И.

Продолжение. Начало см. с. 9-12, 48-61, 97-103, 183-188

8. Команды ATTRIBUTE, SCREEN$ и POINT

Если Вы программировали игры на БЕЙСИКе, то вероятно сталкивались с тем, что Вам необходимо знать в определенной игровой ситуации текущее расположение заданного символа на экране. Это, например, нужно при проверке условия - достигла ли ракета цели, либо при выполнении посадки на Луну. В БЕЙСИКе для этого существуют три способа:

- использовать оператор ATTRIBUTE, который проверяет значение INK, PAPER, FLASH и BRIGHT в заданном знакоместе экрана и выдает число, соответствующее этим параметрам;

- использовать оператор SCREEN$, который определяет код символа в заданном знакоместе и выдает код этого символа, если он входит в диапазон 32...127. В противном случае считается, что ячейка пуста;

Примечание: процедуру в машинных кодах, которая может проверить не только символы ASCII, но и символы UDG-графики и символы блочной графики, т.е. из диапазона 32... 164 мы привели в первом томе, посвященном графике для "Спектрума" -"Элементарная графика" на с. 99 под названием SCANER. - ИНФОРКОМ.

- использование оператора POINT, который проверяет состояние одного пиксела экрана и выдает 1, если пиксел включен и 0, если он выключен.

Все эти три способа могут быть реализованы и в программах в машинных кодах с использованием специальных процедур ПЗУ.

8.1. ATTRIBUTE (строка, столбец).

Процедура ATTR, аналогичная по действию оператору ATTRIBUTE, находится в ПЗУ по адресу 9603. Перед ее вызовом необходимо записать координаты исследуемого знакоместа в регистровой паре BC (номер строки - в регистре B, а номер столбца - в регистре C). Результат проверки в виде числа 0...255 записывается на вершину стека калькулятора.

Определить атрибуты знакоместа, используя это число, можно по формуле:

ЧИСЛО=128*FLASH + 64*BRIGHT + 8*PAPER + INK значение

Это число можно переписать со стека калькулятора в регистр A, используя процедуру ПЗУ FP_TO_AA, находящуюся по адресу 11733, а затем сравнить его с заданным числом N с помощью команды CP N.

Пример реализации этого способа показан в программе 8.1. Программа проверяет каждое знакоместо экрана до тех пор, пока не найдет ячейку, атрибуты которой соответствуют PAPER 1, INK 7, FLASH 1, т.е. числу 143. После запуска этой программы на экране появляется ракета, медленно перемещающаяся по направлению к человечку. При совмещении ракеты с этим человечком происходит возврат в БЕЙСИК. Вы можете вместо команды возврата RET подключить процедуру, создающую звуковой эффект, сопровождающий попадание ракеты в человечка.

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

Листинг 8. 1.

АДРЕС МЕТКА МАШ.КОД АССЕМБЛЕР КОММЕНТАРИЙ

ORG 23760

23760 ED 5B 7B 5C LD DE,(23675) ;Адрес первого символа

графики пользователя.

23764

21

42

5D

LD HL,DATA 3

Конструкция символа UDG.

23767

01

08

00

LD BC,8

8 байтов в символе.

23770

ED

B0

LDIR

Установка символа UDG-"A"

23772

3E

02

LD A,2

Канал экрана - 2.

23774

CD

01

16

CALL 5633

Открываем канал печати на экран.

23777

CD

6B

0D

CALL 3435

Очистка экрана.

23780

3E

02

LD A,2

См. выше.

23782

CD

01

16

CALL 5633

23785

11

2E

5D

LD DE,DATA1

Данные для печати - DАТА1.

23788

01

10

00

LD BC,16

Символов - 16.

23791

CD

3C

20

CALL 8252

Вызов подпрограммы ПЗУ для печати символьной строки.

23794

FD

36

57

03

LD (IY+87),3

(IY+87) указывает на системную переменную PFLAG (23697). Установка в ней числа 3 означает включение режима INVERSE.

23798

AF

XOR A

Обнуление аккумулятора.

23799

32

40

5D

LD (COL),A

Обнуление столбца COL.

23802

L1

11

3E

5D

LD DE,DATA2

Данные для печати - DATA2.

23805

01

04

00

LD BC,4

Символов - 4.

23808

CD

3C

20

CALL 8252

Печать строки DATA2.

23811

DELAY

21

FF

FF

LD HL,65535

Организация цикла

23814

L2

2B

DEC HL

задержки для того, чтобы

23815

7C

LD A,H

изменения на экране не

23816

B5

OR L

происходили слишком

23817

20

FB

JR NZ,L2

быстро.

23819

11

3E

5D

LD DE,DATA2

Данные для печати - DATA2.

23822

01

04

00

LD BC,4

Символов - 4.

23825

CD

3C

20

CALL 8252

Печать строки DATA2.

23828

3A

40

5D

LD A,(COL)

Номер столбца позиции печати

23831

3C

INC A

Переход к соседней позиции.

23832

32

40

5D

LD (COL),A

Запомнили новую позицию.

23835

ED

4B

3F

5D

LD BC,(LINE)

Координаты позиции печати.

23839

CD

83

25

CALL 9603

Вызов процедуры ПЗУ для опре деления атрибутов в текущей координате.

23842

CD

D5

2D

CALL 11733

Перенос результата со стека калькулятора в регистр A.

23845

FE

8F

CP 143

Проверка на PAPER 1: INK 7: FLASH 1.

23847

20

D1

JR NZ,L1

Возврат, если нужное знакоместо еще не найдено.

23849

FD

36

57

00

LD (IY+87),0

Выключение режима INVERSE.

23853

C9

RET

Возврат в БЕЙСИК.

23854

DATA1

DEFB

22

0

20

17

Эти данные эквивалентны:

1

16

7

18

...AT 0,20; PAPER 1; INK 7;

1

144

18

0

FLASH 1; "A"; PAPER 0; INK 7

17

7

16

0

FLASH 0. Здесь "А" - это сим вол UDG; размещенный на клавише A, т.е. CHR$(144).

23870

DATA2

DEFB

22

Эти данные эквивалентны:

23871

LINE

DEFB

0

...AT 0,COL; CHR$(62).

23872

COL

DEFB

0

Символ 62 - это ">", он и

23873

DEFB

62

изображает "ракету".

23874

DATA3

DEFB

24

153

126

153

Это данные для символа UDG,

24

36

36

102

изображающего человечка.

8.2 SCREEN$

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

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

Коды калькулятора при этом оперируют не с самими символами, а с их параметрами, записанными в пятибайтной форме. Для того, чтобы передать параметры символа на стек, необходимо записать в регистровую пару ВС размер символа в байтах, а в регистровую пару DE - начальный адрес участка памяти, где хранится вся информация о символе. Для стандартных символов в регистр A записывается 0.

Для передачи этих параметров на стек используется процедура, находящаяся в ПЗУ по адресу 10929. Процедура же по адресу 11249 выполняет обратную функцию - передает параметры символа со стека в соответствующие регистры A, B, C, D, Е. При этом размер символа будет записан в регистровую пару ВС, а начальный адрес участка памяти с информацией о символе - в регистровую пару DE.

Программа 8.2 показывает, как можно использовать эти процедуры. После выполнения программы, на экране появятся два символа @, соответственно в позициях 0,20 и 0,21. Вместо вызова процедуры PRINT STRING (адрес 6252), можно использовать команду LD A,(DE) для проверки значения символа в позиции 0,20, а затем выполнить необходимые действия.

Листинг 8.2.

C9

RET

23798

При использовании БЕЙСИК-оператора SCREEN$ имеет место одно ограничение. Код распознаваемого символа на экране должен быть в диапазоне от 32 до 127. В противном случае считается, что это пустой символ. Такое ограничение существенно для игровых программ, где используются UDG, распознать которые в данном случае не удается. Для программ в машинных кодах такой проблемы не существует, поскольку UDG можно включить в стандартный символьный набор. Постоянно этот набор хранится в ПЗУ, начиная

АДРЕС

МЕТКА

.КОД

АССЕМБЛЕР ORG 23750

КОММЕНТАРИЙ

23760

3E

02

LD A,2

Канал экрана - 2.

23762

CD

01

16

CALL 5633

Открываем канал печати на экран.

23765

CD

6B

0D

CALL 3435

Очистка экрана.

23768

3E

02

LD A,2

Канал экрана - 2.

23770

CD

01

16

CALL 5633

Открываем канал печати на экран.

23773

3E

16

LD A,22

23775

D7

RST 16

23776

3E

0

LD A,0

Аналог ...AT 0,20;"@"

23778

D7

RST 16

23779

3E

14

LD A,20

23781

D7

RST 16

23782

3E

40

LD A,64

23734

D7

RST 16

23785

06

14

LD B,20

Номер экранного столбца.

23787

0E

00

LD C,0

Номер строки экрана.

23789

CD

38

25

CALL 9528

Вызов процедуры ПЗУ для определения того, что находится в данном знакоместе.

23792

CD

F1

2B

CALL 11249

Передача параметров символа со стека калькулятора в регистры процессора.

23795

CD

3C

20

CALL 8252

Печать той символьной стро-

ки, на местоположение которой указывает пара DE, а длина которой находится в ВС. В нашем случае - это символ "@".

с адреса 15360. Однако начальный адрес этого набора можно менять, меняя значение системной переменной CHARS (23606/7). Она указывает на 256 байтов ниже, чем начало символьного набора. Если переписать символьный набор из ПЗУ в ОЗУ таким образом, чтобы в этот набор вышел участок с информацией об UDG и чтобы UDG "А" соответствовал код 32, UDG "В" - код 33 и т.д., то можно вызывать процедуру SCREEN$ для идентификации UDG на экране.

Программа 8.3 работает точно так же, как и программа 8.1, но эта программа способна распознавать на экране символ, код которого равен 144. Выполнив копирование стандартного символьного набора в ОЗУ и переписав значение символьной переменной CHARS можно совсем отказаться от UDG. Теперь можно часть стандартных символов (например, строчные буквы и некоторые знаки пунктуации) заменить на символы, форму которых можем задать сами (это будет около 50 символов). Процедура SCREEN$ будет легко распознавать на экране любой символ, если он входит в символьный набор. И еще одно важное замечание. Необходимо всегда иметь свободный участок памяти, используемый как рабочий для стека. Если такого участка нет или он есть, но периодически не очищается, то при выполнении программы может появиться сообщение о переполнении памяти. Поэтому перед каждым вызовом процедуры SCREEN$ необходимо очищать специально зарезервированный рабочий участок.

Листинг 8.3.

МЕТКА МАШ.КОД

КОММЕНТАРИЙ

АДРЕС 23760

АССЕМБЛЕР

СМ. ЛИСТИНГ 8.1

ORG 23760

LD HL,(23675) DEC H

2A 7B 5C 25

23840

22 36 5C

23843 23846

23849

23850 23852

23855

23858

CD 38 25 CD F1 2B

1A

FE 20

21 00 3C

22 36 5C

LD (23606),HL

CALL 9528 CALL 11249

LD A,(DE)

CP 32

LD HL,15360 LD (23606),HL

23833 23836 23839

Адрес первого символа UDG. Отступили на 256 байтов. Мы помним, что CHARS указывает на 256 байтов ниже, чем начало шрифта. Переустановили CHARS так, она теперь указывает на область UDG.

Вызов процедуры SCREEN$. Передача параметров символа со стека в регистры. Проверка номера символа в текущем знакоместе. Проверка "не пробел ли это?" Расположение стандартного шрифта минус 256 б. Восстановили стандартное значение CHARS.

Далее, как в программе 8. 1

Процедура очистки рабочего участка имеется в ПЗУ по адресу 5823. Вызов этой процедуры в программе 8.3 можно производить после команды LD A,(DE), однако предварительно необходимо сохранить в памяти последнее значение регистра А.

8.3 POINT

Оператор POINT x,y в БЕЙСИК-программах выдает 1, если пиксел экрана с координатами x,y включен и выдает 0, если он выключен. Процедура ПЗУ, соответствующая этому оператору (адрес 8910), может быть вызвана, если предварительно записать в регистр B у-координату, а в регистр C, соответственно x координату пиксела. При этом результат зашлется на стек, а т.к. он равен 0 или 1, то мы можем переписать его в регистр A и сравнить с заданным значением. В программе 8.4 показан способ проверки пиксела верхнего левого угла (координаты 0,175).

Если в начале в символьную ячейку с координатами 0,0 занести черный квадрат, то результат работы процедуры будет равен 1, т.к. пиксел с координатами 0,175 входит в этот квадрат.

Листинг 8.4.

АДРЕС

МЕТКА МАШ

и.КОД

АССЕМБЛЕР КОММЕНТАРИЙ

ORG 23760

23760

3E

02

LD A,2

Канал экрана - 2

23752

CD

01

16

CALL 5633

Открываем канал экран.

печати на

23765

CD

6B

0D

CALL 3435

Очистка экрана.

23768

3E

02

LD A,2

Канал экрана - 2

23770

CD

01

16

CALL 5633

Открываем канал экран.

печати на

23773

3E

8F

LD A,143

"Черный квадрат"

23775

D7

RST 16

Печать квадрата.

23776

0E

00

LD C,0

Координата x.

23778

06

AF

LD B,175

Координата y.

23780

CD

CE

22

CALL 8910

Вызов процедуры из ПЗУ.

POINT

23783

CD

D5

2D

CALL 11733

Перенос результата со стека калькулятора в регистры.

23786

FE

01

CP 1

Проверка включен или нет.

пиксел

23788

C8

RET Z

Выход, если да.

9. ПРИНТЕР

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

9.1. COPY

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

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

Листинг 9.1

ORG 23760

23760

21

00

40

LD HL,16384

23763

06

C0

LD B,192

23765

F3

DI

23756

CD

B2

0E

CALL 3762

23769

C9

RET

Как Вы заметили, в этой программе перед вызовом процедуры, находящейся в ПЗУ по адресу 3762, необходимо в регистровую пару HL записать начальный адрес экранной области ОЗУ (т.к. нам необходима копия, начиная с первой строки, то этот адрес 16384), а в регистр B - число копируемых строк, умноженное на 8.

9.2 LPRINT

Эта команда имеет сходство с командой PRINT. Различие состоит в том, что не работают по этой команде управляющие коды и, конечно, используется другой канал для вывода информации на принтер, который необходимо открыть в программе в машинных кодах, прежде чем использовать команду RST 16. Например, чтобы вывести на принтер литеру "A", т.е. реализовать в машинных кодах LPRINT "A", необходимо первоначально открыть канал 3, затем записать в регистр A код литеры "A", ну а затем использовать команду RST 16.

Программа 9.2 демонстрирует этот способ для вывода на принтер символьной строки.

Листинг 9.2

ORG 23760

23760

3E 03

LD A,3

23762

CD 01

16

CALL 5633

23765

11 DF

5C

LD DE,DATA

23768

01 09

00

LD BC,9

23771

CD 3C

20

CALL 8252

23774

C9

RET

23775

DATA DEFM

PROGRAM

2

Для выполнения табуляции выводимой на принтер информации, необходимо предварительно в системную переменную PRCC (23680) через POKE записать соответствующее число.

9.3 LLIST

Это третья БЕЙСИК-команда для работы с принтером. Реализовать ее в машинных кодах довольно просто. Достаточно только записать CALL 6133 и будет выполняться листинг строк BASIC-программы на принтере.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Обратная связь - контакты редакции.
От авторов - по новой моде, свалим все на падение общего интеpеса к спектpуму...
Заключение - Ну вот и закончена работа над восьмым проектом журнала FAULTLESS.
От авторов - O истории создания журнала.
Tutorials - графика: "Конверсии - такой ли это отстой? Конверсии - разоблачение титанов? Конверсии - как сделать их круто? Конверсии - зачем?".

В этот день...   25 апреля