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 PageDiese 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.BASWer 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
|