ZX-Ревю 1996 №3 1996 г.

Читатель - читателю - генераторы псевдослучайных последовательностей.


ЧИТАТЕЛЬ-ЧИТАТЕЛЮ

ГЕНЕРАТОРЫ ПСЕВДОСЛУЧАЙНЫХ ПОСЛЕДОВАТЕЛЬНОСТЕЙ © Колотов Сергей, г. Шадринск 1996.

В ZX РЕВЮ 95/6 я с огромным интересом прочитал статью "Быстродействующий генератор псевдослучайных чисел". Получение случайных (точнее псевдослучайных) чисел на компьютере - довольно увлекательная задачка. Примеры её решения неоднократно публиковались и раньше.

Метод, предложенный Сергеем Астровым довольно-таки интересен и поучителен, но с новым алгоритмом появились и новые ограничения в использовании (невозможность получения нулевого значения, периодичность). Напоминаю, по алгоритму в регистре сдвига HL ксорятся биты, отмеченные на схеме, затем регистр сдвигается от младших номеров битов к старшим, а в

нулевой бит записывается результат ксорки.

Н L

Чтобы "перексорить" эти биты, достаточно "вращать" аккумулятор влево командой RLCA (в сторону возрастания номеров битов), выполняя команду XOR в нужный момент (один раз с регистром L и три раза с регистром H). Неважно, что портятся остальные биты аккумулятора, ведь нас интересует только один. Последней командой RLCA нужный нам бит попадает в флаг переноса и затем командой ADC HL,HL попадет в нулевой бит регистровой пары HL после ее сдвига влево.

Новая процедура занимает всего 25 байт. Ее листинг:

RND 31

HL,(SEED) A, H L

NZ,NOZERO L

A, L H

LD

LD

OR

JR

INC

LD

RLCA XOR

NOZERO

RLCA

RLCA

XOR

RLCA

XOR

RLCA

ADC

LD

RET

DEFW

H

H

HL, HL (SEED),HL

#00

SEED

Внимательно изучив работу программы для тестирования различных процедур RND (ZX-РЕВЮ 95/4, с.49), я предлагаю ввести некоторые коррективы. Так, осмысливать процедуру на предмет полного заполнения экрана "на глазок" - топорный приём. Компьютер сам может и должен за этим проследить! И ещё одно замечание. Для заполнения экрана нужно брать не один только младший байт из SEED, но и не забывать о старшем. Мало ли как он себя ведёт (вдруг не псевдослучайно). Вот новый листинг программы:

DIFTST

RES

5,(IY+1)

LPDT1

LD

HL,#4000

LD

B, L

LPDT2

PUSH

HL

PUSH

BC

CALL

RND

POP

BC

POP

HL

LD

A,(SEED)

OR

(HL)

LD

(HL),A

INC

A

JR

Z,GODT1

LD

B, H

GODT1

INC

HL

LD

A,(SEED+1)

OR

(HL)

LD

(HL),A

INC

A

JR

Z,GODT2

LD

B, H

GODT2

INC

HL

BIT

5,(IY+1)

RET

NZ

LD

A, H

CP

#58

JR

C,LPDT2

LD

A, B

OR

A

JR

NZ,LPDT1

RET

Вообще, хочу заметить, что судить о скорости выполнения RND-процедур на таких тестах можно лишь очень приблизительно. Возможно даже, что большая часть времени уйдет на выполнение самого теста и на прерывания (если тестируемая процедура ну очень маленькая). Такие тесты лучше подходят для изучения разброса случайных чисел, их повторяемости. По этому поводу у меня появились некоторые мыслишки и в результате получился новый SEED TEST, который я вам и предлагаю:

SPDTST

DI

LD

LD

LD

INC

LD

LD

INC

HL,#FDFD A, H

(HL),#C3 HL

DE,MYINT (HL),E HL

FILL

LPST1

LPST2

MYINT

COUNT TSTIME

Вначале процедура настраивается на работу в режиме IM2 - подсчёт числа прерываний за время работы теста. Затем происходит выполнение теста вхолостую - необходимо подсчитать время выполнения самого себя. При этом вместо тестируемой RND-процедуры вызывается подпрограмма по адресу 124. В ПЗУ по этому адресу стоит RET, что успешно и выполняется. После этого тест нормально отрабатывается и вычитает из полученного значения время своей работы. Результат вычислений помещается в регистровую пару BC и, следовательно, его можно узнать из БЕЙСИКа командой PRINT USR ...

