Domanda

Poiché molti dei problemi di Project Euler richiedono un controllo di divisibilità per un certo numero di volte, ho cercato di capire il modo più veloce per eseguire questa attività in ZX81 BASIC.

Finora ho confrontato (N / D) con INT (N / D) per verificare se N è divisibile per D o no.
Ho pensato di fare il test in codice macchina Z80 , non l'ho ancora fatto capito come usare le variabili nel BASIC nel codice macchina.

Come può essere raggiunto?

È stato utile?

Soluzione

Non so se RANDOMIZE USR è disponibile in ZX81 ma penso che possa essere usato per chiamare le routine in assembly. Per passare argomenti potrebbe essere necessario utilizzare POKE per impostare alcuni percorsi di memoria fissi prima di eseguire RANDOMIZE USR.

Ricordo di trovare un elenco di routine implementate nella ROM per supportare ZX Basic. Sono sicuro che ci sono alcuni per eseguire operazioni mobili.

Un'alternativa al virgola mobile è l'uso della matematica in virgola fissa. È molto più veloce in questo tipo di situazioni in cui non esiste un coprocessore matematico.

Potresti anche trovare maggiori informazioni nei problemi degli utenti di Sinclair. Hanno pubblicato alcuni articoli relativi alla programmazione nello ZX Spectrum

Altri suggerimenti

Puoi farlo molto velocemente nel codice macchina sottraendo ripetutamente. Fondamentalmente hai una procedura come:

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 versione a 8 bit sarebbe simile a:

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

Ora puoi chiamare dalla base usando USR. Ciò che USR restituisce è qualunque cosa si trovi nella coppia di registri BC, quindi probabilmente vorresti fare qualcosa del tipo:

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

Questa è un'introduzione che ho scritto su Z80 che dovrebbe aiutarti a capirlo. Questo spiega le bandiere se non le conosci. C'è un sacco di collegamenti a cose buone Z80 dal sito principale sebbene sia Spectrum piuttosto che focalizzato su ZX81.

Una versione a 16 bit sarebbe abbastanza simile ma usando le operazioni della coppia di registri. Se hai bisogno di andare oltre i 16 bit, sarebbe un po 'più contorto.

Il modo in cui lo carichi dipende da te, ma il metodo tradizionale utilizza istruzioni DATA e POKE. Potresti preferire che un assemblatore capisca il codice macchina per te!

La tua soluzione esistente potrebbe essere abbastanza buona. Sostituiscilo con qualcosa di più veloce solo se lo trovi un collo di bottiglia nella profilazione.

(Detto con una faccia seria, ovviamente.)

E comunque, sullo ZX81 puoi semplicemente passare alla modalità FAST.

Dovresti prima posizionare i valori in alcune posizioni di memoria note. Quindi utilizzare le stesse posizioni all'interno dell'assemblatore Z80. Non esiste alcun parametro che passa tra i due.

Questo si basa su ciò che ricordo (ancora) di ZX Spectrum 48. Buona fortuna, ma potresti prendere in considerazione l'aggiornamento del tuo hardware. ; /

Il problema con il codice macchina Z80 è che non ha operazioni in virgola mobile (e nessuna divisione intera o moltiplicata, per quella materia). L'implementazione della propria libreria FP nell'assemblatore Z80 non è banale. Ovviamente, puoi usare le routine BASIC integrate, ma puoi anche semplicemente attenerti a BASIC.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top