Быстрая проверка делимости в ZX81 BASIC - PullRequest
3 голосов
/ 15 марта 2009

Поскольку многие проблемы Project Euler требуют от вас проверки делимости довольно много раз, я пытался найти самый быстрый способ выполнить эту задачу в ZX81 BASIC.

До сих пор я сравнивал (N/D) с INT(N/D), чтобы проверить, делится ли N на D или нет.
Я думал о проведении теста в Z80 машинный код , я еще не понял, как использовать переменные в бейсике в машинном коде.

Как этого достичь?

Ответы [ 5 ]

7 голосов
/ 17 декабря 2009

Вы можете сделать это очень быстро в машинном коде, вычитая несколько раз. Обычно у вас есть такая процедура:

set accumulator to N
subtract D
if carry flag is set then it is not divisible
if zero flag is set then it is divisible
otherwise repeat subtraction until one of the above occurs

8-битная версия будет выглядеть примерно так:

DIVISIBLE_TEST:
LD B,10
LD A,100

DIVISIBLE_TEST_LOOP:
SUB B
JR C, $END_DIVISIBLE_TEST
JR Z, $END_DIVISIBLE_TEST
JR $DIVISIBLE_TEST_LOOP

END_DIVISIBLE_TEST:
LD B,A
LD C,0
RET

Теперь вы можете звонить с обычного, используя USR. USR возвращает то, что находится в паре регистров BC, поэтому вы, вероятно, захотите сделать что-то вроде:

REM poke the memory addresses with the operands to load the registers
POKE X+1, D
POKE X+3, N
LET r = USR X
IF r = 0 THEN GOTO isdivisible
IF r <> 0 THEN GOTO isnotdivisible

Это введение, которое я написал для Z80, должно помочь вам понять это. Это объяснит флаги, если вы с ними не знакомы. На основном сайте есть много ссылок на хорошие материалы по Z80, хотя речь идет о спектруме, а не о ZX81.

16-битная версия была бы очень похожа, но с использованием операций пары регистров. Если вам нужно выйти за пределы 16 бит, это будет немного более запутанным.

Как вы загружаете это, зависит от вас - но традиционный метод использует операторы DATA и POKE. Вы можете предпочесть, чтобы ассемблер выяснил машинный код для вас!

4 голосов
/ 15 марта 2009

Ваше существующее решение может быть достаточно хорошим. Замените его на что-то более быстрое, только если вы обнаружите, что оно является узким местом в профилировании.

(Сказано с невозмутимым лицом, конечно.)

И в любом случае, на ZX81 вы можете просто переключиться в режим FAST.

2 голосов
/ 15 марта 2009

Не знаю, доступен ли RANDOMIZE USR в ZX81, но я думаю, что его можно использовать для вызова подпрограмм в сборке. Для передачи аргументов вам может потребоваться использовать POKE, чтобы установить несколько фиксированных областей памяти перед выполнением RANDOMIZE USR.

Я помню, что нашел список подпрограмм, реализованных в ПЗУ для поддержки ZX Basic. Я уверен, что есть несколько, чтобы выполнить плавающую операцию.

Альтернативой с плавающей запятой является использование математики с фиксированной запятой. Это намного быстрее в подобных ситуациях, когда нет математического сопроцессора.

Вы также можете найти больше информации в вопросах пользователей Sinclair. Они опубликовали несколько статей, связанных с программированием в ZX Spectrum

0 голосов
/ 15 марта 2009

Проблема с машинным кодом Z80 заключается в том, что у него нет операций с плавающей запятой (и, в этом отношении, целочисленного деления или умножения). Реализация вашей собственной библиотеки FP в ассемблере Z80 не тривиальна. Конечно, вы можете использовать встроенные подпрограммы BASIC, но тогда вы можете просто придерживаться BASIC.

0 голосов
/ 15 марта 2009

Сначала вы должны поместить значения в некоторые заранее известные ячейки памяти. Затем используйте те же места в ассемблере Z80. Между этими двумя параметрами нет передачи.

Это основано на том, что я (до сих пор) помню о ZX Spectrum 48. Удачи, но вы могли бы подумать об обновлении вашего hw. /

...