Autor Thema: Cursor setzen  (Gelesen 14261 mal)

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« am: 12. May 2007, 04:20 »
Ich schätze mal, jeder von euch hat diesen kleinen Abschnitt so in seinem Kernel zu stehen:
        outport(0x03d4,0x0f);
outport(0x03d5,m_nCursor & 0xff);
outport(0x03d4,0x0e);
outport(0x03d5,m_nCursor >> 8);
Oder zumindest sehr ähnlich. Also, dieser Code funktioniert bei mir auf einmal nicht mehr. Zuerst dachte ich, es wäre ein neuer Bug von Bochs. Nein. Es ist auch kein Compilerfehler, hab den Assmblercode überprüft. Ich habe auch die outport Funktion in Assembler und in C geschrieben, kein Unterschied. Ich hab jetzt keine Ahnung was ich hier machen soll, denn der Cursor wird einfach nicht gesetzt.
An einer anderen Stelle lese ich die Register um meine Cursor-Variable zu updaten, das klappt.
        outport(0x03d4,0x0f);
m_nCursor = inport(0x03d5);
outport(0x03d4,0x0e);
m_nCursor |= inport(0x03d5) << 8;
Auch der Versuch, den Cursor auf 0|0 zu setzen, also direkt 0x00 als Positionen zu übergeben, hat nicht funktioniert.
Nun sitz ich hier bis 4 Uhr nachts nur wegen diesem Fehler, und ich könnte schreien, weil ich nicht wieß, was es ist.

Was ist hier falsch? Ist das wiedermal so etwas, dass Code der sonst immer geht, nur bei mir wieder mal absolut nicht funktioniert? Hatte ich ja sch öfters...

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #1 am: 12. May 2007, 09:39 »
Hi, dazu musste ich erstmal mein alte RM OS/M Betriebssystem Code rauskramen. Das habe ich dann auch gemacht und so schön wie das ist, ich verstehe meinen eigenen Code immer so schnell. Die Variable m_nCursor ist bei dir ein WORD groß, soll das erste Byte den X Wert beinhaltet und das zweite den Y Wert? Wenn ja dann ist das falsch. Man sendet nicht Spalte + Zeile. Man multipliziert die gewünschte Zeile mit 80 (80 = Anzahl der Zeilen) und addiert die gewünschte Spalte hinzu. Also ungefähr so:

Zeile*80+Spalte

Diesen Wert kopiert man dann z.B. in die Variable m_nCursor. Dann das erste Byte senden und dann das zweite (oder so wie ich anders herum, kA ob die Reihenfolge egal ist). Aus deinem Code geht natürlich nicht hervor ob du vorher die Berechnung machst und es also richtig machst. Aber du sagst ja, 0,0 geht auch nicht, also muss es ein anderer Fehler sein. Also mein ASM-Code sollte das gleiche machen wie dein C-Code:

mov al,0Eh
mov dx,03D4h
out dx,al
mov al,bh
mov dx,03D5h
out dx,al
mov al,0Fh
mov dx,03D4h
out dx,al
mov al,bl
mov dx,03D5h
out dx,al

Nur das hier halt in bx der Wert ist, welcher bei dir in m_nCursor ist. Also fürhst du die obene Berechnung auch durch, wird dein Code an der richtigen Stelle ausgefürht etc. ? Ob man jetzt erst den 0Eh-Wert senden muss und dann den 0Fh-Wert oder ob das egal ist weiß ich nicht. Tausche es mal, wenn nichts anderes der Fehler sein kann.


bitmaster
In the Future everyone will need OS-64!!!

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #2 am: 12. May 2007, 09:42 »
Auf den ersten Blick sehe ich da keinen Fehler, vorausgesetzt, du berechnest die Position korrekt.

Hier ein Ausschnitt aus dem LOST-Code. Dieser funktioniert so:
//Hardware Cursor verschieben
word hw_cursor_pos = cursor_x + cursor_y * SCREEN_WIDTH;
outb(0x3D4, 15);
outb(0x3D5, hw_cursor_pos);
outb(0x3D4, 14);
outb(0x3D5, hw_cursor_pos >> 8);

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #3 am: 12. May 2007, 14:44 »
Nein, m_nCursor enthält die bereits berechnete Position, also eigentlich nur das Offset (m_nOffset wäre ein besserer Name, geb ich zu...) Somit muss die Berechnung ja nicht erfolgen. Um eins weiter zu gehen, inkrementiere ich diese Variable nur, ist einfacher als immer mit einem X- und einem Y-Wert zu rechnen und geht auch schneller.
In C hatte ich das schon einmal so gemacht, und es hat funktioniert. Geht es einfach nicht, weil ich C++ verwende, oder was?

Add: Hab jetzt mit X- und Y-Werten probiert, immer noch nicht...

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 12. May 2007, 16:16 »
Eventuell Stack/Memory Corruption oder Probleme mit Paging, Interrupts oder Segmenten, die verhindern, dass der Code ausgeführt wird?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 12. May 2007, 16:55 »
m_nCursor klingt so nach Membervariable. Könnte es sein, dass es eine globale Klasse ist, welche du nicht initialisierst?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 12. May 2007, 18:25 »
http://www.osdev.org/wiki/Text_Mode_Cursor
hat fast genau den gleichen code, es werden nur noch Typumwandlungen gemacht.

