Autor Thema: Bildschirm löschen bzw. leeren  (Gelesen 17257 mal)

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« am: 07. September 2010, 22:25 »
Servus,

erstmal großes Lob an die lieben Leute, die sich solche Mühe für das Wiki gegeben haben.
Ich habe nach langem Rumgewurschtel und Tools installieren (unter Windows, ich denke der Fall ist für euch klar  :wink:) geschafft ein bootfähiges Image, welches GRUB benützt zu erstellen, so wie es in "Teil 4 - Hello World" des Wikis beschrieben ist.
Da ich nirgends eine Anleitung gefunden habe, wie man nun den Bildschirm löscht.

Zitat
[...] ein wunderschönes Hello World in die linke obere Ecke. Den Rest des Bildschirms zu löschen haben wir leider vergessen, so dass das über irgendwelche BIOS-Meldungen geschrieben wird.

Nun, da ich nicht - so wie wir hier in Bayern sagen - auf der Brennsuppe dahergeschwommen komme, schonmal kleine Programme für meinen Taschenrechner in Assembler geschrieben habe und über passable C-Kenntnisse (oder vielmehr C++) verfüge, habe ich folgende schleife in die init()-Funktion hinzugefügt:

//...
int n;
while (n < 0xB8FA0)
{
video[n] = 0x0;
n++;
}
//...

vorher wurde 'video' als Pointer auf die Adresse 0xB8000 definiert.
Im Wiki steht, der Videospeicher ist 4kB groß d.h. 4000 Byte entspricht FA0 in hexadezimal.
Dann rechnet man zu 0xB8000 noch FA0 dazu, und man bekommt die letzte Adresse im Videospeicher - oder?
Mithilfe der schleife wird dann jedes Byte auf 0 (Schwarz) gesetzt. Somit hätte ich ja dann quasi auch den Bildschirm gelöscht.
Und es funktioniert sogar!
Leider gibt Bochs vor dem Ausführen einige PANIC-Meldungen aus, welche ich alle mit 'Continue' quittiere.
Das Hello World wird korrekt auf einem schwarzen Bildschirm ausgegeben, so wie ich es wollte.
Die Frage ist nur, kann ich das auf meinen PC loslassen? Ich meine Bochs wird nicht umsonst PANIC schieben.

mfg rungaaz

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 07. September 2010, 22:43 »
Hm, auf den ersten Blick... Wie wäre es damit, n auch noch zu initialisieren? Und wie ist video deklariert? Als char* bzw. uint8_t*?  Falls nicht: Du wärst nicht der erste, der auf die C-Pointerarithmetik reinfällt. ;)

Ansonsten zeig mal die genauen bochs-Meldungen her, da sollten auch noch ein paar Hinweise auf den Fehler drin stehen.

Was den realen PC betrifft, ist die Wahrscheinlichkeit nicht groß, dass du irgendwas kaputt machst. Wenn du irgendwann mal auf die Festplatte schreibst, würde ich mir Gedanken machen, ob das ausgerechnet die Festplatte sein muss, die die wichtigsten Daten enthält, aber mit ein bisschen falschen Speicher überschreiben geht in der Regel nichts kaputt (auch wenn es mit viel Pech theoretisch möglich wäre, das eine oder andere lahmzulegen).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 07. September 2010, 23:17 »
vorher wurde 'video' als Pointer auf die Adresse 0xB8000 definiert.
Im Wiki steht, der Videospeicher ist 4kB groß d.h. 4000 Byte entspricht FA0 in hexadezimal.
Dann rechnet man zu 0xB8000 noch FA0 dazu, und man bekommt die letzte Adresse im Videospeicher - oder?
Ja, dass ist die letzte bzw. die Adresse danach. Aber die brauchst du gar nicht. Wenn char* video = 0xb8000, dann hast du das
Ende schon mit video[0xfa0] erreicht(bzw. überschritten) und nicht erst mit video[0xb8fa00].
« Letzte Änderung: 07. September 2010, 23:54 von MNemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 07. September 2010, 23:45 »
Ups, MNemo hat natürlich recht. Da habe ich nicht gründlich gelesen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 08. September 2010, 08:40 »
Also video wurde folgendermaßen definiert: char* video = (char*) 0xB8000
Ach, jetz peil ich das. Die Schleife muss folgendermaßen lauten:

int n (0); //Oder int n = 0; Ist glaub ich Jacke wie Hose
while (n < 0xFA0)
{
    video[0xB8000 + n] = 0x0; //ansonsten würde man ja den Speicher von 0x0 bis 0xB7FFF auch löschen, was ich ja nicht will.
    n++
}

