Als Beispiel habe ich einmal die Zahl
2000000 in ein Langword umgewandelt:
1 ) 2000000/65536=30.51757813
1a) HI-Word=30 --> LO=30, HI=0
2 ) 2000000-30*65536=33920
2a) LO-Word=33920 --> LO=128, HI=132
Longword:
---------
0 30 132 128
Binär:
------
00000000 00011110 10000100 10000000
Soviel also hierzu. Nun können wir also
schon einmal beliebig lange 32-Bit-
Timerwerte berechnen. Für EVAL habe ich
übrigens nicht irgendeine Zahl genommen,
sondern schlichtweg die größte (also die
42 Milliarden von oben). Länger als 72
Minuten sollte eine zu testende Assem-
blerroutine sowieso nicht sein.
Kommen wir nun also zu der Programmie-
rung von EVAL. Hier möchte ich Ihnen
einmal den Anfang des Programms aufli-
sten:
-------------------
EVAL LDA #$7F Zunächst alle Inter-
STA CIA2+13 rupts sperren.
LDA #00 Und...
STA CIA2+14 Timer A und
STA CIA2+15 Timer B anhalten.
-------------------
LDA #$FF Nun den Maximalwert
STA CIA2+4 in Timer A
STA CIA2+5 und
STA CIA2+6 in Timer B
STA CIA2+7 schreiben.
-------------------
LDA #$41 Timer B soll Timer A
STA CIA2+15 zählen
LDA #$81 Timer A soll System-
STA CIA2+14 takte zählen.
-------------------
JSR $C000 Testprogramm aufrufen
-------------------
Im ersten Teil dieses Listings sperren
wir zunächst einmal alle Interruptquel-
len durch Löschen des ICR. Anschließend
werden durch das Schreiben von 0 in die
Control-Register der Timer selbige ge-
stoppt. Diese Maßnahmen sind nur für den
Fall gedacht, daß in diesen Timern ganz
gegen unsrer Erwartung doch etwas laufen
sollte. Zum korrekten Ablauf von EVAL
ist es absolut notwenidig, daß die Timer
stehen, da sonst die Testwerte
verfälscht würden.
Anschließend werden die Register TALO,
TAHI, TBLO, TBHI mit dem Wert 255 (=$FF)
geladen und so auf den Maximalwert
2↑32-1 gesetzt.
Im dritten Teil des Listings werden nun
die beiden Timer wieder gestartet. Hier-
bei MUß Timer B unbedingt VOR Timer A
aktiviert werden, da er zum Einen von
diesem abhängig ist, und deshalb zuerst
aktiv sein sollte (würde Timer A nämlich
unterlaufen BEVOR Timer B zählbereit
ist, wäre das Testergebnis ebenfalls
nicht in Ordnung), und zum Anderen müs-
sen wir so spät wie möglich den 32-Bit-
Timer starten, damit auch tatsächlich
die Taktzyklen der zu messenden Routine
gezählt werden und nicht etwa noch eini-
ge Taktzyklen die EVAL benötigt.
Im letzten Teil wird nun noch die zu
testende Routine aufgerufen, die ich
hier einmal bei $C000 (dez.49152) ange-
siedelt habe.
Jetzt ist also unser 32-Bit-Timer aktiv
und zählt schön brav von 4294967295
Richtung 0 hinab. Währenddessen läuft
unser Testprogramm ab und jeder Taktzy-
klus der dabei verstreicht wird mit-
gezählt.
Wird das Programm dann mittels "RTS"
beendet, so kehrt der Rechner wieder in
EVAL zurück. Nun müssen wir uns um die
weitere Behandlung der Timer kümmern.
Damit wieder keine unnötige Rechnerzeit
mitgezählt wird stoppen wir also
zunächst beide Timer:
-------------------
LDA #$80 Wert für "Timer-Stop"
STA CIA2+14 Timer A und
STA CIA2+15 Timer B anhalten.
-------------------
Da der unser 32-Bit-Timer nun also nur
während des Ablaufs des zu testenden
Programms lief, müsste nun in den Timer-
registern logischerweise haargenau die
Anzahl der verbrauchten Taktzyklen ste-
hen, jedoch in einem invertierten For-
mat. Das heißt, daß dadurch, daß der
Timer rückwärts lief, die Taktzyklenan-
zahl mit folgender Formel berechnet wer-
den muß:
(2↑32-1)-(Longword in Timerregistern)=
tatsächlich verbrauchte Taktzyklen.
Na aber holla, das könnte ja schwer wer-
den, die 4-Byte Werte voneinander zu
subtrahieren! Doch keine Panik, auch das
läßt sich ganz einfach lösen. Dadurch
nämlich, daß wir beim Start den absolu-
ten Maximalwert in die Timer geladen
hatten, können wir diese Umrechnung
durch schlichtes invertieren der einzel-
nen Bytes vornehmen. Dabei wird das so-
genannte Einerkomplement unserer Zahl
gebildet, was ebenfalls eine Art ist,
Bytes voneinander zu subtrahieren. Zum
Beweis möchte ich Ihnen hier einmal ein
Beipiel geben:
Wir hatten den Startwert $FF $FF $FF $FF
im Timer stehen. Eine Invertierung die-
ses Werts mittels des "EOR"-Befehls
ergäbe dann: $00 $00 $00 $00 - mit ande-
ren Worten, der Startwert war 0.
Angenommen, nun war der Wert, den wir
nach Ablauf eines Testprogramms in den
Timern vorfanden folgender:
$FF $FD $03 $AE. Dies entspricht dem
Dezimalwert 4294771630. Subrtrahieren
wir diesen Wert von 2↑32-1, so ergibt
sich folgendes Ergebnis: 195665. Das
wäre also die Anzahl der Taktzyklen, die
das aufgerufene Programm verbrauchte.
Nun wollen wir doch testweise einfach
einmal das Einerkomplement der Ergebnis-
zahl bilden (ebenfalls mittels "EOR"):
$FF $FD $03 $AE --> $00 $02 $FC $51.
Dieses Longword umgerechnet ergibt nun
aber ebenfalls die Zahl 195665 - "quod
erat demonstandum!"
Kommen wir nun also zum nächsten Teil
von EVAL, dem Retten der Timerwerte und
dem gleichzeitigen Umwandeln in die ab-
solute Zahl an Taktzyklen:
-------------------
LDY #03 Quellzähler initia-
lisieren.
LDX #00 Zielzähler initiali-
sieren.
LOOP1 LDA CIA2+4,Y Akku mit dem hinter-
sten Timerregister
laden
EOR #$FF Komplement bilden
STA $62,X und umgekehrt si-
chern.
INX Zielzähler +1.
DEY Quellzähler -1.
BPL LOOP1 Wenn noch nicht un-
tergelaufen, dann
wiederholen.
-------------------
Diese Schleife nimmt sich nun nacheinan-
der die CIA-Register 7,6,5 und 4 vor,
bildet ihr Komplement und speichert sie
umgekehrt in die Zeropageadressen $62,
$63, $64 und $65. Damit hätten wir dann
auch gleichzeitig das Problem gelöst,
daß die Bytes ja in der Reihenfolge TBHI
TBLO TAHI TALO aufeinander folgen müs-
sen, damit Sie einen Sinn ergeben. Das
hat aber auch noch einen anderen, wei-
taus wichtigeren Grund:
Ich habe die Adressen $62-$65 nämlich
nicht etwa willkülich als Zwischenspei-
cher gewählt, sondern in diesen Adressen
befinden sich nämlich die Mantissenbytes
des Floatingpoint-ACcumualtors (kurz:
"FAC") des 64ers. Damit wir unsere 32-
Bit-Zahl nämlich auch richtig in dezima-
ler Schreibweise ausgeben können, brau-
chen wir nämlich den FAC. Der FAC ist
ein bestimmter Speicherbereich in der
Zeropage der vom Betriebssystem dazu
genutzt wird, Fließkommazahlen aufzuneh-
men und mit ihnen herumzurechnen. Ebenso
gibt es auch eine Routine des Be-
triebssystems, mit deren Hilfe wir die
32-Bit-Zahl nachher in Dezimalschreib-
weise umwandeln, um sie ausgeben zu kön-
nen. Dazu jedoch später.
Zunächst einmal hätten wir also die ab-
solute Anzahl der vergangenen Taktzy-
klen, die zwischen Start und Stop des
Timers verstichen sind im FAC stehen.
Leider haben wir nun aber doch noch ei-
nige Taktzyklen, die durch EVAL ver-
braucht wurden, in unserer Rechnung. WO?
Werden Sie jetzt fragen, na ganz einfach
- schauen wir uns nocheinmal die Zeilen
vor und hinter dem Aufruf des Testpro-
gramms an:
...
LDA #$81 Timer A soll System-
STA CIA2+14 takte zählen.
-------------------
JSR $C000 Testprgramm aufrufen.
-------------------
LDA #$80 Wert für "Timer-Stop"
STA CIA2+14 Timer A und
STA CIA2+15 Timer B anhalten.
-------------------
...