INT (ROM-Routine)
Anmerkung: Dieser Artikel beschreibt die numerische INT-Routine zur Umwandlung von Fließkommazahlen in Ganzzahlen im BASIC-ROM des C64.
Name: | INT | ||||||
Beschreibung: | Fließkommaregister FAC durch Abrunden in Ganzzahl wandeln | ||||||
Einsprungpunkt: | $BCCC / 48332 | ||||||
Übergebene Argumente: | |||||||
Sonstige: | FAC = Zu wandelnde Fließkommazahl | ||||||
Rückgabe-Werte: | |||||||
Sonstige: | FAC = Durch Abrunden in ganze Zahl umgewandelter Eingabeparameter |
Die ROM-Routine INT[1][2] wandelt den im Fließkommaregister FAC befindlichen Wert in eine Ganzzahl um, indem sie diesen falls nötig auf die nächstkleinere ganze Zahl abrundet. Ihr Einsprungpunkt ist in der Tabelle der BASIC-Funktionen an Adresse $A054 hinterlegt, so dass die Routine bei jeder Auswertung der Funktion INT vom BASIC-Interpreter aufgerufen wird.
INT verändert nicht nur den Inhalt des Fließkommaregisters FAC, sondern kopiert auch das niederwertigste Byte der Ganzzahldarstellung von FAC in die Speicherzelle 7/$07. Auf diesen Seiteneffekt verlassen sich die ROM-Routinen FPWR, FPWRT und EXP.
Algorithmus[Bearbeiten | Quelltext bearbeiten]
- INT prüft zunächst anhand des Exponenten, ob für die in FAC enthaltene Fließkommazahl überhaupt Nachkommastellen gespeichert sind. Hat der Exponent einschließlich Exzess den Wert 160 oder größer, so hat das niederwertigste Bit der Mantisse von FAC mindestens den Wert 20 = 1. In diesem Fall ist FAC bereits ganzzahlig und die Routine INT wird ohne weitere Rechenschritte verlassen.
- Ansonsten ruft INT zunächst die ROM-Routine QINT auf und wandelt damit den Wert von FAC in eine 32-Bit-Ganzzahl. Das niederwertigste Byte des Resultats wird in den Hilfspuffer an Adresse 7/$07 kopiert. Basierend auf diesem Pufferinhalt berechnen die ROM-Routine FPWR und FPWRT später das Vorzeichen beim Potenzieren negativer Zahlen, und die Routine EXP nutzt ihn für die Erkennung eines Überlaufs.
- Um diese Ganzzahl wieder in eine Fließkommazahl zurückzuverwandeln, setzt INT nun das Exponentenbyte auf 160/$A0, entsprechend einem Exponenten von 32 (ohne Exzess). Das niederwertigste Bit der Mantisse hat damit den Wert 20 = 1, und FAC kann als nicht-normalisierte Fließkommazahl aufgefasst werden. Allerdings befindet sich für negative Werte von FAC die Mantisse noch in der Zweierkomplement-Darstellung. INT springt daher zum Abschluss in die ROM-Routine FSUB an die Stelle, an der negative Resultate invertiert und dafür das Vorzeichen auf "negativ" gesetzt wird, bevor FAC normalisiert wird.
Laufzeitverhalten[Bearbeiten | Quelltext bearbeiten]
Falls der Wert von FAC betragsmäßig größer oder gleich 231 ist, so ist das Fließkommaregister bereits ganzzahlig. INT erkennt diesen Sonderfall und benötigt dann nur 20 Systemtakte. Ansonsten ist die Laufzeit von INT bestimmt durch die Zeit für die Umwandlung von FAC in eine 32-Bit-Ganzzahl, gegebenenfalls für die Invertierung und für die anschließende Normalisierung.
Der Algorithmus sowie das Laufzeitverhalten bei der Umwandlung in eine Ganzzahl sind ausführlich in der Beschreibung von QINT dokumentiert. INT benötigt, wie auch QINT, besonders lange für die Umwandlung betragsmäßig sehr kleiner Fließkommazahlen. Die Gesamt-Rechenzeit der ROM-Routine INT liegt für positive Werte von FAC zwischen 204 und 7579 Takten, für negative Werte zwischen 389 und 8726 Takten. Wird INT mit dem Wert FAC = 0 aufgerufen, so liegt die Laufzeit der Routine bei 250 Takten.
Ein Systemtakt entspricht auf dem Commodore 64 rund einer Mikrosekunde (μs). Im ungünstigsten Fall benötigt die QINT-Routine also für die Umwandlung fast 9 Millisekunden (ms).
Bugs[Bearbeiten | Quelltext bearbeiten]
Die ROM-Routine INT prüft zunächst anhand des Exponenten, ob die in FAC enthaltene Fließkommazahl möglicherweise bereits ganzzahlig ist. In diesem Sonderfall werden nicht nur alle weiteren Rechenschritte übersprungen, sondern auch das niederwertigste Byte der Mantisse wird nicht in den Hilfspuffer an Adresse 7/$07 umkopiert. Die auf INT aufbauenden Routinen FPWR und FPWRT stufen daher insbesondere alle ganzen Zahlen in den Intervallen ] -232; -231 ] und [ 231; 232 [ als "gerade" ein und liefern beim Potenzieren von negativen Zahlen mit einem ungeraden Exponenten aus diesen Bereichen fälschlicherweise ein positives Ergebnis:
Weblinks[Bearbeiten | Quelltext bearbeiten]
- Disassembly von INT/$BCCC auf All About Your 64
- CodeBase 64: Floating Point Math
- C64 BASIC & KERNAL ROM Disassembly von Michael Steil
- C64OS: Floating Point Math from BASIC