SCREENWATCH - Direkter Bildschirmzugriff? Nein danke!

Die gegenüber dem ST neuen Bildschirmauflösungen des TT haben ein ganz spezielles Problem aufgezeigt: Einige Programme greifen direkt auf den Bildschirmspeicher zu und umgehen somit das GEM. Dies kann zu Fehlern und Inkompatibilitäten führen. Solche Übeltäter können auf dem TT entlarvt werden.

Aber nicht nur TT-Anwender, sondern auch Besitzer eines ST haben mit Programmen zu kämpfen, die die Nutzung neuer Auflösungen durch direkte Zugriffe auf den Bildschirmspeicher verbauen. Schließlich gibt es für den ST inzwischen diverse Hardware-Lösungen, die es erlauben, auf dem SM 124 eine höhere Auflösung als 640x400 Punkte zu nutzen. Ärgerlich, wenn man feststellen muß, das ein Programm, für das eine höhere Auflösung von Vorteil wäre, nicht mit dem größeren Bildschirm zurechtkommt. Gerade bei Textverarbeitungen profitiert man von jeder Textzeile oder -spalte, die zusätzlich auf dem Bildschirm untergebracht werden kann.

Unsauber programmiert

Anders kann man Programme, die durch einen direkten Zugriff auf den Bildschirmspeicher die Nutzung neuer Auflösungen verhindern, nicht bezeichnen. Bereits seit einiger Zeit (spätestens seit der Ankündigung des TT) ist klar, daß Text- und Grafikausgaben möglichst nicht unter Umgehung des GEM erfolgen sollten. Einige Programme reagieren zwar auch ohne GEM-Nutzung sehr flexibel auf unterschiedliche Auflösungen, aber spätestens dann, wenn ein Bildschirm vorliegt, der nicht auf Bitmap-Basis arbeitet (z.B. ein grafikfähiges Terminal), führen eigene Ausgaberoutinen nicht mehr zum Ziel. Zwar sind solche Bildschirme für ST oder TT noch nicht aktuell, aber das kann sich ja noch ändern.

Sicherlich muß man bei konsequentem Einsatz des GEM einen gewissen Geschwindigkeitsverlust bei der Grafikdarstellung in Kauf nehmen, aber werden AES und VDI optimal programmiert, sind durchaus hohe Geschwindigkeiten möglich. Gerade bei den Rechnern der neueren Generation, also beim Mega STE und TT, werden auch bei ausschließlicher Nutzung des GEM gute Zeiten bei der Bildschirmausgabe erreicht.

Nicht todernst

Zwar kann man direkte Zugriffe auf den Bildschirmspeicher nicht sinnvoll verhindern, aber Besitzer des TT haben immerhin die Möglichkeit, Programme, die das GEM durch solche Methoden umgehen zu entlarven. Wenn auch diese Anwendung eine nicht ganz ernste ist, gibt sie uns doch eine gute Gelegenheit, neue Seiten der PMMU des 68030 kennenzulernen: Deskriptoren im Langformat und den Zugriffsschutz für einzelne Speicherseiten.

Lange Deskriptoren

In den letzten Ausgaben der ST-Computer haben uns in Verbindung mit der MMU ausschließlich Deskriptoren mit einer Länge von 32 Bits beschäftigt. Nun gibt es neben diesem Kurzformat jedoch auch noch ein Deskriptor-Langformat, das gleich 64 Bits in Anspruch nimmt. Eines der neu hinzugekommenen Bits erlaubt es, einzelne Speicherseiten gezielt gegen einen Zugriff aus dem User-Modus zu schützen. Es handelt sich um das S-Bit (Supervisor Only).

Der Aufbau dieser für uns neuen Deskriptoren wird in Bild 1 dem bereits bekannten kurzen Format gegen übergestellt. Mit welchem Deskriptor-Typ die MMU zu rechnen hat, wird im CRP-Register (CPU Root Pointer) anhand des DT-Feldes (Descriptor Type) definiert.

Bildschirmschutz

