| 
Das Betriebssystem CP/M Plus besteht wie so ziemlich alle Systeme aus vielen
Tabellen. Wer diese Systembereiche kennt und weiß, welche Informationen
da verborgen sind, versteht das System besser und kann es dann auch effizienter
einsetzen. Wir wollen uns deshalb heute mit der sog. »Zero Page«
(= »Nullseite«) beschäftigen.
 Wenn der Mikroprozessor Z80A in unserer Joyce aktiv ist, dann kann er auf maximal 64 KB (= 65536 Bytes) zugreifen. Das Betriebssystem CP/M Plus unterteilt diesen Bereich in »Pages« (= »Seiten«), die jeweils 256 Bytes umfassen. Warum gerade eine so krumme Zahl wie 256? Nun, als hexadezimale Zahl ist 256 = 100h, also gar nicht so krumm... Wenn wir auf unserer Joyce ein Programm aufgerufen haben, dann ist der dem Anwenderprogramm zugängliche Speicher wie folgt belegt: 
        ________________
        FFFFh = 65535        oberes Ende
        ...
        FC00h = 64512        Beginn des BIOS
        ...
        F606h = 62982        Beginn des BDOS
        ...
        C000h = 49152        Beginn Common Area
        ...
        0100h = 00256        Programmanfang
        ...
        0080h = 00128        Beginn DMA
        ...
        0000h = 00000        Beginn Zero Page
Diese Nullseite ist immer vorhanden und darf von unserem Programm nie
überschrieben werden; ein wohl erzogenes Anwenderprogramm beginnt deshalb
stets oberhalb von 0100h, also nach der Nullseite. Ein Anwenderprogramm
darf den gesamten Speicher ab der Nullseite bis zum Beginn des BDOS belegen.
Ab hier ist für Anwenderprogramme absolute Sperrzone, da ab dieser Adresse
die Einsprungspunkte in die Systemroutinen liegen.
Ganz am Anfang der Nullseite befinden sich zwei Sprungbefehle; der erste springt direkt in die BIOS-Routine »Warmstart«; damit wird nämlich ein aktuelles Programm beendet und der CCP (= »Command Console Processor«) meldet sich wieder und erwartet die Eingabe eines neuen CP/M-Befehles. Dies können auch Basic-Coder ausnutzen: Anstatt »SYSTEM« können wir auch das Basic-Programm mit »warmstart=0:CALL warmstart« beenden. Der zweite Sprungbefehl steht ab der Adresse »5« und führt direkt in die BDOS-Funktion mit der Nummer »0«, mit der ebenfalls ein Programm ordentlich beendet werden kann. Aber in der Nullseite stehen noch viel mehr Informationen, wie folgende Tabelle zeigt: Von Bis Bedeutung 0001h 0003h Einsprungsadresse ins BIOS 0006h 0007h Beginn des BDOS 0008h 003Ah Restartvektoren 003Bh 004Fh unbenutzt 0050h 0050h Nummer des Laufwerkes (1..16) 0051h 0052h Adresse des ersten Paßwortes 0053h 0053h Länge des ersten Paßwortes 0054h 0055h Adresse des zweiten Paßwortes 0056h 0056h Länge des zweiten Paßwortes 0057h 005bh unbenutzt 005Ch 007Bh Dateileitblock der ersten Datei 006Ch 007Bh Dateileitblock der zweiten Datei 007Ch 007Ch Satzzähler für die erste Datei 007Dh 007Fh Satzposition der ersten Datei 0080h 00FFh Standard-Ein-/Ausgabe-BereichDa einige sich vielleicht unter manchen Begriffen nichts vorstellen können, wollen wir etwas näher darauf eingehen: 
 Diese Restart-Befehle besitzen aber einen großen Nachteil: sie springen an feste Adressen. So verzweigt z.b. »RST 0h« zur Adresse »0000h«, »RST 8h« zur Adresse »0008h« etc. Es stehen deshalb nur kümmerliche acht Bytes für die Behandlung einer Unterbrechung zur Verfügung. Der Z80-Prozessor wurde deshalb erweitert: man verpaßte ihm gleich drei verschiedene Unterbrechungsmodi: »IM 0«, »IM 1« und »IM 2«. Der »Interrupt Modus 0« (= IM 0) funktioniert wie beim 8080. Unsere Joyce arbeitet aber im Modus 1: Immer wenn eine Unterbrechung eintritt (z.b. durch Tastatureingabe), dann wird der Befehl »RST 38H« ausgeführt. An dieser Stelle muß nun in die Analyse-Routine verzweigt werden, denn das Betriebssystem muß ja schließlich feststellen, welcher Peripherie-Baustein sich da gemeldet hat. In der Nullseite seht also an der Adresse 0038h ein Sprungbefehl in die Unterbrechungsbehandlung des Betriebssystems. Da der Timer alle 1/50 Sekunden sich auch hier meldet, können wir uns an dieser Stelle »vordrängeln« und eigene »Interrupt-gesteuerte« Routinen einbauen (z.b. eine permanente Zeitanzeige). Die anderen RST-Adressen ab 0008h sind bei der Joyce unbenutzt. Wir können hier also kleine Routinen unterbringen. Das ist vor allem für Basic-Coder von Interesse, weil wir dann unsere (kleinen) Assemblerprogramme mittels POKE in die Nullseite schreiben können. Als Beispiele sind zwei kleine Basic-Programme abgedruckt: 
 
 
  | 
