由于许多Project Euler问题要求你进行很多次的可分性检查,我一直试图找出在ZX81 BASIC中执行此任务的最快方法。
到目前为止,我已将(N/D)
与INT(N/D)
进行了比较,以检查N
是否可以D
分割。
我一直在考虑在Z80 machine code中进行测试,我还没有想出如何在机器代码中使用BASIC中的变量。
如何实现?
答案 0 :(得分: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
This is an introduction I wrote to Z80 which should help you figure this out.如果您不熟悉它们,这将解释标志。 虽然它是Spectrum而不是ZX81,但是有更多链接可以从主站点获得良好的Z80内容。
16位版本将非常相似,但使用寄存器对操作。如果你需要超过16位,它会更复杂。
如何加载它取决于您 - 但传统方法是使用DATA语句和POKE。您可能更愿意让汇编程序为您找出机器代码!
答案 1 :(得分:4)
您现有的解决方案可能已经足够好了。如果你发现它是分析的瓶颈,只能用更快的东西替换它。
(当然,直言不讳地说。)
无论如何,在ZX81上你可以切换到快速模式。
答案 2 :(得分:2)
不知道ZX81中是否有RANDOMIZE USR,但我认为它可用于调用程序集中的例程。要传递参数,您可能需要在执行RANDOMIZE USR之前使用POKE设置一些固定的内存位置。
我记得在ROM中找到一个例程列表来支持ZX Basic。我确信有一些可以执行浮动操作。
浮点的替代方法是使用定点数学。在没有数学协处理器的情况下,它会快得多。
您还可以在Sinclair用户问题中找到更多信息。他们在ZX Spectrum中发表了一些与编程有关的文章
答案 3 :(得分:0)
首先应将值放在某些预先知道的内存位置。然后使用Z80汇编程序中的相同位置。两者之间没有参数传递。
这是基于我(仍然)记得的ZX Spectrum 48.祝你好运,但你可能会考虑升级你的hw。 ; /
答案 4 :(得分:0)
Z80机器码的问题在于它没有浮点运算(并且没有整数除法或乘法)。在Z80汇编程序中实现自己的FP库并非易事。当然,你可以使用内置的BASIC例程,但是你也可以坚持使用BASIC。