Wie kann man einen Schreibschutz für den Bildschirmspeicher nun konkret verwirklichen? Der naheliegende Gedanke, den Bildschirm einfach in einem schreibgeschützten Speicherbereich anzusiedeln, läßt sich zwar (bereits mit kurzen Deskriptoren) verwirklichen, ist allerdings wenig günstig. Fehler beim Schreiben auf den Bildschirm würden dann nämlich auch vom Betriebssystem verursacht, da ja das Ansprechen des Bildschirmspeichers unter keinen Umständen erlaubt wäre. Ausgaben, die über das GEM gemacht werden, sollten jedoch nicht irgendwelchen Einschränkungen unterliegen.

Da ist es schon besser, den Bildschirm nicht global zu schützen, sondern lediglich Zugriffe aus dem User-Modus abzufangen und diese durch einen Signalton anzuzeigen. Dabei setze ich voraus, daß ein Anwenderprogramm in der Regel im User-Modus läuft. Ist dies nicht der Fall, erfolgen Zugriffe auf den Bildschirm-Speicher also im Supervisor-Modus, läßt sich natürlich durch den hier in Betracht gezogenen Schutzmechanismus nichts erreichen.

Bild 1: Deskriptoren
Bild 2: CRP und SSR

The same procedure

Wie bereits in [ 1 ] erläutert, erlaubt es der RTE Befehl, eine Operation, die zu einer Exception geführt hat, nochmals auszuführen. Für SCREEN-WATCH genügt dies alleine aber nicht, denn es würde natürlich sofort wieder ein Busfehler resultieren. Anders sieht es jedoch aus, wenn der nächste Befehl, also nur der Zugriff auf den Bildschirm, ausnahmsweise im Supervisor-Modus erfolgen könnte. Der 68030 bietet in der Tat die Möglichkeit, die Zugriffsbedingungen für die Wiederholung des Befehls, der zum Busfehler führte, zu ändern. Alle Daten, die hierzu benötigt werden, befinden sich während der Exception auf dem Interrupt-Stack [2]. An Offset 10 relativ zum Stackpointer befindet sich das Special Status-Register, das Aussagen über den internen Zustand des Prozessors zum Zeitpunkt des Fehlers macht.

Spezialitäten

Um solche handelt es sich bei den Bits des Special Status-Registers (Bild 2), die Aussagen über einen Buszyklus machen, bei dem ein Busfehler auftrat:

RR (Re-Run): Ist dieses Bit gesetzt, was der Default-Zustand ist, wird bei der Ausführung von RTE der letzte Buszyklus wiederholt.

IF (Instruction Fetch): Der Fehler trat beim Holen des nächsten Befehls auf.

DF (Data Fetch): Der Busfehler wurde beim Holen eines Datenwortes erzeugt.

RM (Read/Modify/Write): Der Fehler entstand während eines Read/Modify/Write-Zyklus’.

HB (High Byte/Low Byte): Bei gesetztem Bit trat der Busfehler auf, als auf das High-Byte eines Wortes zugegriffen wurde.

BY (Byte/Word): Ist dieses Bit 1, wurde beim Auftreten des Fehlers auf ein Byte zugegriffen, andernfalls handelte es sich um einen Wortzugriff.

RW (Read/Write): Der Fehler wurde während eines Lesezugriffs hervorgerufen, wenn das RW-Bit gesetzt ist.

FC2-FC0 (Function Code Bits): Diese Bits machen eine nähere Aussage über die Art des Zugriffs (s.u.)

Alle weiteren Bits des Special Status-Registers sind nicht belegt.

User oder Supervisor?

Es ist programmgesteuert möglich, die Bedingungen, unter denen der nächste Datenoder Adreßzugriff erfolgen soll, nahezu beliebig zu verändern. Da sich alle Angaben über den internen Zustand des Prozessors auf dem Stack befinden, sind weitreichende Manipulationen denkbar (und erlaubt!). In unserem Fall sind lediglich die Function Code Bits FC2-FC0 von Bedeutung, die Aussagen über Art und Adreßraum des Zugriffs machen:

FC2-0 Adreßraum
000 reserviert
001 User-Daten
010 User-Programm
011 reserviert
100 reserviert
101 Supervisor-Daten
110 Supervisor-Programm
111 CPU-Adreßraum

Es läßt sich leicht erkennen, daß FC2 bestimmt, ob ein Zugriff unter den Bedingungen des User- oder Supervisor-Modus’ stattfindet. Wird das entsprechende Bit im Statuswort gesetzt, gelten für die Wiederholung des Befehls durch RTE die Zugriffsrechte des Supervisor-Modus’. SCREENWATCH wird also nur für den nächsten Befehl keine Busfehler-Meldung erhalten. Und genau das wollten wir ja erreichen.

Langgemacht

Da ein Zugriffsschutz speziell für den User-Modus nur mit langen Seitendeskriptoren zu realisieren ist, besteht eine der Hauptaufgaben von SCREENWATCH darin, die kurzen Deskriptoren der Standardtabelle in das Langformat umzuwandeln.

SCREENWATCH versucht bei der Konvertierung so vorzugehen, daß bereits geänderte Deskriptoren ihre Werte behalten. So wird eine möglichst hohe Kompatibilität zu anderen Programmen erzielt, falls diese ebenfalls Gebrauch von der MMU machen. Die in den kurzen Deskriptoren enthaltenen Adressen weiterer Deskriptoren oder Speicherseiten werden vom Programm von den Deskriptor-Flags isoliert und anschließend zu langen Deskriptoren zusammengesetzt.

Nicht erwischt

SCREENWATCH ist in der Lage, die meisten unsauberen Zugriffe auf den Bildschirm zu erkennen. Ausnahmen stellen, wie bereits angesprochen, Programme dar, die aus dem Supervisor-Modus heraus auf den Bildschirm zugreifen. In solchen Fällen ist der Schreibschutz auf den Bildschirmspeicher erlaubt, da sonst das GEM ja keine Möglichkeit hätte, Ausgaben ohne Warnmeldung vorzunehmen.

Ebenfalls nicht erkannt werden Zugriffe, die vorgenommen werden, nachdem ein Programm den Bildschirmspeicher an eine neue RAM-Adresse gelegt hat. SCREENWATCH kann schließlich nur den Speicherbereich schützen, in den das Programm während der Initialisierung den neuen Bildschirm legt. Wird diese Adresse durch nachfolgende Programme geändert, wird der Schutzmechanismus deaktiviert.

MMU-Schlamassel

Bei der Verwendung von SCREENWATCH ist zu beachten, daß möglichst keine anderen Programme installiert werden sollten, die ebenfalls Gebrauch von der MMU machen. Ganz allgemein kann man jedoch davon ausgehen, daß es Schwierigkeiten gibt, wenn mehr als ein Programm die MMU für sich zu beanspruchen versucht. Ferner darf kein Programm vor SCREENWATCH gestartet worden sein, das eine eigene Busfehler-Routine einrichtet, die nicht den in [1] aufgestellten Kriterien genügt.

SCREENWATCH geht davon aus, daß die Deskriptor-Tabellen beim Programmstart so vorliegen, wie es beim Atari TT der Normalzustand ist. Leider liegt zu diesen Tabellen noch keine offizielle Dokumentation von Atari vor. Dennoch machen bereits einige Programme von der Tatsache Gebrauch, daß TOS die Deskriptoren im Speicherbereich von $0700 bis $0800 anlegt. Bleibt zu hoffen, daß demnächst Informationen erhältlich sind, die eine legale Nutzung dieser Tabellen zulassen. Leider lassen solche Unterlagen gewöhnlich lange auf sich warten ...

US

Literatur:

[1] „Virtuelle Speicherverwaltung - Eine Fallstudie“, ST-Computer 6/91

[2] Steve Williams, „68030 Assembly Language Reference“, Addison-Wesley Publishing Company Inc., ISBN 0-201-08876-2