Ist deine outport-function korrekt? ist die vieleicht nicht für bytes sondern words? was anderes fällt mir sonst nicht ein.

PS:
OSDev.org sagt auch:
Zitat
Keep in mind that in/out to VGA Hardware is a slow operation. So using the hardware registers to remember of the current character location (row, col) is bad practice
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #7 am: 12. May 2007, 20:41 »
Standardmäßig sahe sie so aus:
        [GLOBAL outport]
outport:
push ebp
mov ebp, esp

mov edx, [ebp+8]
mov eax, [ebp+12]

out dx, al

leave
ret

[GLOBAL inport]
inport:
push ebp
mov ebp, esp

mov edx, [ebp+8]

in al, dx

leave
ret
So hab ich sie immer genutzt... Als das auf einmal im C++ Kernel nicht funktioniert hat, hab ich versucht, das so zu machen:
unsigned char inport(unsigned short port)
{
unsigned char value;
__asm__ __volatile__ ("inb %1, %0" : "=a"(value) : "d"(port));
return value;
}

void outport(unsigned short port,unsigned char value)
{
__asm__ __volatile__ ("outb %b0,%w1" : : "a"(value), "d"(port));
}
(Gefunden in dem OSD Kernel Paket auf Bona Fide)

Edit: Vorher hab ich immer die ASM-Funktionen genutzt... Hat auch immer funktioniert. Nebenbei, der outport bei
outport(0x03d4,0x0f);
m_nCursor = inport(0x03d5);
outport(0x03d4,0x0e);
m_nCursor |= inport(0x03d5) << 8;
muss ja funktionieren, da der Cursor richtig ausgelesen wird. Nur nicht richtig gesetzt... Der steht im Konstruktor (weil statische Klasseninstanz), also wird die Variable initialisiert.

Der Code
outport(0x03d4,0x0e);
outport(0x03d5,0x00);
outport(0x03d4,0x0f);
outport(0x03d5,0x00);
geht ja auch nicht...

Nebenbei... von inline assembler von gcc hab ich keine ahnung... Versteht den überhaupt jemand? Der ist so kryptisch...
« Letzte Änderung: 12. May 2007, 20:47 von FalShen »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 12. May 2007, 20:48 »
Nebenbei... von inline assembler von gcc hab ich keine ahnung... Versteht den überhaupt jemand? Der ist so kryptisch...
http://lowlevel.brainsware.org/wiki/index.php/Inline-Assembler_mit_GCC
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #9 am: 13. May 2007, 01:58 »
ich hab mit dem inline assembler etwas gemacht... und dann einfach, weil's mir so langsam reicht, alles komplett mit assembler gemacht, also due cursor-funktion:
        [GLOBAL cursor]
cursor:
push ebp
mov ebp, esp

mov ebx, [ebp + 8]

mov al, 0x0e
mov dx, 0x03d4
out dx, al

mov al, bl
mov dx, 0x03d5
out dx, al

mov al, 0x0f
mov dx, 0x03d4
out dx, al

mov al, bh
mov dx, 0x03d5
out dx, al

leave
ret

ABER: ES GEHT IMMER NOCH NICHT!!!

Ich raste bald aus, es ist doch DER SELBE CODE den ALLE ANDEREN und auch ich selbst benutzen, und der immer funktioniert... NUR HIER NICHT...
WARUM NUR??

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 13. May 2007, 07:43 »
Entweder deine Routine ist zu schnell---> Dann würde ich irgendwelche NOPs mal reinflicken zur verlangsamung.
Oder es liegt an etwas ganz anderem an deinem OS! Was hast du denn schon alles implementiert? Multitasking?, welches?, Paging, PM, hast du irgendwelche Ports vielleicht gesperrt, IOPL-Flag in den Eflags, oder TSS?, Flaches oder anderes Speichermodell...
Erzähl mal was über dein OS!!


Gruss
Noooooooooooos
« Letzte Änderung: 13. May 2007, 07:45 von nooooooooos »

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #11 am: 13. May 2007, 11:18 »
Zitat
Entweder deine Routine ist zu schnell---> Dann würde ich irgendwelche NOPs mal reinflicken zur verlangsamung.
Was für ein Schwachsinn!!!

bitmaster
In the Future everyone will need OS-64!!!

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 13. May 2007, 11:54 »
Bochs erwartet nicht, dass du wartest bis die Bytes korrekt verarbeitet wurden. Bochs braucht kein exaktes Timing soweit ich weiß (beim den Controllern für Floppy oder Harddisk sowie beim APIC und anderen Geräten auch nicht.)

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 13. May 2007, 13:55 »
Warum Schwachsinn?? 1. steht ja sowas in Osdev.org... und 2. hat es mehr Sinn einfach mal zur kontrolle 3 nops reinzuflicken, als zu erklären, wie man einen Pixel berechnet, was gar nix mit dem Problem zu tun hat....