LD

(HL),D

INC

HL

LD

(HL),A

INC

L

JR

NZ,FILL

INC

H

LD

(HL),A

INC

A

LD

I,A

IM

2

LD

HL, #FFFF

LD

(COUNT) , HL

EI

HALT

PUSH

HL

CALL

124

POP

HL

DEC

HL

LD

A, L

OR

H

JR

NZ,LPST1

LD

HL,(COUNT)

HALT

LD

(TSTIME),HL

LD

HL,#FFFF

LD

(COUNT) , HL

HALT

PUSH

HL

CALL

RND

POP

HL

DEC

HL

LD

A, L

OR

H

JR

NZ,LPST2

DI

LD

A, #3F

LD

I,A

IM

1

LD

HL,(COUNT)

LD

BC,(TSTIME)

AND

A

SBC

HL, BC

LD

B, H

LD

C, L

EI

RET

PUSH

HL

LD

HL,(COUNT)

INC

HL

LD

(COUNT) , HL

POP

HL

EI

RET

DEFW

0

DEFW

0

Мною было проведено исследование скорости работы различных RND-процедур на двух компьютерах. Были получены следующие значения:_

Процедуры RND

КОМПЬ

ЮТЕРЫ

КВОРУМ-128

СПЕКТР

RND: №6,1994

425

1851

RND 2: №4,1995

223

948

RND 3: №6,1995

123

550

RND 31:

92

410

RND 4:

82

411

Объяснить такой разброс для двух компьютеров не могу, выводы же можете делать сами.

Присмотревшись к таблице повнимательнее, Вы спросите: а что за RND_4 присутствует здесь, как ни в чём не бывало? Отвечаю: это самая маленькая на данный момент RND-процедура из написанных мною. Она занимает всего 20 байт (2 байта SEED, я думаю, давно пора перестать считать). В своей работе процедура использует регистр регенерации R и данные из ПЗУ - они хорошо подходят для этой цели. В результате, процедура работает очень быстро и выдаёт довольно-таки случайное распределение чисел. Вот её листинг:

LD

HL,(SEED)

LD

A, R

XOR

H

LD

E, A

AND

%00111111

LD

D, A

LD

A, (DE)

XOR

L

LD

H, A

XOR

E

RRCA

LD

L, A

LD

(SEED),HL

RET

Работая на ассемблере долгое время, удивляешься - какое количество тайников и секретов содержит этот простенький с виду процессор Z80. Так, совсем недавно, я обнаружил две очень интересные команды, одна из которых заполняет содержимым флага переноса аккумулятор, а вторая - регистровую пару HL. А ведь эти команды всё время были на виду. Лишь запись их мнемоник была не очень удобочитаема. Итак, это команды: SBC A,A (#9F) и SBC HL,HL (#ED #62). Вот как они работают:

•S если флаг C включен (равен 1), то при выполнении SBC A,A в аккумуляторе будет #FF (аналогично, команда SBC HL,HL занесёт в регистровую пару HL число #FFFF) •f если флаг C выключен (равен 0), то получим A=0 (HL=0). Приведу один интересный пример использования команды SBC A,A: В программах часто можно встретить такую конструкцию: LD A, 0

JR NC,GO1

LD A,...

GO1 ...

Но ведь гораздо проще написать:

SBC A, A AND .

Преимущества налицо.

Также, я хотел бы высказать своё мнение насчёт использования шестнадцатеричной системы счисления. Совсем недавно я считал HEX-систему "страшилкой" и все мои программы писал только в десятичной системе. Если где-нибудь встречались значки H,#, то я ужасно ругался и пересчитывал, пересчитывал, пересчитывал...

Но времена меняются. Долгие копания в чужих программах, работа с дизассемблером, да и что греха таить - ваши публикации, сломили кодерскую душу, и теперь о пользе HEX-системы

25

меня можно не вразумлять. Я уж не говорю о том, что при работе с экраном и TR-DOS использование HEX-системы просто необходимо!




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Капля припоя - схема ZS Scorpion 1024.
Почта - Анонс раздела.
Фантастика - Повесть Стругацких "Путь к Амальтею"(продолжение).
Music - n1k-o обьясняет итальянскому спектрумисту, как пользоваться Pro Tracker'ом.
Программистам - Конверсия чисел в десятичный формат.

В этот день...   21 ноября