********************************
*                              *
* SCREENWATCH V1.0             *
*                              *
* Überwachung des Bildschirms  *
*                              *
* per MMU                      *
*                              *
* by Uwe Seimet                *
* (c) 1991 MAXON Computer      *
********************************

GEMDOS  = 1 
CCONWS  = 9 
SUPER   = 32 
PTERMRES= 49 
MXALLOC = 68 
MSHRINK = 74

BCONOUT = 3 
BIOS    = 13

XBIOS   = 14 
SETSCREEN=5

_v_bas_ad= $44e 
_p_cookies= $5a0

magic = "SCRW"                  ;für XBRA


        text

        move.l 4(sp),a0 ;Pointer auf
                                ;Basepage
        move.l 12(a0),a6 
        add.l 28(a0),a6 
        lea $100(a6),a6 
        pea (a6)
        pea (a0) clr -(sp)
        move #MSHRINK,-(sp)     ;Restspeicher
        trap #GEMDOS            ;freigeben
        lea 12(sp),sp 
        tst.l d0
        bne quit                ;Fehler-

        clr.l -(sp)
        move #SUPER,-(sp)       ;Supervisor
        trap #GEMDOS            ;Modus
        addq.l #6,sp
        move.l d0,d7            ;SSP merken

        move.l $08,a0
        cmp.l #magic,-8(a0)     ;bereits
        beq exit                ;installiert-

        lea sterr(pc),a5 
        move.l _p_cookies,d0
        beq error               ;kein cookie jar
        move.l d0,a0 
nomch:  movem.l (a0)+,d0-d1
        tst.l d0                ;Ende des
        beq error               ;cookie jar-
        cmp.l #"_MCH",d0        ;Computertyp?
        bne nomch               ;nein-
        swap dl
        subq.l #2,d1            ;TT?
        bne error               ;nein-

        lea memerr(pc),a5
        clr -(sp)               ;nur ST-RAM
        pea 5*32768+32767       ;Platz für 5 Pages
        move #MXALLOC,-(sp)     ;anfordern
        trap #GEMDOS 
        addq.l #8,sp 
        add.l #32767,d0
        and #$8000,d0           ;Bildschirmstart
                                ;auf Page-Anfang 
        move.l d0,d5            ;neue Bildschirm-
                                ;Adresse
        beq error               ;kein Speicher-

        move.l _v_bas_ad,a0 
        move.l d5,a1 
        move #38399,d0 
scrcpy: move.l (a0)+,(a1)+      ;Bildschirm
        dbra d0,scrcpy          ;kopieren

        move.l #table+15,d6     ;Deskriptortabelle 
        and #$fff0,d6           ;auf 16 Byte-Grenze

        pmove crp,crpsav        ;alter CRP
        move.l crpsav+4,a0      ;Pointer auf
                                ;alte Tabelle 
        move.l d6,crpreg+4      ;für neuen CRP

        moveq #63,d0            ;64 Deskriptoren
        move.l d6,a1            ;neue Tabelle
        move.l crpsav+4,a2      ;zeigt auf
        lea 256(a2),a2          ;Tabellenende
copy:   move.l (a0)+,d1         ;Kurzformat
        move.l d1,d2
        and.l #$ff,d1           ;Adresse ausblenden 
        btst #1,d1              ;Seiten-Deskriptor? 
        beq cont                ;ja
        and #$0f,d1             ;Adresse ausblenden 
cont:   or.l #$8000fc01,d1      ;ergibt Langformat
        move.l  d1,(a1)+
        btst #1,d1              ;Seiten-
        beq next                ;Deskriptor-
        move.l d2,d1 
        clr.b d1
        cmp.l a2,d1             ;außerhalb
        bcc next0               ;der Tabelle
        and #$fff0,d2 
        sub.l crpsav+4,d2
        add.l d2,d2             ;neue Adresse
        add.l d6,d2             ;berechnen
        bra next0 
next:   clr.b d2
next0:  move.l d2,(a1)+
        dbra d0,copy

        move.l a1,a0 
        moveq #3,d0
        lea (384,d6.l),a2       ;Tabellen-
