╔───────────────────────────────────────╗
│ ОБМЕН ОПЫТОМ │
│ ───────────────────────────────────── │
│тем, кто много знает,читать запрещается│
╚───────────────────────────────────────╝
(C) Заводчиков Константин
(C) Музыка NEVER
Сегодня мы осветим некоторые вопро-
сы по программированнию на ассемблере,
часто возникающие у начинающих програм-
мистов. Возможно,эта статья будет повто-
рять своим содержанием некоторые печатные
или электронные издания, и кто-то, воз-
можно, упрекнет наш журнал в этом. Хотя
стоит вспомнить, что не каждый имеет дома
подшивку ZX-РЕВЮ хотя-бы за какой-нибудь
год. Так что, кто силен в кодах и знает
множество приемов, может смело покинуть
эту статью. А с теми, кто остался,мы пос-
тaраемся что-нибудь выяснить для всеобще-
го блага.
Для начала затронем несколько про-
цедур, находящихся в ПЗУ :
CLEAR xxxxx - программа очистки об-
ласти переменных BASICа, экрана, уста-
новки стека и переменной RAMTOP в новые
значения. Для эмуляции этой команды в ко-
дах регистровая пара BC должна содержать
адрес установки стека. В ассемблере это
будет выглядеть так :
LD BC,xxxxx
CALL 7855 (#1EAF) .
Если в BC содержится 0 тогда произойдет
только очистка переменных и экранной об-
ласти.
CLS - программа очистки экрана. Ат-
рибуты устанавливаются соответственно
значению переменной ATTR-P (23693). При
обращении к этой программе в регистры за-
носить данные не надо. Она вызывается :
CALL 3435 (#0D6B) .
CLEAR-LINES - подпрограмма очистки
нижних N строк экрана. В регистр B зано-
сится количество очищаемых строк :
LD B,N
CALL 3652 (#0E44) .
PAUSE - полный аналог команды
BASICа. В регистре BC содержится количес-
тво задержек, если оно равно нулю то воз-
врат из процедуры будет совершен только
при нажатой клавише :
LD BC,пауза
CALL 7997 (#1F3D) .
Вызывая эту программу, не забудте разре-
шить прерывания и включить первый режим
прерываний (IM1), иначе из данной проце-
дуры вы сможете вернуться только по кноп-
ке RESET.
BREAK_KEY - процедура, проверяющая
нажатие клавиши BREAK (не следует путать
с клавишей SPACE). Вызывается она:
CALL 8020 (#1F54) .
После возврата из процедуры, сброшенный
флаг переноса указывает на то, что была
нажата клавиша BREAK.
PLOT - эта поцедура зажигает (или
гасит,в зависимости от системных перемен-
ных),на экране точку. В регисте C - коор-
дината X, регистре B - Y:
LD B,Y
LD C,X
CALL 8933 (#22E5) .
DRAW - программа изображения на эк-
ране прямой линии. Здесь, также как и
в процедуре PLOT, в регистрах B и C нахо-
дятся координаты Y и X, но не фиксирован-
ные - координаты смещения. В регистре D
знак смещения по координате X, в E знак
смещения по Y. То есть, если в знаке сме-
щения какой-нибудь координаты находится :
255 (#FF), то соответствующее смещение
будет воспринято со знаком "минус"; 1- то
смещение будет со знаком "плюс"; 0 - сме-
щение по данной координате просто игнори-
руется.
LD B,Y
LD C,X
LD D,знак для Y
LD E,знак для X
CALL 9402 (#24BA) .
CHAN-OPEN - подпрограмма служит для
открытия канала. Часто начинающие прог-
раммисты забывают открывать канал "S" при
использовании процедуры печати из ПЗУ,
после чего с недоумением смотрят на стра-
но появившееся их сообщение, да еще и не
там, где надо, либо, что более интересно,
выскакивает "OUT OF SCREEN". Для правиль-
ного вызова этой процедуры, в регистре A
должно находится число в диапозоне от 253
(#FD) до 3. Эти числа являются потоками,
ведущими к каналам : клавиатуры "K", эк-
рана "S", принтера "P" и рабочей области
"R". Перед вами значения потоков, ведущие
к стандартным каналам:
253 (#FD) - открывает канал "K"
254 (#FE) - открывает канал "S"
255 (#FF) - открывает канал "R"
0 (#00) - открывает канал "K"
1 (#01) - открывает канал "K"
2 (#02) - открывает канал "S"
3 (#03) - открывает канал "P" .
Так вот, повторюсь, при вызове процедуры
аккумулятор должен содержать номер потока
(см. таблицу). К тому же,процедура должна
вызываться в сответствии с приведенным
ниже текстом:
LD A,номер потока
CALL 5633 (#1601) .
А для того, чтобы печатать нормально во
всем экране, надо в регистр A занести
число 2 и вызвать процедуру CHAN-OPEN .
SET_ADDR - программа расчета адреса
знакоместа на экране. При обращении к
данной процедуре регистр B должен содер-
жать координату X, а регистр C координату
Y требуемого знакоместа. Вместо точки
входа в ПЗУ, представляю вам листинг этой
программы.
LD B,координата Y
LD C,координата X
CALL SET_ADDR
............
SET_ADDR
LD A,B
RRCA
RRCA
RRCA
AND #E0
LD L,A
LD A,B
AND #18
OR #40
LD H,A
LD B,#00
ADD HL,BC
RET .
После вызова процедуры SET_ADDR адрес
знакоместа находится в регистре HL.
SET_ATTR - эта процедура расчитыва-
ет адрес атрибута для соответствующего
адреса из области точек. На входе в про-
цедуру регистр HL должен содержать нужный
адрес из области точек. Также приведу
листинг данной процедуры.
LD HL,адрес
CALL SET_ATTR
............
SET_ATTR
LD A,H
RRCA
RRCA
RRCA
AND #0B
OR #50
LD H,A
RET .
Здесь в HL возвращается адрес атрибута.
А теперь приведу несколько простых
приемов, требующихся при написании прог-
рамм в ассемблере.
Деление регистровoй пары на 2, 4, 8
и т.д. :
AND A
RR B
RR C .
При повторе данного примера N раз вы раз-
делите число на 2 в степени N. Таким ме-
тодом возможно разделить и отдельные ре-
гистры.
Умножить регистровую пару можно по
аналогии с предыдущим примером, заменив
команды RR на RL:
AND A
RL C
RL B .
А если вам надо перемножить регистр HL,то
это лучше сделать командой сложения ADD :
ADD HL,HL умножить на два
ADD HL,HL на четыре
ADD HL,HL на восемь
........... и т.д.
А сейчас частные примеры:
Умножение HL на шесть :
ADD HL,HL
LD B,H
LD C,L
ADD HL,HL
ADD HL,BC ,
умножение HL на сорок :
ADD HL,HL
ADD HL,HL
ADD HL,HL
LD B,H
LD C,L
ADD HL,HL
ADD HL,HL
ADD HL,BC ,
деление A на шесть:
LD A,делимое
LD B,#00
LABEL SUB #06 (делитель)
RET C
INC B
JR LABEL
на выходе этой процедуры частное будет
находится в регистре B (не забудте, что
таким методом можно выполнить только це-
лочисленное деление!).
Если вы используете для сложения
или вычитания регистровых пар команды :
ADC и SBC, помните - при вычислениях они
используют флаг переноса (CARRY FLAG).
Поэтому перед ADC или SBC для получения
верного результата этот флаг необходимо
сбрасывать. Очень удобно делать это ко-
мандой AND A. При этом содержимое акку-
мулятора не меняется.
Между прочим, в ПЗУ SPECTRUMа есть
специальная мощная программа для разнооб-
разных математических вычислений. Но она
имеет ряд недостатков, из-за которых ее
использование бывает затруднительно :
1.Вычисления производятся достаточно мед-
ленно. Поэтому калькулятор нецелесообраз-
но применять, например для расчета коор-
динат в программах с динамической вектор-
ной графикой.
2.Работа с калькулятором осуществляется
несколько необычным способом, впрочем,
хорошо знакомым тем, кто когда-нибудь ра-
ботал на ПМК (программируемом микрокаль-
куляторе. Суть работы такова : сначала на
СТЕК КАЛЬКУЛЯТОРА (не на машинный!) зано-
сятся значения, а затем производятся опе-
рации с ними. После чего, опять же, со
стека калькулятора снимается результат.
Не вдаваясь глубоко в подробности, приве-
дем некоторые точки входа, необходимые
для работы :
значение из A на стек #2D28
значение со стека в A #2DD5
значение из BC на стек #2D2B (*)
заначение со стека в BC #2DA2
*) при возврате из этой подпрограммы в
регистре IY будет установлено значение
23610 (#5C3A).
Теперь небольшой пример практическо-
го применения калькулятора.
Необходимо вычислить (21-Y)*8+3 :
LD A,21 ; заносим на стек
CALL #2D28
LD A,(Y) ; значения в поряд-
CALL #2D28
LD A,8 ; ке вычислений,
CALL #2D28
LD A,3 ; т.е. 21 Y 8 3
CALL #2D28
; теперь будем считать
RST #28 ; вкл. калькулятор
DEFB #03 ; вычитаем
DEFB #04 ; умножаем
DEFB #0F ; прибавляем
DEFB #38 ; выкл. калькулятор
; снимаем результат со стека
CALL #2DD5 ; результат в A
Попробуйте написать самостоятельно
подпрограмму вычислений по этой формуле
без использования калькулятора и сравнить
и эти две процедуры.
Таблицу кодов операций калькулятора
вы можете найти в трехтомнике по програм-
мированию в машинных кодах фирмы "ИНФОР-
КОМ". А если вы не сможете найти эту ли-
тературу, мы поделимся информацией в сле-
дующих выпусках журнала.
На этом разрешите откланяться, а
если кому-то что-то не ясно или появились
вопросы - обращайтесь в редакцию журнала,
мы приложим все усилия и постараемся
помочь вам!
* * *