ИСПОЛЬЗОВАНИЕ ПОДПРОГРАММ ПЗУ
Использование подпрограмм ПЗУ ZX Spectrum может значительно
облегчить программирование на ассемблере. Например, почти полностью
отпадает необходимость в самостоятельном написании процедур ввода/вы-
вода (прибегать к этому приходится только в случаях, когда не удовлетворяет
скорость или гибкость стандартных подпрограмм).
Ниже описаны подпрограммы ПЗУ, наиболее часто используемые на
практике. Перед вызовом большинства из них необходимо настроить регистро-
вую пару HL' на адрес 10082 (#2762), а в индексный регистр IY записать адрес
системной переменной ERR_NR: 23610 (#5СЗА).*
Ввод/вывод
Установка текущего потока: CALL 5633 (#1601)
Подпрограмма устанавливает текущим поток, номер которого указан
в регистре А (см. «Архитектура ZX Spectrum»). Операционная система
ZX Spectrum предоставляет пользователю 4 потока:
поток 0 и 1 — ввод с клавиатуры, вывод на служебный экран;
поток 2 — вывод на основной экран;
поток 3 - вывод на принтер;
Потоки с номерами от 4 до 15 открываются при подключении различ-
ных внешних устройств (дисковых накопителей, контроллеров сети и т. п.).
Вывод символа в поток: RST 16 (#0010)
Подпрограмма выводит в текущий поток символ, код которого занесен
в регистр А. Процедура может быть также использована для смены парамет-
ров вывода на экран (аналогично выполнению операторов INK, PAPER, TAB,
AT и др.). Для этого необходимо вывести в поток соответствующий управля-
ющий код (см. «Контрольные коды ZX Spectrum») и сразу за ним — требу-
емый аргумент (номер цвета, позицию печати и т. д.).
Контроль нажатия клавиши BREAK: CALL 8020 (#1F54)
Процедура сбрасывает флаг переноса CY, если в момент ее выполне-
ния нажимается клавиша Break (Caps Shift/Space), в противном случае флаг
устанавливается.
*) Регистр IY должен настраиваться на ERR_NR также, когда в программе
используется режим прерываний 1 и прерывания разрешены.
Очистка всего экрана: CALL 3435 (#0Р6В)
Подпрограмма очищает основной и служебный экраны и, в соответ-
ствии с системными переменными ATTR_P (23693) и BORDCR (23624),
устанавливает атрибуты.
После выполнения этой и следующей процедуры текущим устанав-
ливается поток номер 1.
Очистка служебного экрана: CALL 3438 (#0P6El
Подпрограмма очищает служебный экран, атрибуты для которого
устанавливаются в соответствии с системной переменной BORDCR (23624).
Скроллинг экрана: CALL 3582 (#0PFE)
Процедура перемещает содержимое основного экрана вверх на одну
символьную строку.
Изображение точки на экране: CALL 8933 (#22Е5)
Координаты точки задаются содержимым регистровой пары ВС. В
регистр В заносится значение координаты Y (0...175), в С — координаты X
(0...255). Атрибуты знакоместа, в которое попадает точка, задаются систем-
ной переменной ATTR P (23693).
Вывод числа в поток в десятичной форме
Для вывода в текущий поток целых чисел последовательно вызовите
две подпрограммы:
CALL 11563 (#2D2B)
CALL 11747 (#2DE3)
Первая подпрограмма помещает число в стек калькулятора, вторая —
выводит его в текущий поток. Число, предназначенное для вывода, должно
находиться в регистровой паре ВС. Незначащие нули игнорируются.
Ввод символа с клавиатуры
Для опроса клавиатуры чаще всего используют системные перемен-
ные LAST_K (23560) и FLAGS (23611). При установленном режиме преры-
ваний 1 и разрешенных прерываниях, переменная LAST_K содержит код
последней нажатой клавиши, а 5-й бит переменной FLAGS устанавливается
при нажатии любой клавиши. Таким образом, ожидание нажатия произволь-
ной клавиши можно организовать с помощью следующей подпрограммы:
KEY El ; разрешение прерываний
RES 5,(IY+1) ; сброс 5-го бита системной
; переменной FLAGS
LOOP BIT 5,(IY+1) ; клавиша нажата?
JR ZfLOOP ; переход на LOOP, если не нажата
LD A,(IY—50) ; чтение кода нажатой клавиши
; из системной переменной LAST.K
RET ; возврат из подпрограммы
Приведенная подпрограмма ждет нажатия любой клавиши и возвра-
щает ее код в аккумуляторе.
Ожидание ввода: CALL 5598 (#<5РЕ)
Подпрограмма осуществляет ввод из текущего потока. По окончании
ввода одного байта процедура проверяет флаг переноса CY. Если он уста-
новлен, происходит выход из подпрограммы, в противном случае проверя-
ется флаг нуля Z. Если Z установлен, процедура ввода повторяется. При
условии Z=0 управление передается операционной системе, которая выдает
сообщение 8 End of file.
Если текущим установлен поток 1 (обычно — канал "К"), подпрограм-
ма осуществляет опрос клавиатуры, и после нажатия клавиши помещает ее
код в аккумулятор. Однако существует сложность: если бит 3 системной
переменной TVFLAG (23612) установлен, то параллельно вводу символов с
клавиатуры на служебном экране будет отображаться содержимое буфера
редактора.
Звуковой сигнал: CALL 949 (#03BS)
Перед вызовом подпрограммы в регистровые пары HL и DE помеща-
ются числа (0...65535), пропорциональные, соответственно, частоте звуково-
го сигнала и его длительности. При этом нужно учитывать линейную
зависимость между частотой и длительностью — чем выше тон, тем короче
звук. Необходимые значения рассчитываются следующим образом:
HL = (437500/f)—30.125 DE = f * t
где f — частота в Гц, t — время в сек.
Например, для воспроизведения в течении 1 секунды ноты «ДО»
первой октавы (частота примерно 261 Гц) в HL необходимо поместить число
1646, а в DE — число 261.
Печать сообщений: CALL 3082 (#0С0А}
Для выполнения этой подпрограммы в регистровую пару DE загру-
жается начальный адрес таблицы сообщений, в регистр А — номер сообще-
ния в ней. Первое сообщение имеет номер 0. Первым байтом в таблице
должен стоять код 128 (#80). Для задания конца сообщения старший бит его
последнего байта должен быть установлен в единицу.
Пример:
LD А,0 ; печать первого
CALL PRIMES ; сообщения в таблице
PR_MES LD DE,MES_TAB
CALL 3082 ; вывод сообщения на основной экран
RET
MES_TAB DEFB #80 ; начало таблицы
DEFM "ENTR" ; начало сообщения "ENTRY"
DEFB "Y"@#80 ; конец сообщения
DEFM "ENTRY " ; второе сообщение "ENTRY 2"
DEFB "2"@#80
Изображение окружности: CALL 900S (#232P|
Параметры окружности предварительно помещаются в стек калькуля-
тора в следующем порядке: X, Y (координаты центра окружности) и Z (радиус).
Сделать это можно с помощью специальной подпрограммы, размещенной по
адресу 11560 (#2D28), которая заносит в стек калькулятора содержимое
аккумулятора.
Следует учитывать, что процедура изображения окружности изменяет
значение системной переменной COORDS (23677/78).
В качестве примера приведем следующую программу:
LD HL, (23677) ; запоминаем текущие
PUSH HL ; координаты (COORDS)
LD А,Х ; координата X (от 0 до 255)
CALL #2D28 ; запись аккумулятора в стек
LD А,У ; координата Y (от 0 до 175)
CALL #2D28 ; запись аккумулятора в стек
LD АД ; Z - радиус
CALL #2D28 ; запись аккумулятора в стек
CALL #232D ; изображение окружности
POP HL ; восстанавливаем
LD (23677)tHL ; координаты (COORDS)
Изображение линии: CALL 9399 С#24В7), CALL 9401 (#24ВА)
Для процедуры изображения линии, расположенной с адреса 9399
(#24В7), параметры передаются так же, как и для процедуры изображения
окружности — через стек калькулятора. На практике удобнее пользоваться
подпрограммой по адресу 9402 (#24ВА), параметрами для которой являются
значения регистровой пары ВС и системной переменной COORDS
(23677/78). В регистры В и С записываются соответственно величины
смещений относительно текущих координат Y (0...175) и X (0...255), с одер-
жапфихся в системной переменной COORDS.
Знаки смещений по Y и X задаются в регистрах D и Е соответственно
записью в них следующих значений: +1 (#01) — положительное, -1 (#FF)
— отрицательное.
С использованием CALL 9402 (#24ВА) можно легко реализовать ассем-
блерный эквивалент команды Бейсика DRAW. Например, результат выпол-
нения следующей программы аналогичен выполнению команды DRAW 0,20:
LD BCf#1400 ; 20,0
LD DE,#0101 ; знаки смещений
CALL 9402
Для изображения отрезка с координатами начала (127,87) и смеще-
нием конца (-20,40) перед вызовом подпрограммы необходимо настроить
системную переменную COORDS:
LD L.127 ; стартовые координаты Х=127
LD Н.87 ; и Y=87
LD (23677),HL ; записываются в COORDS
LD' С,20 ; смещение по X
LD Е,—1 ; задается равным —20
LD В,40 ; смещение по Y -
LD D,1 ; равным +40
CALL 9402 ; изображение отрезка
Очистка части экрана: CALL 3652 (#0Е44)
Подпрограмма служит для очистки нижней части экрана. Количество
строк, которые необходимо очистить, указывается в регистре В.
Скроллинг части экрана: CALL 3584 (#0Е00)
Подпрограмма перемещает вверх на одну символьную строку ниж-
нюю часть экрана. В регистр В записывается число, на единицу меньшее
количества строк, которые необходимо переместить.
Загрузка к запись файлов на магнитофон
Как правило, файл, записанный на магнитной ленте, состоит из двух
блоков, первый из которых называется заголовком и содержит информацию
о файле (тип, длина и т. п.), второй — собственно данные. Подпрограмма
ПЗУ загружает и обрабатывает заголовок и на основе полученной информа-
ции загружает данные.
Длина заголовка составляет 17 байт:
байт 0 — тип файла:
0 — бейсик-программа;
1 — числовой массив;
2 — символьный массив ;
3 — двоичный (кодовый) файл.
байты 1...10 — имя файла;
байты 11,12 —длина блока данных;
байты 13, 14 — для типа 0: номер строки автозапуска;
— для типа 3: начальный адрес загрузки;
байт 14 — для типов 1 и 2 — имя и тип массива в
следующей форме:
'' биты 0...4 — имя массива (A...Z);
бит 5 — 0, если массив числовой;
бит 3 — 1, если массив символьный;
бит 7 — всегда установлен;
байты 15, 16 — длина бейсик-программы.
Загрузка файла без заголовка: CALL 1366 (#0556)
Процедура предназначена для загрузки с ленты блока кодов и про-
верки записи. Она используется следующим образом:
LD 1Х,<начальный адрес>
LD ОЕ,<длина блока>
LD А,<флаг>
SCF
CALL 1366 ; вызов процедуры загрузки
RET
В индексный регистр IX загружается адрес ячейки памяти, начиная с
которой будет производиться проверка или загрузка блока кодов. В регистро-
вую пару DE помещается длина загружаемого файла в байтах, а в регистр А
— так называемый флаговый байт. Он равен нулю, если ожидается заголовок,
и 255 — если тело файла (возможны и другие значения флагового байта).
Загрузка кодового блока будет производиться, если перед выполнением про-
цедуры был установлен флэт CY, проверка блока — если CY сброшен.
По возврату из процедуры, если загрузка (проверка) произведена
успешно, флаг CY устанавливается, в противном случае — сбрасывается.
Прервать загрузку (проверку) блока можно, нажав клавишу Break, при этом
на экран выдается сообщение BREAK — CONT repeats. Для запрещения преры-
вания загрузки нужно несколько изменить программу вызова процедуры:
LD 2Х,<начальный адрес>
LD DE,< длина блока>
LD А,<флаг>
SCF
INC D
EX AF.AF'
DEC D
DI
LD А,15 ; номер начального цвета бордюра + 8
OUT (254).А
CALL 1378
LD А,7 ; восстановление цвета бордюра
OUT (254),А
EI
RET
Если при возврате из этой подпрограммы флаг переноса равен нулю,
то это означает, что либо загрузка (проверка) произведена с ошибкой, либо
во время загрузки была нажата клавиша Break. Более точно установить
причину ошибочного завершения операции можно, опросив клавиатуру.
Запись файла без заголовка: CALL 1218 (#04С2)
Подпрограмма служит для записи данных на магнитофон и вызыва-
ется аналогично процедуре загрузки:
LD 1Х,<начальный адрес>
LD ОЕ,<дпина блока в байтах>
LD А,<флаг>
CALL 1218
RET
При нажатии клавиши Break выполнение процедуры будет прервано
и выдано сообщение BREAK — CONT repeats, чего можно избежать, запустив
процедуру не с адреса 1218, а с 122$2.