Quando ho iniziato a studiare l'assembler avevo Olivetti M24 su processore 8086 e sul C64 usavo solo BASIC (al limite integrato con Simon Basic per qualche routine grafica). L'assembler 8086 non e' banalissimo ma la cosa che piu' mi infastidiva era quella di non poter gestire in modo nativo la matematica dei numeri float ....a meno che di non possedere un costosissimo coprocessore matematico (che e' stato integrato solo dalla serie x486)
Con sorpresa ho scoperto che usare i numeri a virgola mobile e fare conti su C64 e' incredibilmente banale anche in assembler.
Per prima cosa i numeri float hanno una struttura di 5 byte e sono nel formato esponenziale base 2 ...quindi qualcosa del tipo x.xxx 2^y
byte 1 : esponente : il valore dell'esponente e' nel formato exp-129 (quindi 2^0 avra' il valore 81, valore piu' bassi indicano esponenti negativi)
byte 2-5 : mantissa
Convertire da formato float decimale a float C64
per fare poca fatica conviene usare direttamente la conversione di C64
Per esempio si digiti da BASIC
NEW
X = 3.14159
IND = PEEK(71)+256*PEEK(72)
PRINT PEEK(IND)
PRINT PEEK(IND+2)
PRINT PEEK(IND+3)
PRINT PEEK(IND+4)
PRINT PEEK(IND+5)
quale e' il significato. Diciamo al BASIC di salvare il valore di float di pi greco in una variabile. Nelle locazioni a pagina zero 71 e 72 c'e' il puntato alla zona di memoria dove viene inserito effettivanemente il numero (gia' decodificato in formato C64). Nel mio caso l'indirizzo e' $805 (esadecimale) se sei aggiungono altre variabile si vedra' che il puntatore si aggiorna
La risposta al comando e'
$82 $49 $0F $CF $82
ovvero la traduzione in formato float C64
Per fare la riprova si puo' usare questo programma assembler in ACME
in pratica si popola la'accumulatore di float FAC con il valore di pi greco, si chiama il kernal per la conversione del valore in una stringa ($BDDD) e poi si mostra la stringa a schermo
-----------------------------------------------
Per la riconversione l'algoritmo (preso da qui) e' il seguente
Float
!source "./std.a"
!to "float.prg", cbm
!sl "float.map"
!cpu 6510
*=$1000
LDFAC = $bba2
!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}
+LoadFAC pi
MOVFA ; sposta FAC in ARG
;JSR $E264 ;COSENO NON UTILIZZATA
JSR $BDDD ;Convert FAC to zero-terminated string representation at memory addresses $0100-$010A.
LDY #0
loop: LDA $100,Y
BEQ done
JSR $FFD2
INY
BNE loop
done:
RTS
pi !by $82, $49, $0F, $CF, $82
-----------------------------------------------Per la riconversione l'algoritmo (preso da qui) e' il seguente
- Exponent: exp-128
- Mantissa: (m4 >= 128 ? -1 : +1) * ((m4 | 0x80) >> 8 + m3 >> 16 + m2 >> 24 + m1 >> 32)
La cosa interessante e' che da Assembler si possono chiamare anche le funzioni trigonometriche, le stesse condivise con BASIC, ma che risultano decisamente piu' veloci (vedi la chiama alla subroutine in $E264 corrispondente al coseno)
c'e' da osservare che la precisione dell'arrotondamento delle routine non e' ottimale (vedi questo link)
c'e' da osservare che la precisione dell'arrotondamento delle routine non e' ottimale (vedi questo link)