Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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. Вы можете предпочесть, чтобы ассемблер выяснил машинный код для вас!

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top