3

由于许多 Project Euler 问题需要您多次进行整除性检查,因此我一直试图找出在ZX81 BASIC 中执行此任务的最快方法。

到目前为止,我已经比较(N/D)INT(N/D)是否N可以除以D
一直在想用Z80机器码做测试,还没想清楚如何在机器码中使用BASIC中的变量。

如何实现?

4

5 回答 5

7

您可以通过重复减法在机器代码中非常快速地做到这一点。基本上你有一个像这样的程序:

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 的介绍,应该可以帮助您解决这个问题。如果您不熟悉这些标志,这将解释它们。尽管它是 Spectrum 而不是 ZX81 的重点,但主站点上有更多指向 Z80 好东西的链接。

16 位版本将非常相似,但使用寄存器对操作。如果您需要超过 16 位,它会变得更加复杂。

你如何加载它取决于你——但传统的方法是使用 DATA 语句和 POKE。不过,您可能更喜欢让汇编程序为您找出机器代码!

于 2009-12-16T23:08:08.120 回答
4

您现有的解决方案可能已经足够好了。如果您发现它是分析中的瓶颈,请仅将其替换为更快的东西。

(当然是板着脸说。)

无论如何,在 ZX81 上,您只需切换到 FAST 模式即可。

于 2009-03-15T12:29:15.910 回答
2

不知道 RANDOMIZE USR 是否在 ZX81 中可用,但我认为它可以用来调用汇编中的例程。要传递参数,您可能需要在执行 RANDOMIZE USR 之前使用 POKE 设置一些固定的内存位置。

我记得在 ROM 中找到了一个支持 ZX Basic 的例程列表。我敢肯定有几个可以执行浮动操作。

浮点的替代方法是使用定点数学。在这种没有数学协处理器的情况下,它要快得多。

您还可以在 Sinclair 用户问题中找到更多信息。他们在 ZX Spectrum 上发表了一些与编程相关的文章

于 2009-03-15T13:02:36.020 回答
0

您应该首先将这些值放在一些预先知道的内存位置。然后使用 Z80 汇编器中的相同位置。两者之间没有参数传递。

这是基于我(仍然)记得的 ZX Spectrum 48。祝你好运,但你可能会考虑升级你的硬件。;/

于 2009-03-15T12:29:01.980 回答
0

Z80 机器代码的问题在于它没有浮点运算(就此而言,也没有整数除法或乘法)。在 Z80 汇编器中实现您自己的 FP 库并非易事。当然,你可以使用内置的 BASIC 例程,但你也可以坚持使用 BASIC。

于 2009-03-15T12:44:04.440 回答