|
Move
#10
04 сентября 1997 |
|
Алгоритмы - Подпрограммы связанные с выводом на экран: переход к предыдущему символу по экранному адресу, переход на следующую экранную линию, переход к предыдущей линии экрана, как определить адрес атрибута для заданного символа с координатами XY, переход к следующей строке атрибутов. Быстрая процедура умножения.

Алгоритмы и идеи. Быстрая процедура умножения.
Ars; KVA from E-Mage /г.Гродно/
(ОКОНЧАНИЕ. НАЧАЛО В MOVE #09)
────────────────────────────────────────────────────────────────
(c) Ars
В этой рубрике мы продолжаем публиковать полезные процедуры.
На этот раз речь пойдет о различных подпрограммах, связанных с
выводом на экран. Если у вас возникнут какие-то замечания,
сообщите нам. А также вы можете предложить для обсуждения свой
вариант алгоритмов на страницах MOVE.
Часть процедур, приводимых ниже, написал Rui Ribeiro - автор
WSpecem - эмулятора Спектрума для Windows.
7) Переход к предыдущему символу по экранному адресу.
Input: HL = screen address
Output: HL = previous char screen address
PrevChr RR H
RR H
RR H
DEC HL
RL H
RL H
RL H
RET
Две следующие процедуры вы наверняка знаете наизусть, настолько
часто они используются в программах.
8) Переход на следующую экранную линию.
Input: HL = screen address
Output: HL = scan inferior address
NextLine INC H
LD A,H
AND 7
RET NZ
LD A,L
ADD A,32
LD L,A
RET C
LD A,H
SUB 8
LD H,A
RET
9) Переход к предыдущей линии экрана.
Input: HL = screen address
Output: HL = superior scan address
PrevLine DEC H
LD A,H
AND 7
CP 7
RET NZ
LD A,L
SUB 32
LD L,A
RET C
LD A,H
ADD A,8
LD H,A
RET
10) Следующая процедура позволяет просканировать экран так, как
это делает луч разверки.
Input: screen address
Output: next visual scan address
NextVAdd INC L
LD A,L
AND #1F
RET NZ
INC H
LD A,H
AND 7
LD A,L
JR NZ,NVALab
AND #E0
RET Z
LD A,H
SUB 8
LD H,A
RET
NVALab SUB 32
LD L,A
RET
11) Та же самая операция, но движение в обратную сторону - снизу
вверх.
Input: HL = screen address
Output: HL = previous visual scan address
PrevVAdd DEC L
LD A,L
AND #1F
CP #1F
RET NZ
DEC H
LD A,H
AND 7
CP 7
LD A,L
JR NZ,PVALab
AND #E0
CP #E0
RET Z
LD A,H
ADD A,8
LD H,A
RET
PVALab ADD A,32
LD L,A
RET
И напоследок, процедуры, связанные с адресацией атрибутов.
Atribute file: Length=768 bytes. Address: #5800..#5AFF
(22528..23295)
Цвета задаются
Адрес атрибута вычисляется так: следующими битами:
adr(C,L) = 22528+L*32+C 7 6 543 210
---------------
где: L - строчка (0..23) f b p i
C - столбец (0..31) l r a n
a i p k
Схематически адрес атрибута выглядит так: s g e
h h r
0101 10LL LLLC CCCC t
12) Как определить адрес атрибута для заданного символа с
координатами XY.
Input: BC = YX
Output: HL = attribute address
AdrAttr LD A,B
RRCA
RRCA
RRCA
LD H,A
AND #E0
OR C
LD L,A
LD A,H
AND 3
OR #58
LD H,A
RET
13) Переход к следующей строке атрибутов.
Input: HL = attribute address
Output: HL = upper attribute address
DownAttr LD A,L LD DE,32
ADD A,32 или ADD HL,DE
LD L,A
RET NC
INC H
RET
14) Переход к предыдущей строке атрибутов.
Input: HL = attribute address
Output: HL = lower attribute address
UpAttr LD A,L LD DE,32
SUB 32 или AND A
LD L,A SBC HL,DE
RET NC
DEC H
RET
Информация получена с Web-странички:
http://www.atlantic.net/~adansby/plot.html
КАК БЫСТРО ПЕРЕМНОЖИТЬ ДВА ЧИСЛА.
(Концепция процедур умножения.)
────────────────────────────────────────────────────────────────
(c) KVA from E-Mage /г.Гродно/
В настоящее время многие знают как быстро перемножить два
числа, однако не все знают как работают те процедуры, которыми
они пользуются. Если же понять, по какому принципу написаны все
эти алгоритмы, то под каждый конкретный случай можно написать
процедуру, которая будет раза в два быстрее, чем процедура для
общего случая.
Рассмотрим, как мы перемножаем два числа в десятичной
системе счисления:
176*25 = 100*(1*25)+10*(7*25)+1*(6*25)
Т.е., мы раскладываем одно из чисел на разряды (единицы,
сотни, десятки и т.д.). Но ведь можно же сделать то же самое и в
двоичной системе счисления :
101101*1011 = 100000*(1*1011)+10000*(0*1011)+...
Теперь заметим, что умножение сводится к двум операциям:
1. Умножение на два (операция в Assembler'e - ADD r,r).
2. Прибавление второго числа.
Попробуем на таком принципе разложить предыдущее число:
101101*1011=1*1011+10*(0*1011+10*(1*1011+10*(1*1011+
10*(0*1011+10*(1*1011)))))
Рассмотрим процедуру умножения байт*байт, написанную в Echo:
ADD HL,HL ┐ H - число 1 ┐
JR NC,M1 ├ Повторить 8 раз. E - число 2 ├Вход
ADD HL,DE │ D и L = 0 ┘
M1: ┘ HL = Answer ─Выход
Команда ADD HL,HL выполняет сразу две функции:
1. Умножает содержимое регистра L на два.
2. Выносит последний бит регистра H в флаг C.
(При первой команде получаем 7-й бит входного числа,
при второй - 6- бит входного числа и т.д.)
Команда JR NC,M1 выполняет функцию умножения (т.к. мы
пользуемся двоичной системой, то у нас есть только две цифры, на
которые мы можем умножить - 0 и 1)
Команда ADD HL,DE используется для прибавления к регистру L
регистра E.
Команды JR NC,M1 и ADD HL,DE вместе выполняют функцию
прибавления к регистру L регистра Е, умноженного на последний
бит регистра H.
В этой процедуре используется принцип "с конца", т.е.
сначала обрабатывается бит 7, затем 6 и т.д. А если короче, то
здесь применяется сочетательный закон математики, который
изучается еще в школе. Можно сначала взять E, умноженное на 0-й
бит H. Затем прибавить число 10*E*[1-й бит H] (10 - двоичная
система), потом число 100*Е*[2-й бит H], потом 1000*Е*[3-й бит
H]...прибавляем 10000000*E*[7-й бит H]. А можно сделать
по-другому. Сначала берем Е*[7-й бит H], умножаем на 10 (2),
прибавляем Е*[6-й бит H], умножаем на 10, прибавляем Е*[5-й бит
H]...умножаем на 10, прибавляем Е*[0-й бит H]. В конце этой
операции, получим точно такой же эффект, как и в первом случае,
однако с помощью assembler'a Spectrum'а второе сделать легче !!!
Напоследок, привожу пару процедур, написанных мной для случая
байт*слово=слово (слово это 2 байта), слово*слово=слово,
слово*слово=двойное слово (4 байта), двойное слово*двойное
слово= двойное слово.
Хочу сразу же всех предупредить, что тексты здесь с
использованием специальных директив ассемблера ALASM v3.8 - DUP
и EDUP (DUP x -повторить x раз строчки, следующие за этой
командой и оканчивающиеся строчкой с командой EDUP).
; байт*слово=слово
; Вход - А-число 1, DE-число 2.
; Выход - HL-результат.
LD HL,0
DUP 8
ADD HL,HL
ADD A,A
JR NC,$+3
ADD HL,DE
EDUP
; слово*слово=слово
; Вход - BC-число 1,DE-число 2.
; Выход - HL-результат.
LD HL,0
LD A,B
DUP 8
ADD HL,HL
ADD A,A
JR NC,$+3
ADD HL,DE
EDUP
LD A,C
DUP 8
ADD HL,HL
ADD A,A
JR NC,$+3
ADD HL,DE
EDUP
; слово*слово=двойное слово
; Вход - BC-число 1,DE-число 2
; Выход - HL-младшая часть слова,HL'-старшая часть слова.
LD HL,0
EXX
LD HL,0
LD DE,0
EXX
LD A,B
DUP 8
ADD HL,HL
EXX
ADC HL,HL
EXX
ADD A,A
JR NC,$+6
ADD HL,DE
EXX
ADC HL,DE
EDUP
LD A,C
DUP 8
ADD HL,HL
EXX
ADC HL,HL
EXX
ADD A,A
JR NC,$+6
ADD HL,DE
EXX
ADC HL,DE
EXX
EDUP
; двойное слово*довойное слово=двойное слово
; Вход - DE' DE-число 1, BC' BC-число 2
; Выход - HL' HL-результат
LD HL,0
EXX
LD HL,0
EXX
DUP 16
ADD HL,HL
EXX
ADC HL,HL
EX DE,HL
ADD HL,HL
EX DE,HL
EXX
JR NC,$+6
ADD HL,BC
EXX
ADC HL,BC
EXX
EDUP
DUP 16
ADD HL,HL
EXX
ADC HL,HL
EXX
EX DE,HL
ADD HL,HL
EX DE,HL
JR NC,$+6
ADD HL,BC
EXX
ADC HL,BC
EDUP
P.S. Если кого-нибудь заинтересовала эта статья (и вообще,
эта тема), вы можете написать в редакцию MOVE или связаться со
мной по телефону (0152) 318-721 (Витя), либо оставить сообщение
на E-Mage BBS (0152) 441-176. Ждите следующих номеров MOVE, где
я опишу процедуры деления.
Другие статьи номера:
Эхо - Обзор писем читателей газеты: Beard, Space5, DarkMax. |
Система - Организация почты в C-DOS v1.32. |
Алгоритмы - Подпрограммы связанные с выводом на экран: переход к предыдущему символу по экранному адресу, переход на следующую экранную линию, переход к предыдущей линии экрана, как определить адрес атрибута для заданного символа с координатами XY, переход к следующей строке атрибутов. Быстрая процедура умножения. |
Железо - Гальвоническая развязка с телефонной линией в C-DOS модеме. |
Мозаика - Спектрум в Internet. |
BRAVO на отдых - Рассказы : Автобус, Ода комару. |
Реклама - Реклама и объявления. |
Похожие статьи:
В этот день... 16 ноября