LISTING >HARDCOPY<, REMARK = >REM<.
100        REM HARDCOPY.BAS: ruft mittels XBIOS die Hardcopy-Routine auf
110        DEFINT a-z
120        REM Maschinencode ab Adresse &H0016 installieren
130        hardcopy=3D16
140        RESTORE 210
150        FOR offset=3D0 TO 5
160        .. READ code.byte$
170        .. code=3DVAL("&H"+code.byte$)
180        .. POKE hardcopy+offset,code
190        NEXT offset
200        PRINT "Hardcopy-Routine ist installiert - Aufruf: CALL hardcopy"
210        REM Maschinencode
220        DATA CD,5A,FC...... :REM call XBios
230        DATA 72,14......... :REM defw KM_PTR_COPY
240        DATA C9............ :REM ret
250        REM Ende Maschinencode
260        REM
270        REM Hardcopy von Basic aus aufrufen
280        PRINT "Test: Hardcopy von Basic aus aufrufen"
290        PRINT "Papier in Drucker einlegen..."
300        CALL hardcopy
310        PRINT "Test beendet"
320        REM
330        REM EOF: HARDCOPY.BAS
 
LISTING >PRTMENU <, REMARK =>REM<.
100        REM PRTMENU.BAS: ruft mittels XBIOS das Drucker-Menü auf
110        DEFINT a-z
120        REM Maschinencode ab Adresse &H0008 installieren
130        prtmenu=3D8
140        RESTORE 220
150        FOR offset=3D0 TO 5
160        .. READ code.byte$
170        .. code=3DVAL("&H"+code.byte$)
180        .. POKE prtmenu+offset,code
190        NEXT offset
200        PRINT "Printer-Menü-Routine ist installiert - Aufruf: CALL prtmenu"
220        REM Maschinencode
230        DATA CD,5A,FC...... :REM call XBios
240        DATA 6F,14......... :REM defw KM_PTR_MODE
250        DATA C9............ :REM ret
260        REM Ende Maschinencode
270        REM
280        REM Printer-Menü von Basic aus aufrufen
290        PRINT "Test: Printer-Menü von Basic aus aufrufen"
300        PRINT "Druckereinstellung mit EXIT beenden..."
310        CALL prtmenu
320        PRINT "Test beendet"
330        REM
340        REM EOF: PRTMENU.BAS
 
 
 
 Für Basic-Coder ist dieser DMA-Bereich besonders interessant, weil das Mallard-Basic selbst einen eigenen Ein-/Ausgabebereich reserviert. Der Standard-DMA-Bereich von 128 bis 255 wird nicht verwendet und steht uns deshalb für etwaige Assemblerroutinen zur Verfügung. Als Beispiel ist das Programm FASTWRIT.BAS abgedruckt, mit dem die PRINT-Ausgabe um etwa 25 % beschleunigt wird. 
 
LISTING >FASTWRIT<, REMARK =>REM<.
100        REM FASTWRIT.BAS: mittels XBIOS PRINT um 25 % beschleunigen
110        DEFINT a-z
120        REM Maschinencode ab Adresse &H0080 installieren
130        fastwrit=3D128
140        RESTORE 210
150        FOR offset=3D0 TO 5
160        .. READ code.byte$
170        .. code=3DVAL("&H"+code.byte$)
180        .. POKE fastwrit+offset,code
190        NEXT offset
200        PRINT "FastWrit-Routine ist installiert - Aufruf: CALL fastwrit"
210        REM Maschinencode
220        DATA CD,5A,FC...... :REM call XBios
230        DATA 48,05......... :REM defw TE_TEXT_OUTPUT
240        DATA C9............ :REM ret
250        REM Ende Maschinencode
260        REM
270        REM schnelle PRINT-Ausgabe installieren
280        OPTION PRINT=3Dfastwrit
290        PRINT CHR$(27)"E"CHR$(27)"H"
300        FOR i=3D1 TO 12
310        .. PRINT SPACE$(i*3);"FASTWRIT: schnelle PRINT-Ausgabe ist installiert"
320        NEXT i
330        OPTION PRINT
340        FOR i=3D12 TO 1 STEP -1
350        . PRINT SPACE$(i*3);"schnelle PRINT-Ausgabe ist wieder abgeschaltet"
360        NEXT i
370        PRINT "Test beendet"
380        REM
390        REM EOF: FASTWRIT.BAS
Wer nun selbst die Nullseite analysieren möchte, für den wurde das
Pascal Programm ZEROPAGE.PAS geschrieben. Es gibt in aufbereiteter Form
die wichtigsten Informationen in der Nullseite aus. Wer z.B.
»ZEROPAGE A:EINGABE.DAT;PASS1 B:AUSGABE.DAT;PASS2« startet, kann dann leicht
herausfinden, wo das CP/M Plus die angegebenen Paßwörter unterbringt.
Auf der PD-Diskette befindet sich noch ein weiteres Programm BIOSADDR.PAS, das die Adresse der verschiedenen BIOS-Routinen auflistet  das ist aber vielleicht Stoff für einen weiteren Artikel... 
DangSoft
 
 |