Этюды
Alone Coder
1. Вызов функции по номеру
а)если номера идут не подряд:
;HL=список функций
;(номер, смещение адреса),
;0=конец списка, т.е. функции 0 нет
;C=номер функции
#1624
CALL #1бDC
RET NC;функция не найдена
LD D,0
LD E,(HL);смещение адреса функции
ADD HL,DE
JP (HL)
...
#1бDB
INC HL
#1бDC
LD A,(HL)
AND A
RET Z;конец списка,функция не найдена
CP C
INC HL
JR NZ,#1бDB
SCF
RET
;пример списка функций:
DB 1
DB 255&(func1-$)
DB 10
DB 255&(func10-$)
DB 0;конец списка
;сами функции рядом:
func1
...
RET
func10
...
RET
б)если номера функций идут подряд (1,2,
...):
;B=номер функции
DJNZ nofunc1
<func1>
RET
nofunc1
DJNZ nofunc2
<func2>
RET
nofunc2
...
;у последней функции номер не проверяется
;(может быть 0)
<funcO>
RET
2. Поиск текста
(например, сообщения) по номеру
а)вариант из ACEdit:
;HL=указатель на список текстов
;(каждый текст кончается на 0)
;D=номер текста (1..n)
;возвращает HL = указатель на нужный текст
LD B,H;достаточно большое число
XOR A;символ конца текста
DEC D
RET Z
CPIR;ищем символ конца текста
;и ставим HL после него
JR $-4
б)вариант в ПЗУ 48 Basic
(только для ASCII, т.к. 7-й бит занят под
признак конца текста):
;DE=указатель на список текстов
;(каждый с установленным 7-м битом
;в последнем символе)
;A=номер текста (0..n)
;возвращает DE = указатель на нужный текст
#0C41
PUSH AF
EX DE,HL
INC A
#0C44
BIT 7,(HL)
INC HL
JR Z,#0C44
DEC A
JR NZ,#0C44
EX DE,HL
POP AF
cp #20 ;это
ret c ;для
ld a,(de);нас
sub #41 ;не важно
RET
;пример списка текстов:
#0095
DB #BF ;любой байт с установленным
;7-м битом (будет пропущен)
DB "RN","D"+#80
DB "INKEY","$"+#80
...
3. Определение наличия
музыкального сопроцессора
LD BC,#FFFD
XOR A;A=0/2/4/7/11 (полные 8-битные)
OUT (C),A;избегаем OUT (C),0
IN L,(C);oldRO
INC L
LD B,#BF
OUT (C),L;newRO != oldRO
;читать R0 и проверить, изменился ли он
LD B,#FF;#fdfd нельзя на ATM1
IN A,(C);R0
CP L;newRO
JR Z,AY_ON;R0 == newRO
AY_OFF
Кто придумает короче без потери совмес─
тимости?
4. Установка пикселя
в режиме 320x200 на ATM Turbo 2
Поскольку X-координата не помещается в
одном байте, отрежем младший бит в отдель─
ный регистр.
;setpixel (EGA screen)
;страницы экрана - в двух окнах памяти
;addr = tY(y) + tX(x)
;l=x
;e=y
;lx=xlow mask
;d='tY
;h='tX
LD A,(DE);(y*40)
ADD A,(HL);x div 4
LD C,A
INC D
INC H
LD A,(DE);'(y*40)
ADC A,(HL);f(x mod 4)
LD B,A
LD A,(BC)
(X)OR LX;xlow mask
LD (BC),A
DEC D
INC H
;74(66) t-states
(ср.62(58) такта на 6912, см. ZX-Guide #1)
Таблицы подготавливаются так:
LD HL,#4000;экран в #4000 и #c000
LD BC,40
LD E,B
mktyO
LD D,'tY
LD A,L
LD (DE),A
INC D
LD A,H
LD (DE),A
ADD HL,BC
INC E
JNZ mktyO
mktxO
LD D,'tX
LD A,E
RRA
RRA
AND #3F
LD (DE),A
INC D
LD A,E
RRCA
AND #80
BIT 2,E
JZ $+4
OR #20
LD (DE),A;#00,#80,#20,#a0
INC E
JNZ mktxO
В Nedodemo 2 использовался вариант это─
го метода приX=0..255:
;l=x
;e=y
;d='tY
LD H,'tX
LD A,(DE);(y*40)
ADD A,(HL);x div 4
LD C,A
INC D
INC H
LD A,(DE);'(y*40)
ADC A,(HL);f(x mod 4)
;#00,#00,#80,#80,#20,#20,#a0,#a0
LD B,A
INC H;'tXmask
LD A,(BC)
(X)OR (HL);xlow mask
LD (BC),A
DEC D
;80(76) t-states
В генераторе таблиц надо добавить тре─
тийRRA, второй RRCA, заменить #3F на #1F
и вставить передLD (DE),A:
INC D
LD A,E
RRA
SBC A,A
XOR %01000111;left pixel
AND C
5. Библиотеки процедур в ALASM
Если надо сделать библиотеку процедур,
каждая из которых будет компилироваться
только тогда,когда используется в програм─
ме, то можно пойти такими путями:
а)создать макросы на каждую процедуру:
INCLUDE "math",pgmath
...
MUL _MUL
DIV _DIV
math.h:
MACRO _MUL
;процедура умножения
RET
ENDM
MACRO _DIV
;процедура деления
RET
ENDM
б)один и тот же модуль инклюдить неско─
лько раз - по одному для каждой процедуры.
Это эффективнее по памяти, чем макросы
(где может просто переполниться страница
макросов), но скорость не гарантируется:
...
MUL INCLUDE "math",pgmath
DIV INCLUDE "math",pgmath
...
math.H:
IFN ?mathtwice
const1=1
const2=2
...
MACRO mathbla
...
ENDM
mathtwice
ENDIF
IFO ?MUL;если метка определена
IFN ?MULcompiled
;процедура умножения
RET
MULcompiled
ENDIF
ENDIF
IFO ?DIV;если метка определена
IFN ?DIVcompiled
;процедура деления
RET
DIVcompiled
ENDIF
ENDIF
в)инклюдить все библиотеки в самом кон─
це, чтобы они сами могли проверять, какие
процедуры используются, какие нет:
...
CALL MUL
CALL DIV
...
INCLUDE "math",pgmath
math.h:
IFN ?MUL;если к метке обращались
MUL
;процедура умножения
RET
ENDIF
IFN ?DIV;если к метке обращались
DIV
;процедура деления
RET
ENDIF
6. Короткий генератор случайных чисел
(прислал Tiboh)
EXX
INC HL
RES 3,H
LD A,R
XOR (HL)
EXX
7. Ускорение LD:PUSH
Обычный код вывода на экран типаLD DE:
PUSH DE неудачно ложится на задержки в фи─
рменных машинах (4 восьмитактовых цикла).
Если же есть свободный регистрBC, то
можно выиграть в скорости, переписав так:
LD BC,nn
LD DE,nn
PUSH BC
PUSH DE
Это занимает 7 восьмитактовых циклов,то
есть 3.5 на каждыйPUSH.
Добавление регистраHL в общем невыгод─
но (11 восьмитактовых циклов на триPUSH),
но если постараться загнать группуPUSH в
поле бордера, можно чего-то добиться.
Other articles: