Move #10
04 сентября 1997

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

<b>Алгоритмы</b> - Подпрограммы связанные с выводом на экран: переход к предыдущему символу по экранному адресу, переход на следующую экранную линию, переход к предыдущей линии экрана, как определить адрес атрибута для заданного символа с координатами 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 на отдых - Рассказы : Автобус, Ода комару.

Реклама - Реклама и объявления.


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

Похожие статьи:
От авторов - Редакция.
BRAVO на отдых - Рассказы : Автобус, Ода комару.
Самиздат - Новый Год для особо одиноких.
Разное - Еmрlаstrum аdhаesivum.
B.B.S. Новости - О работе B.B.S.'ок.

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