Magic Disk 64

home to index to html: MD9103-KURSE-CIA_KURS_TEIL_5-2.html
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.    
-------------------                     
...                                     
Valid HTML 4.0 Transitional Valid CSS!