VGA - Bildschirm löschen



  • mein vorschlag:

    mov di, 0B8000h
    
    mov cx, 07FFh ; (0B8FFFh - 0B8000h)/2
    
    starte_löschen:
    add di, 02h
    mov byte [es:di],' '
    loop start_löschen
    
    ...
    

    habs net überprüft, also weiß net obs funzt...

    .MamboKurt



  • Hallo Leute, wie soll denn bitte in das Register di (16 Bit) der Wert b8000h (32 Bit) passen?



  • das funktioniert.....



  • Hallo,

    da ich bisher nur im real-Mode programmierte, würde ich es so machen.

    Der Textbildschirm steht im real-Mode bei 0b000:8000

    mov ax,0b000h   ;Segmentadresse des Textbildschirms
         mov es,ax       ;nach Segmentregister ES
         mov di,08000h   ;Register DI auf den Anfang des Textbildschirms 
         mov ax,aazz     ;aa = Attribut des Zeichens zz = Zeichen (zum löschen 20h)
         mov cx,0fffh
         rep stosw       ;Schreibt 0xfff(Counter CX)Words in AX   
                         ;nach ES:DI, DI wird nach jedem schreiben um 2 erhöht
                         ;Postincrement
    

    Wie gesagt, das ganze im real Mode, mich würde allerdings interessieren
    wie man mit dem Befehl stosw im protected Mode umgeht.



  • .....das kann gar nicht funkltionieren!



  • (war auf post vom MamboKurt bezogen)



  • dann halt so:

    mov ax,0B000h
    mov es,ax
    mov di,08000h
    
    mov cx, 07FFh ; (0B8FFFh - 0B8000h)/2
    
    starte_löschen:
    add di, 02h
    mov byte [es:di],' '
    loop start_löschen
    

    und wenns immer noc net passt, dann is mir auch wurscht

    .MamboKurt



  • Passt es denn?



  • hermes schrieb:

    Der Textbildschirm steht im real-Mode bei 0b000:8000

    Jo, = B800:0000 (IMHO ueblicher).

    hermes schrieb:

    Wie gesagt, das ganze im real Mode, mich würde allerdings interessieren
    wie man mit dem Befehl stosw im protected Mode umgeht.

    Bleibt im Grunde alles beim Alten. 😉 Einziger Unterschied: Die Adressierung funktioniert anders. Praktisch musst du nur statt einer direkten Segmentadresse einen Selector nach ES laden - ueber den dazugehoerigen Descriptor wird dann adressiert.
    Weitere Infos zur Adressierung im PM gibt's hier:
    C/C++ Forum :: FAQ - Assembler :: Protected Mode / MMX 🙂

    BTW:
    Wie kommst du auf FFF im Counter? 😃



  • Jo, = B800:0000

    Ach ja stimmt, hatte da noch irgendwas mit 8xx im Kopf.
    Müsste mal wieder mehr Assembler programmieren.

    Wie kommst du auf FFF im Counter?

    Blödsinn, Textbildschirm 80*25 = 07d0h



  • Nochmal zu Speicheradressierung im Protected Mode.

    Ich verstehe das ganze so, im Segmentregister befindet sich
    ein bis zu 13 Bit grosser Wert sowie eine Kennung ob es sich um eine globale oder locale Deskriptortabelle handelt.
    Der 13Bit-Offset*8 + Basis des GTDR oder LTDR ist dann der Index auf den Segmentdeskriptor in dem sich die Basisadresse (4Byte) des Speicherobjects sowie das Ende (4Byte) des Objects befindet.
    Wenn ich ein mit dem C++ Builder erstelltes C++ Programm Debuge(CPU asm) haben DS,SS sowie ES den Gleichen Wert. Nur CS hat einen anderen.
    Befinden sich nun die Daten sowie der Stack im gleichen Seicherobject
    der Code aber in einem anderen?



  • Moin hermes,

    soweit mir bekannt ist, liegen Daten, Stack und Code eines Prozesses im selben Segment. Das CS einen anderen Wert hat als die anderen Segmentregister, liegt an der Benutzung eines sogenannten Alias. D.h. hinter dem Deskriptor, auf den CS zeigt, verbirgt sich dasselbe Segment. Es hat nur einen anderen "Namen".

    Ciao...



  • @Kal El:
    Jo, und zwar deshalb, weil der Deskriptor auf den CS zeigt logischerweise executable geflagged sein muss (Code-Deskriptor - ueber diesen Deskriptor hat man dann hoechstens noch Leserechte), waehrend die Uebrigen Segmentregister auf Datendeskriptoren ohne Ausfuehrungsrechte zeigen (dafuer koennen die dann auch r/w sein).

    hermes schrieb:

    Ich verstehe das ganze so, im Segmentregister befindet sich
    ein bis zu 13 Bit grosser Wert sowie eine Kennung ob es sich um eine globale oder locale Deskriptortabelle handelt.

    Jo, der Indexteil des Selektors ist 13Bit gross (von Bit3-15).
    Neben dem von dir angesprochenen TI-Bit enthaelt der Selektor aber in Bit0 und 1 das sog. RPL(Request Privilege Level)-Feld. Das gibt praktisch die Privilegstufe des Selektors an, mit der auf einen Deskriptor zugegriffen wird.
    Die Adressierung ueber einen bestimmten Deskriptor funktioniert schliesslich nur, wenn das RPL des entsprechenden Selektors vom Wert her groesser oder gleich dem D(eskriptor)PL ist.

    Im Deskriptor von CS heisst das RPL uebrigens CPL(Current Privilege Level).
    Das RPL in den Datendeskriptoren darf vom Wert her nicht niedriger als die CPL sein.

    hermes schrieb:

    Der 13Bit-Offset*8 + Basis des GTDR oder LTDR ist dann der Index auf den Segmentdeskriptor in dem sich die Basisadresse (4Byte) des Speicherobjects sowie das Ende (4Byte) des Objects befindet.

    Jo, so laesst sich die Adresse des gerade gewaehlten Deskriptors wohl berechnen.
    Der Deskriptor enthaelt aber noch ein bissel mehr, als nur Segmentbasis und Limit (groesse des adressierbaren Datenbereichs - nicht "das Ende"). 😉
    Die Segmentbasis belegt 4Byte im Deskriptor, das Limit belegt 2,5Byte - der Rest geht fuer weitere Flags (DPL, Type usw.) drauf.



  • Jetzt nochmal zu dem Anfangsproblem, ein Zeichen in den Textbildschirm zu
    schreiben.
    Ich versuche es mit einem Consolenprogramm
    Die Adresse des Textbildschirms im Real Mode 0B800:0 - 0b800:07d0
    was einer physischen Adresse von 0B8000 - 0B87d0 entspricht.
    Da ich im protectec Mode nur über den Deskriptor auf die Daten zugreifen
    kann, oder?, muss doch zuerst ein Deskriptor für dieses Speicherobject
    existieren.

    int main(int argc, char* argv[])
    {
    	asm
         {
              es -> Zeiger auf Deskriptor für Speicherobject(0B8000 - 0B87d0)
              mov edi,0
              mov ax,8031h
              stosw
    
         }
    	return 0;
    }
    

    Aber das anlegen eines Deskriptors ist doch nur dem Betriebssystem vorbehalten.

    Und muss ich mir eine Zugriffsbverletzung wie folgt vorstellen:

    Ich greife mit dem Befehl stosw über den Deskriptor auf den vom Betriebssystem
    erhaltenen Datenbereich zu. Der Prozessor vergleicht nun Hardwaremäßig
    den Offset in DI mit der Endadresse des Speicherobjects im Deskriptor.
    Ist die Adresse in DI grösser die angegeben Endadresse wird ein Interrupt
    ausgelöst, der Interrupt Vector zeigt auf eine Execptionbehandlungsroutine
    im Betriebssystem wo dann die Exeption behandelt wird.



  • hermes schrieb:

    Da ich im protectec Mode nur über den Deskriptor auf die Daten zugreifen
    kann, oder?, muss doch zuerst ein Deskriptor für dieses Speicherobject
    existieren.

    Richtig, richtig.

    Aber das anlegen eines Deskriptors ist doch nur dem Betriebssystem vorbehalten.

    Wieder richtig. Deshalb schreibt man auch nicht direkt in den Bildschirmspeicher, wenn man unter einem aktuellen OS läuft.

    Und muss ich mir eine Zugriffsbverletzung wie folgt vorstellen:

    Ich greife mit dem Befehl stosw über den Deskriptor auf den vom Betriebssystem
    erhaltenen Datenbereich zu. Der Prozessor vergleicht nun Hardwaremäßig
    den Offset in DI mit der Endadresse des Speicherobjects im Deskriptor.
    Ist die Adresse in DI grösser die angegeben Endadresse wird ein Interrupt
    ausgelöst, der Interrupt Vector zeigt auf eine Execptionbehandlungsroutine
    im Betriebssystem wo dann die Exeption behandelt wird.

    Ich würde sagen, der Offset wird einfach mit der Länge des Segments verglichen. Das ist nur einer von mehreren Checks, aber prinzipiell stimmt es.



  • Kann ich dann eigentlich unter DOS mit dem TASM ein Programm im protectec Mode schreiben.
    Ich müsste doch nur, bevor ich den Prozessor in den protectect Mode
    schalte, den GTDR initialisieren und dann Deskriptoren von meinen Datenbereich
    dem Stackbereich sowie Codebereich mit entsprechenden Privilegien anlegen.
    Ausserdem möchte ich einen Deskriptor anlegen um schreib lese Rechte
    für die Grafig-Karte im 1024*768 256 Farben (VESA) zu erhalten(A000:0), der dann z.B. über das ES Register erreichbar ist (endlich linearer Grafigspeicher ohne
    Bankswitching).
    Müßte eventuell auch noch den INT Vector für die Exeption Behandlung auf meine
    Routine verbiegen.
    Kann man im Prinzip so vorgehen?



  • hermes schrieb:

    Kann ich dann eigentlich unter DOS mit dem TASM ein Programm im protectec Mode schreiben.[?]

    Jup, das geht sogar sehr gut. 😃

    hermes schrieb:

    Ich müsste doch nur, bevor ich den Prozessor in den protectect Mode
    schalte, den GTDR initialisieren und dann Deskriptoren von meinen Datenbereich
    dem Stackbereich sowie Codebereich mit entsprechenden Privilegien anlegen.

    Jo, theoretisch schon - dabei solltest du aber nicht vergessen, dass sgoar DOS teilweise schon ProtectedMode-Komponenten hat (zB. EMM386), die es dir uU. nicht erlauben, einfach so direkt in den PM zu schalten.
    Wenn du also ein DOS-Programm schreiben willst, das im PM laeuft, solltest du in Betracht ziehen, einen DOS-Extender/DPMI zu benutzen, um in den PM zu wechseln. Der DPMI-Host richtet dann beim Wechsel in den PM soweit schon alles fuer dein Programm ein und erleichtert im Allg. die Arbeit im PM unter DOS.
    DPMI-Spezifikationen und weitere Infos zu DOS-Extendern gibt's auch auf der Seite mit dem PM-Tutorial.

    hermes schrieb:

    Ausserdem möchte ich einen Deskriptor anlegen um schreib lese Rechte
    für die Grafig-Karte im 1024*768 256 Farben (VESA) zu erhalten(A000:0), der dann z.B. über das ES Register erreichbar ist (endlich linearer Grafigspeicher ohne
    Bankswitching).

    Jo, blieben 2Dinge zu beachten:
    1.Der FrameBuffer bei A0000 ist auch im PM nur 64KByte gross. Der LFB liegt an einer anderen Adresse, die dir die VESA-Funktion 01h zurueckgibt.
    2.Um VESA-Funktionen aufrufen zu koennen, musst du idR. erstmal wieder in den RM (oder V86) zurueckschalten.

    hermes schrieb:

    Müßte eventuell auch noch den INT Vector für die Exeption Behandlung auf meine
    Routine verbiegen.

    Klingt sinnvoll...

    Wie gesagt, ein DOS-Extender nimmt dir einen Grossteil der Arbeit ab:

    • Mode-Switching(RM<->PM)
    • Weiterleiten von Ints/IRQs von PM zu RM oder
      teilweise auch umgekehrt 😉
    • Speichermanagement (Einrichten von IDT,GDT usw.)
    • Exception-Behandlung

    ...Nachteil ist, dass du aufgeschmissen bist, wenn da irgendwo der Wurm drin steckt 😃 (mir ist bisher noch kein bugfreies Exemplar untergekommen *grml* - mal abgesehen vom Win9x DPMI-Host; Der funktioniert eigentlich ganz gut...). Die Dinger sind schlecht zu debuggen und Support kriegst du dafuer praktisch auch nicht mehr. 😡



  • Nobuo T schrieb:

    2.Um VESA-Funktionen aufrufen zu koennen, musst du idR. erstmal wieder in den RM (oder V86) zurueckschalten.

    Ist so nicht ganz richtig. Es gibt ja auch ein Protected-Mode Interface in der VESA Schnittstelle. schon seit der Revision 2.1 (oder noch eher) und mit der Version 3.0 sogar ein richtig gutes. 😃

    EDIT: Hat jemand nen Link, wo man sich noch die VESA VBE 2.0/2.1 Dokumentation laden kann? Weil die haben meines Wissens nach ja noch ein anderes PM-Interface als die Version 3.0 oder?



  • IMHO beschraenkt sich die PM-Unterstuetzung von VBE2.0 auf den LFB und die Funktionen 05h, 07h und 09h (entry-Point ueber Funktion 0Ah). Bei aelteren Versionen gibt es gar keine PM-Unterstuetzung.
    Wenn man bedenkt, dass auch funktionen fuer buffering und bankswitching verfuegbar sind, habe ich wohl in der Tat unrecht, da der Grossteil der Funktionsaufrufe auch direkt vom PM aus erledigt werden kann.
    Spaetestens wenn's dann aber ans Wechseln des Grafikmodus geht, stimmt die Aussage wieder - VBE3 ist schliesslich nicht unbedingt weit verbreitet. :p

    BTW:
    In den VBE3-Docs stehen auch Infos zu allen Vorgaengerversionen. 😉



  • Danke für die lehrreiche Diskussion zum Thema Protectec Mode.
    Heißt DPMI "Dos Protectect Mode Interface"?


Anmelden zum Antworten