So, die genauen Panic-Meldungen werde ich noch Posten, aber nicht jetzt, da ich gerade nicht zuhause bin.

Und danke für die Nachsicht im Bezug auf die Forenwahl.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 08. September 2010, 09:24 »
Wenn video 0xb8000 ist, dann ist video[0xb8000 + n] an der Adresse 0x170000 + n. Das ist nicht, was du wolltest.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 08. September 2010, 09:49 »
Aber ich dachte, 0xB8000 wäre die erste Adresse im Videospeicher.
Und da muss man natürlich 4kB dazurechenen, um die letzte Adresse zu erhalten.

Achja, stimmt, video zeigt ja schon auf 0xB8000...


[EDIT]
Also, nochmal   :-D
int n (0);

while (n < 0xFA0)
{
    video[n] = 0x0;
    n++;
}

Das dürfte dann hinhauen.
Ich werds testen, und ich werde auch den Code posten.
Aber wie gesagt, erst später, wenn ich zuhause bin.

Zitat
Wie wäre es damit, n auch noch zu initialisieren?
n ist doch dann automatisch 0 - oder?
« Letzte Änderung: 08. September 2010, 11:33 von hrungaaz »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 08. September 2010, 13:30 »
Dann musst du schon schreiben

int n = 0;

Die Klammern sind falsch.

Eleganter wäre

for( n = 0; n < 4000; n++ )
  video[n]=0;

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 08. September 2010, 13:38 »
Also in C++ ist int n (0); äquivalent zu int n = 0;
Ob das in C anders ist, weiß ich nicht.
Wie gesagt, ich bin gerade nicht zuhause, um das auszutesten.

 - Ja, wohl war, aber ich bin kein Fan von For-Schleifen.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 08. September 2010, 13:45 »
Keine Ahnung, da ich mich in C++ nicht besonders auskenne. Da der gcc ein C/C++-Compiler ist, wird er das vielleicht auch können - festlegen mag ich mich da nicht.

For-Schleifen sind aber unglaublich praktisch, um Listen zu traversieren, außerdem kürzer:

void* anfang=...; void* tmp;
for( tmp = anfang; tmp!=NULL; tmp=tmp->next )
  guck_dir_element_an(tmp);

:-P

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 08. September 2010, 13:56 »
Dann musst du schon schreiben

int n = 0;

Die Klammern sind falsch.
Wenn er sein Kernel in C++ schreibt, sind sie nicht falsch.

Zitat
Wie wäre es damit, n auch noch zu initialisieren?
n ist doch dann automatisch 0 - oder?
Nein! n enthält das was zufällig gerade auf dem Stack liegt bis du ihm einen bestimmten wert zugewiesen hast.
Wenn n global definiert ist landet es nicht auf dem Stack sondern in der .bss Sektion, die wenn du glücke hast
vorher mit 0 gefüllt worden ist, aber verlassen solltest du dich da nicht drauf.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 08. September 2010, 14:18 »
Nein! n enthält das was zufällig gerade auf dem Stack liegt bis du ihm einen bestimmten wert zugewiesen hast.
Wenn n global definiert ist landet es nicht auf dem Stack sondern in der .bss Sektion, die wenn du glücke hast
vorher mit 0 gefüllt worden ist, aber verlassen solltest du dich da nicht drauf.
Wie kaputt C++ an dieser Stelle ist weiß ich nicht, aber C99 garantiert dir bei einer globalen Variablen, dass sie mit 0 initialisiert wird.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 08. September 2010, 14:31 »
Ich finde in While-Schleifen ist man einfach freier.

Zitat
Nein! n enthält das was zufällig gerade auf dem Stack liegt bis du ihm einen bestimmten wert zugewiesen hast.
Wenn n global definiert ist landet es nicht auf dem Stack sondern in der .bss Sektion, die wenn du glücke hast
vorher mit 0 gefüllt worden ist, aber verlassen solltest du dich da nicht drauf.
- Achso, das wäre also dann quasi so, als würde man einen Pointer nur deklarieren.

Zitat
Was soll das eigentlich heißen. Ich habe auch unter Windows entwickelt und es war leicht alles einzurichten.

Immer diese Windows Feinde hier...