Gruss
Noooooooooos

PS: übrigens steht glaub ich nirgends was über bochs...

Coffee

  • Beiträge: 470
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 13. May 2007, 16:58 »
Zuerst dachte ich, es wäre ein neuer Bug von Bochs.

ejtz hört ma auf euch hier so zu dissen das bringt auch kein ergebnis...
obwohl ich verlangsamung auch für überflüssig halte

MfG
PS: einfach mal auf überflüssig klicken und outchilln

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #15 am: 13. May 2007, 19:40 »
Zitat
was gar nix mit dem Problem zu tun hat....
Was wir bis dahin ja noch gar nbicht wussten. Und deine NOPs bringen da auch nichts, weil es mit dem Code gar nichts zu tun hat. Dieser wird nämlich nicht oder nicht richtig aufgerufen. Der Code an sich ist richtig. Also liegt das Problem ganz wo anders.


bitmaster
In the Future everyone will need OS-64!!!

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 13. May 2007, 20:28 »
Das ist mir ja auch klar dass das warscheinlich nix bringt...Aber ganz sicher war ich mir halt nicht, weshalb ich ihm sagte er solls einfach mal probieren...Sowieso handelte der grösste Teil meines Posts nachher über andere Möglichkeiten welchen den Fehler zur Folge haben könnten.

Darum back-to-topic:
Entweder deine Routine ist zu schnell---> Dann würde ich irgendwelche NOPs mal reinflicken zur verlangsamung.
Oder es liegt an etwas ganz anderem an deinem OS! Was hast du denn schon alles implementiert? Multitasking?, welches?, Paging, PM, hast du irgendwelche Ports vielleicht gesperrt, IOPL-Flag in den Eflags, oder TSS?, Flaches oder anderes Speichermodell...
Erzähl mal was über dein OS!!

Und dann eben schau nochmals mittels einer Testausgabe oder sowas ob der Code ausgeführt wird. Du kannst z.B. ein Zeichen dort ausgeben, wo der Cursor hinsollte.


Gruss Nooooooooooos

Homix

  • Beiträge: 138
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 13. May 2007, 22:42 »
hi,
an der Stelle, wohin der Cursor hin soll, was steht da denn für ein Farbwert/Attributewert/"ka wie man das nennt"-Wert ?
Es sollte zumindest kein Schwarz auf Schwarz dastehen (0x00) :)

mfg,
Stefan

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #18 am: 14. May 2007, 00:33 »
Die Zeichenausgabe ist wunderschön, so funktioniert alles.

Hier die Ganze story: Der Kernel ist der neueste rewrite des Scén-Kernels. Hier wollte ich möglichst viel Objektorientiert arbeiten. Bisher hab ich es geschafft (siehe Topic), den Kernel an die Adresse 0xc0000000 zu mappen.
Die Klasse CVideo soll überall gleichermaßen zu benutzen sein. Um dies zu erreichen, wird eine statische Variable als Instanz definiert. Da allerdings ein statisches Objekt bei jedem Aufruf neu erzeugt wird (weshalb die Bezeichnung 'static' eher Schwachsinn ist), wird im Konstruktor der Hardware-Cursor ausgelesen. Somit ist es natürlich wichtig, dass der immer korrekt gesetzt ist.

Es passiert folgendes: Bochs setzt den Cursor irgendwo in die mitte des Bildschirms. Dann, bei jedem Aufruf, also
CVideo::getInstance() << "String";Wird das objekt erzeugt, der String wird dargestellt, aber der Cursor nicht gesetzt. Beim nächsten Aufruf startet er also wieder an der Adresse des Hardware-Cursors, der noch von Bochs stammt.
Die schreib-routine ist die selbe wie immer, gefunden im BKerndev und anderen Tuts bei Bona Fide. Hab's auch 3000mal kontrolliert.
Das schärfste: Hab auch disassmebliert und mit dem alten C-Kernel verglichen, wo es funktionierte. Exakt das selbe.

Was bisher implementiert ist: Paging, PSE (die einzige Neuerung zu vorher), Exceptions (also die ersten 32 interrupts), und die IRQs, aber nur definiert, noch nichts weiter.

also der einzige unterschied sind die Zeilen
mov eax, cr4
or eax, 0x11
mov cr4, eax
Für die 4MB-Pages, aber das isses nicht oder?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #19 am: 14. May 2007, 10:11 »
Um dies zu erreichen, wird eine statische Variable als Instanz definiert. Da allerdings ein statisches Objekt bei jedem Aufruf neu erzeugt wird (weshalb die Bezeichnung 'static' eher Schwachsinn ist), wird im Konstruktor der Hardware-Cursor ausgelesen.
Dann machst du irgendwas falsch. Das stimmt nämlich so nicht. Für statische und globale Objekte musst du aber selbst für die Konstruktion und Destruktion sagen, siehe wiki. Zeig am besten mal deine CVideo implementation, die scheint mir dann kein richtiges Singleton zu sein.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen