VGA - Bildschirm löschen



  • Hallo,
    Ich befinde mich im protected-mode im Textmodus. Nun mach ich folgendes um ein Zeichen auszugeben (in dem Beipsiel oben Links in der Ecke)

    mov byte [es:0B83EAh],'n'
    

    So. Jetzt habe ich ne ganze Reihe Zeichen auf den Bildschirm geschrieben, und würde den Bildschirm nun gerne komplett löschen. Gibt es da eine Möglichkeit, ohne jeden Wert zwischen 0B8000h und 0B8FFFh per hand mit einem Leerzeichen zu überschreiben? Denn das wäre echt sehr mühselig. Habe leider noch keine Möglihkeit gefunden, habe zwar schon rumprobiert, bin aber zu keinem funktionierenden Ergebniss gekommen. 😃 Danke!



  • Du musst jeden einzeln überschreiben.



  • Och nöh...Jeden mit dem Befehl

    mov byte [es:0B8000h],' '
    ...
    mov byte [es:0B8FFFh],' '
    

    Oder kennt einer ne Möglichkeit, eine Schleife zu bauen, die automatisch von 0B000H bis 0BFFFh hochzählt? ioch hatte folgenden Ansatz, der aber leider nich zu funktionieren scheint:

    mov di, 0B8000h
    
    starte_löschen:
    add di, 02h
    mov byte [es:di],' '
    cmp di, 0B8FFFh
    jne start_löschen
    
    ...
    

    Weiß einer vielleicht, warum das nicht funktioniert oder was ich verändern muss, damit es funktioniert? Danke!



  • Ja natürlich macht man das mit einer Schleife. Du willst doch nicht ernsthaft die Zeile tausende Male hintereinanderkopieren.

    Du verwendest 16bit-Register, aber 32bit-Werte. 😕



  • naja, ich habe jetzt diese zeile von 0B8000 bis 0B8FFF geschrieben. Aber natürlich macht das den Quellcode langsam unübersichtlicht. Kannst du mir denn sagen, wie ich so eine Schleife bauen kann? Danke! Weil ich fand meine Idee schon gut, nur leider ist da der Wurm drin, die funktioniert nämlich net, wie schon gesagt.



  • 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.


Anmelden zum Antworten