dloop:  move.l #$8000fc03,(a2)+ ;Deskriptoren
        move.l a0,(a2)+         ;für ST-RAM
        lea 256(a0),a0 
        dbra d0,dloop

        moveq #0,d1 
        moveq #127,d0 
init:   move.l #$0000fc01,(a1)+
        move.l d1,(a1)+ 
        add.l #$00008000,d1 
        dbra d0,init

        move.l $08,o_bus 
        move.l #buserr,$08

        pmove crpreg,crp        ;neuer Rootpointer 
                                ;(ATC wird gelöscht!) 
        ptestr #7,(d5.1),#7,a0  ;Adresse der 
                                ;Bildschirm-/Deskriptoren 
        bset #0,2(a0)           ;Supervisor-Only
        bset #0,10(a0)          ;für 5 Pages
        bset #0,18(a0)          ;(=Videoram)
        bset #0,26(a0) 
        bset #0,34(a0)

        move.l d7,-(sp)
        move #SUPER,-(sp)       ;Rückkehr in
        trap #GEMDOS            ;User-Modus
        addq.l #6,sp

        move #-1,-(sp)
        move.l d5,-(sp)         ;neue Adresse
        move.l d5,-(sp)         ;für Bildschirm
        move #SETSCREEN,-(sp) 
        trap #XBIOS 
        lea 12 (sp),sp
        pea message(pc)         ;SCREENWATCH
        move #CCONWS,-(sp)      ;ist
        trap #GEMDOS            ;installiert
        addq.l #6,sp 
        clr -(sp)
        pea (a6)                ;Programmlänge
        move #PTERMRES,-(sp)    ;Programm
        trap #GEMDOS            ;resident
                                ;halten

error:
        pea (a5)                ;Fehlermeldung
        move #CCONWS,-(sp)      ;ausgeben
        trap #GEMDOS 
        addq.l #6,sp
        pea inserr(pc)          ;nicht installiert 
        move #CCONWS,-(sp) 
        trap #GEMDOS 
        addq.l #6,sp 
exit:   move.l d7,-(sp)
        move #SUPER,-(sp)       ;zurück in
        trap #GEMDOS            ;User-Modus
        addq.l #6,sp 
quit:   clr -(sp)
        trap #GEMDOS

        dc.l "XBRA" 
        dc.l magic 
o_bus:  dc.l 0

buserr:
        ptestr #3,([16,sp]),#7
        pmove psr,status        ;Adresse testen
        btst #5,status          ;Supervisor
        bne wrterr              ;Only-
oldbus: move.l o_bus(pc),-(sp) 
        rts

wrterr:
        movem.l a0-a2/d0-d2,-(sp) 
        move #7,-(sp)           ;BEL
        move #2,-(sp) 
        move #BCONOUT,-(sp) 
        trap #BIOS              ;Alarmton ausgeben 
        addq.l #6,sp
        movem.l (sp)+,a0-a2/d0-d2 
        bset #2,11(sp)          ;Befehl im
        rte                     ;Supervisor-Modus
                                ;wiederholen

crpreg: dc.l $80000003          ;alle Deskriptoren 
        dc.l $00000000          ;im Langformat

message:dc.b $0d,$0a,"SCREENWATCH V1.0 " 
        dc.b "installiert",$0d,$0a 
        dc.b "1991 by Uwe Seimet",$0d,$0a,0

*Diverse Fehlermeldungen

sterr:  dc.b $0d,$0a,"SCREENWATCH läuft nur "
        dc.b "auf einem TT!",0

memerr: dc.b $0d,$0a,"Zu wenig Speicher!",0

inserr: dc.b $0d,$0a,"SCREENWATCH V1.0 "
        dc.b "nicht installiert",$0d,$0a,0

        bss

crpsav: ds.l 2

status: ds.w 1                  ;für MMU-Status

table:  ds.b 512+1024+15        ;Deskriptortabelle

Uwe Seimet
Aus: ST-Computer 07 / 1991, Seite 174

Links

Copyright-Bestimmungen: siehe Über diese Seite