Question

Étant donné que de nombreux problèmes liés à Project Euler nécessitent un contrôle de la divisibilité plusieurs fois, j’essaie de trouver le moyen le plus rapide d’exécuter cette tâche dans ZX81 BASIC.

Jusqu'à présent, j'ai comparé (N / D) à INT (N / D) pour vérifier si N est divisible par D ou non.
Je pensais faire le test dans code machine Z80 , je n'ai pas encore compris comment utiliser les variables du BASIC dans le code machine.

Comment cela peut-il être réalisé?

Était-ce utile?

La solution

Je ne sais pas si RANDOMIZE USR est disponible dans le ZX81 mais je pense qu’il peut être utilisé pour appeler des routines en assembleur. Pour passer des arguments, vous devrez peut-être utiliser POKE pour définir des emplacements de mémoire fixes avant d'exécuter RANDOMIZE USR.

Je me souviens de trouver une liste de routines implémentées dans la ROM pour prendre en charge le ZX Basic. Je suis sûr qu'il en existe quelques-uns pour effectuer des opérations flottantes.

Une alternative à la virgule flottante consiste à utiliser le calcul mathématique en virgule fixe. C'est beaucoup plus rapide dans ce genre de situation où il n'y a pas de coprocesseur mathématique.

Vous pouvez également trouver plus d’informations sur les problèmes d’utilisateur de Sinclair. Ils ont publié des articles sur la programmation dans le ZX Spectrum

Autres conseils

Vous pouvez faire cela très rapidement dans le code machine en soustrayant plusieurs fois. Fondamentalement, vous avez une procédure comme:

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

La version 8 bits aurait quelque chose comme:

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

Vous pouvez maintenant appeler à partir de base avec USR. Ce que l'USR renvoie est ce qui se trouve dans la paire de registres de la Colombie-Britannique. Vous voudrez donc probablement faire quelque chose du genre:

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

Ceci est une introduction que j'ai écrite à Z80 et qui devrait vous aider à comprendre cela. expliquez les drapeaux si vous ne les connaissez pas. Il y a beaucoup plus de liens vers de bonnes choses sur le Z80 depuis le site principal, bien que le spectre soit ciblé sur le ZX81.

Une version 16 bits serait assez similaire mais utiliserait des opérations de paires de registres. Si vous devez aller au-delà de 16 bits, cela deviendra un peu plus compliqué.

La façon dont vous chargez cela dépend de vous - mais la méthode traditionnelle utilise des instructions DATA et des POKE. Vous préférerez peut-être qu'un assembleur trouve le code machine pour vous!

Votre solution existante est peut-être suffisante. Remplacez-le par quelque chose de plus rapide si vous constatez que c'est un goulot d'étranglement dans le profilage.

(dit avec un visage impassible, bien sûr.)

Et de toute façon, sur le ZX81, vous pouvez simplement passer en mode FAST.

Commencez par placer les valeurs dans des emplacements de mémoire connus à l’avance. Utilisez ensuite les mêmes emplacements depuis l’assembleur Z80. Aucun paramètre ne passe entre les deux.

Ceci est basé sur ce que je me souviens (encore) de ZX Spectrum 48. Bonne chance, mais vous pourriez envisager de mettre à jour votre hw. ; /

Le problème avec le code machine Z80 est qu’il n’a pas d’opérations en virgule flottante (et qu’il n’y ait pas de division ou de multiplication d’entiers). L'implémentation de votre propre bibliothèque FP dans l'assembleur Z80 n'est pas triviale. Bien sûr, vous pouvez utiliser les routines BASIC intégrées, mais vous pouvez aussi vous en tenir à BASIC.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top