Gut, stimmt auch wieder, aber es gab eine Zeit, da hatte ich noch extrem wenig Erfahrung, da habe ich es einfach nicht zustande gebracht, das ganze unter Windows einzurichten. Nun, da ich mehr Erfahrung habe, ist das kein Problem mehr gewesen. Aber damals hätte ich es unter Linux womöglich schon zustand gebracht.
Außer ich hätte wegen meiner damals mangelnden Linux-Kenntnissen die nötigen Tools nicht kompilieren können, was dann aufs Gleiche hinausgelaufen wäre.

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 08. September 2010, 14:55 »
Ja, gut, das stimmt auch wieder.
Es ist nur so, ich bin quasi mit Windows aufgewachsen.
Ich habe schon ein wenig Kenntnisse in Linux aber weitaus nicht so viele wie unter Windows.
Und wie gesagt, ich habe es jetzt auch unter Windows zu stande gebracht.

Zitat
und komme nicht auf die Idee dir einen 64Bit Cross gcc für Windows zu kompilieren
Keine Angst, das hatte ich ohnehin nicht vor.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 08. September 2010, 15:01 »
Nein! n enthält das was zufällig gerade auf dem Stack liegt bis du ihm einen bestimmten wert zugewiesen hast.
Wenn n global definiert ist landet es nicht auf dem Stack sondern in der .bss Sektion, die wenn du glücke hast
vorher mit 0 gefüllt worden ist, aber verlassen solltest du dich da nicht drauf.
Wie kaputt C++ an dieser Stelle ist weiß ich nicht, aber C99 garantiert dir bei einer globalen Variablen, dass sie mit 0 initialisiert wird.
OK. Sieht so aus als ob sich gcc/g++ darauf verlässt das die .bss Sektion mit Nullen gefüllt wird. Und in der ELF-Spezifikation steht dass sogar drin. Irgend wie hatte ich in Erinnerung das das nur eine Empfehlung sei -- kein Muss. Das läuft in meinem ELF loader glaub ich noch schief. :roll:

- Achso, das wäre also dann quasi so, als würde man einen Pointer nur deklarieren.
So in etwa.

@offfff topic
Da sitzt du einen Tag dran und es geht immer noch nicht.
Immer diese … Kämpfen Tage lang mit Ihren Tools, aber unter Windows ist trotzdem alles ganz easy ..?..
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 08. September 2010, 15:08 »
OK. Sieht so aus als ob sich gcc/g++ darauf verlässt das die .bss Sektion mit Nullen gefüllt wird. Und in der ELF-Spezifikation steht dass sogar drin. Irgend wie hatte ich in Erinnerung das das nur eine Empfehlung sei -- kein Muss. Das läuft in meinem ELF loader glaub ich noch schief. :roll:
Besser gleich fixen, in tyndur hatten wir genau deswegen schon echte Bugs. Die zu debuggen macht keinen Spaß, denn auf den ELF-Loader kommt man erst als allerletzes.

Edit: Huch, du schreibst ein eigenes OS? Ich hatte dich immer irgendwie als einen von der Fraktion der Theoretiker angesehen. Gibt's irgendwo was zu sehen?
« Letzte Änderung: 08. September 2010, 15:09 von taljeth »
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 08. September 2010, 15:23 »
Edit: Huch, du schreibst ein eigenes OS? Ich hatte dich immer irgendwie als einen von der Fraktion der Theoretiker angesehen. Gibt's irgendwo was zu sehen?
Ja, ich schreibe ein eigenes OS(Namen hat es (immer-)noch nicht). Ich gehöre auch etwas zu der Fraktion der Theoretiker, das ist nicht der erste versuch für einen OS, und diesmal hab ich mir halt vorgenommen das alles besser zu planen. Deshalb ist da nicht viel zu sehen. Und so intensive arbeite ich da auch nicht dran.  Und die quellen sind auch nicht offen. Von daher eher uninteressant.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 08. September 2010, 16:02 »
Eine Frage: Kann es sein, dass an jeder Adresse 16BIT stehen?
Wenn ja, muss ich in meiner schleife nicht überprüfen, ob n < 0xFA0 sondern n < 0x1F40 - oder?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 08. September 2010, 16:19 »
Wenn du es als char* deklariert hast nicht.

Und halbieren, nicht verdoppelt wäre der richtige Ausgleich für diesen Fall.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

hrungaaz

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 08. September 2010, 16:33 »
Verzeih mir die Frage, aber ist ein char wirklich 16BIT groß?

Zitat
Und halbieren, nicht verdoppelt wäre der richtige Ausgleich für diesen Fall.
- Ja, verdammt, stimmt.  :-)
Mit der Zeit schwindet irgendwie das logische Denken...

 

Einloggen