Autor Thema: Cursor setzen  (Gelesen 18035 mal)

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #20 am: 14. May 2007, 18:22 »
Ja na gut... die Sache mit dem Singleton ist ja aus dem Game-Bereich übernommen, als ich noch so was gemacht hab... da hat es Größtenteils geklappt.

Hier die video.h (der relevante Teil jedenfalls)
#ifndef __VIDEO_H__
#define __VIDEO_H__

class CVideo
{
protected:
void putc(char c);
void putnum(int num);
void scroll();
void update_cursor();

CVideo();

unsigned short *m_pVideoMem;
unsigned char m_nColour;
unsigned short m_nCursor;
static CVideo m_Instance;
public:
static CVideo getInstance();

CVideo &operator << (const char c);
CVideo &operator << (const char *str);
CVideo &operator << (const int num);

void setColour(unsigned char colour);
void cls();
};

#endif

Und die Implementation, video.cpp (diesmal fast alles):

#include <system.h>
#include <video.h>

extern "C" void cursor(unsigned short crs);

const int COLS = 80;
const int ROWS = 25;

CVideo CVideo::m_Instance = CVideo();

CVideo::CVideo()
{
m_pVideoMem = (unsigned short*)(0xb8000);
m_nColour = 0x07;

outport(0x03d4,0x0f);
m_nCursor = inport(0x03d5);
outport(0x03d4,0x0e);
m_nCursor |= inport(0x03d5) << 8;
}

CVideo CVideo::getInstance()
{
return m_Instance;
}

void CVideo::putc(char c)
{
if(c == '\n')
{
m_nCursor = (m_nCursor + COLS) & ~(COLS - 1);
}
else if(c == '\b')
{
if(m_nCursor > 0) m_nCursor--;
}
else if(c == '\t')
{
m_nCursor = (m_nCursor + 8) & ~(8-1);
}
else if(c >= 0x20)
{
m_pVideoMem[m_nCursor] = c | m_nColour << 8;
m_nCursor++;
}

scroll();
update_cursor();
}

void CVideo::putnum(int num)
{
char tmp[8];
int i = 0;

if (num == 0) putc('0');
else
{
while (num > 0)
{
int j = num % 0x10;
if(j < 10) tmp[i++] = '0' + j;
else
{
j -= 10;
tmp[i++] = 'A' + j;
}
num /= 0x10;
}
while (i-- > 0)
{
putc(tmp[i]);
}
}
}

void CVideo::scroll()
{
if(m_nCursor >= (COLS * ROWS))
{
memcpy(m_pVideoMem,&m_pVideoMem[COLS],COLS * (ROWS-1));
memsetw(&m_pVideoMem[COLS * (ROWS-1)],0,COLS);
m_nCursor = COLS * (ROWS-1);
}
}

void CVideo::update_cursor()
{
outport(0x03d4,0x0f);
outport(0x03d5,m_nCursor & 0xff);
outport(0x03d4,0x0e);
outport(0x03d5,m_nCursor >> 8);
}

void CVideo::cls()
{
memsetw(m_pVideoMem,0,COLS*ROWS);
outport(0x03d4,0x0f);
outport(0x03d5,0x00);
outport(0x03d4,0x0e);
outport(0x03d5,0x00);
}

void CVideo::setColour(unsigned char colour)
{
m_nColour = colour;
}

CVideo &CVideo::operator <<(const char c)
{
putc(c);
return *this;
}

CVideo &CVideo::operator <<(const char *str)
{
while(*str != '\0') putc(*str++);
return *this;
}

CVideo &CVideo::operator <<(const int num)
{
putnum(num);
return *this;
}

Dazu noch der Assemblerteil für die Konstruktoren:

extern __ctors_start__, __ctors_end__, __dtors_start__, __dtors_end__

; call the constructors
static_ctors_loop:
mov ebx, __ctors_start__
jmp .test
.body:
call [ebx]
add ebx,4
.test:
cmp ebx, __ctors_end__
jb .body

sti

; call kernel proper
mov eax, [multiboot]
push eax
call main
add esp, 4

; call the destructors
static_dtors_loop:
mov ebx, __dtors_start__
jmp .test
.body:
call [ebx]
add ebx,4
.test:
cmp ebx, __dtors_end__
jb .body

cli
hlt

Das war's so weit...

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #21 am: 15. May 2007, 03:01 »
Ich hab jetzt mal ganz am anfang, noch vor dem mappen und alles sonst, etwas code zum nullen des Cursors hinzugefügt:
mov dx, 0x03d4
mov al, 0x0e
out dx, al

mov dx, 0x03d5
mov al, 0x00
out dx, al

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

mov dx, 0x03d5
mov al, 0x00
out dx, al

Und siehe da... es geht. Dann noch weiter an verschiedenen Stellen des Assemblerstarts. Der Punkt, ab dem es nicht mehr geht, ist gleich nach dem die Konstruktoren aufgerufen wurden. Der einzige Konstruktor ist der vom Singleton.

Ich vermute daher sehr sehr stark dass das auslesen des Cursors im Konstruktor einen Schreibzugriff irgendwie nicht mehr zulässt. Daher muss jetzt also entweder wissen warum nicht mehr, oder herausfinden wie ich ein immer wiederholendes Initialisieren des Singleton verhindern kann.
3. Möglichkeit: Ich schreib alles wieder in C.

Korona

  • Beiträge: 94
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 15. May 2007, 11:08 »
Ich kenn mich nicht besonders mit C++ aus, aber
CVideo CVideo::m_Instance = CVideo();Kann imho nicht richtig sein. Du deklarierst das Feld m_Instance der Klasse CViedeo als CVideo und setzt es auf CVideo() ? Schwachsinn imho. Sollte es nicht CVideo::m_Instance = CVideo() sein? (Lässt sich der Konstruktor nicht auch ohne Zuweisungsoperator aufrufen?)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #23 am: 15. May 2007, 11:41 »
@Korona: Das ist schon richtig so

@FalShen: deine getInstance Methode sollte entweder eine Referenz oder einen Zeiger auf das statische Objekt zurückgeben und nicht eine Kopie. Das macht doch das Singleton Pattern aus: Nur (maximal) eine Instanz zu jeder Zeit.

edit: Bevor ichs vergesse: Der copy-constructor und der destructor sollten ebenfalls private oder protected sein. Es ist in dem Fall wichtig zumindest alle zu deklarieren, dann kann man von außen schon nicht zugreifen und alles andere gibt dann ein nicht aufgelöstes Symbol beim Linken.
edit2:  :-D Fast hätte ich den operator = vergessen denn du auch nur deklarieren solltest.
« Letzte Änderung: 15. May 2007, 15:05 von bluecode »
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

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #24 am: 16. May 2007, 00:53 »
Ja... das & hab ich vergessen, mann war ich blöde... Dank an bluecode  :roll:
Den copy-constructor hab ich auch überschrieben, für den fall der Fälle... nur wenn ich einen destruktor deklariere, will der eine __cxa_atexit und den ganzen rest haben... obwohl ich eine dtors section haben will...

Der Cursor wird immer noch nicht richtig gesetzt... aber wenigstens kann ich erstmal weiterarbeiten, da er ja nicht mehr alles in eine Zeile schreiben will

Add: Tja... ich dachte an den inport liegt es dass der das Schreiben in die VGA-Ports nicht mehr zulässt, aber offenbar nicht... hab das gelöscht, der cursor wird immer nocht nicht gesetzt. Der Code ist aber zu 100% korrekt und wird auch aufgerufen, da bin ich mir sicher.
« Letzte Änderung: 16. May 2007, 01:20 von FalShen »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #25 am: 16. May 2007, 11:56 »
Den copy-constructor hab ich auch überschrieben, für den fall der Fälle... nur wenn ich einen destruktor deklariere, will der eine __cxa_atexit und den ganzen rest haben... obwohl ich eine dtors section haben will...
Du musst die richten configure-flags bzw. commandline flags angeben um das zu so hinzukriegen. Ich hoffe, dass da das was ich ins wiki eingetragen hab stimmt, aber ich bin zuversichtlich :)
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

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #26 am: 16. May 2007, 15:01 »
Nee stimmt irgendwie nicht...

Egal, hab mich jetzt einfach kurzerhand vom OO-Design verabschiedet und in C gewechselt, wobei der Cursor immer noch nicht richtig gesetzt wird, ist es nicht lustig?

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #27 am: 16. May 2007, 16:03 »
Also ich hab jetzt keine Ahnung von C-Aufrufen usw...
Aber bist du sicher, dass du nicht irgendwie ein IOPL-Flag ausversehen gesetzt hast? Ich würds mal mit dem Debugger überprüfen...

Gruss
Nooooooooooos

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #28 am: 16. May 2007, 20:37 »
Auch auf die Gefahr hin, jetzt doof darzustehen... was'n ein IOFL flag?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #29 am: 17. May 2007, 02:20 »
Zitat von: AMD Manual zum Thema eflags
I/O Privilege Level Field (IOPL) Field. Bits 13–12. The IOPL field specifies the privilege level required to execute I/O address-space instructions (i.e., instructions that address the I/O space rather than memory-mapped I/O, such as IN, OUT, INS, OUTS, etc.). For software to execute these instructions, the current privilege-level (CPL) must be equal to or higher than (lower numerical value than) the privilege specified by IOPL (CPL <= IOPL). If the CPL is lower than (higher numerical value than) that specified by the IOPL (CPL > IOPL), the processor causes a general-protection exception (#GP) when software attempts to execute an I/O instruction. See Protected-Mode I/O” in Volume 1 for information on how IOPL controls access to address-space I/O. Virtual-8086 mode uses IOPL to control virtual interrupts and the IF bit when virtual-8086 mode extensions are enabled (CR4.VME=1). The Protected-mode virtual-interrupt mechanism (PVI) also uses IOPL to control Virtual interrupts and the IF bit when PVI is enabled (CR4.PVI=1). See “Virtual Interrupts” on page 241 for information on how IOPL is used by the virtual interrupt mechanism.
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

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #30 am: 17. May 2007, 10:15 »
Bochs sagt, das IOPL ist dann am Ende gleich 0. Soll das so sein?
Kann das auch was mit dem VME-Flag zu tun haben, in cr4? Die Infos die ich zu den Pentium-Registern finde sind eher dürftig.
Ich weiß auch immer nicht ob das OS nun CPL = 0 oder CPL = 3 ist... Mann bin ich blöd ^^

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #31 am: 17. May 2007, 10:18 »
Dann solltest du dir erstmal die Grundlagen der x86 CPU vertraut machen sowie die Grundlagen oder am besten erweiterte Kentnisse von C/C++ anschaffen. Denn ich sehe das Problem weder an der Cursor-Funktion, noch im IOPL-Flag sondern eher an mangelnde Kentnisse. Wenn du nicht weißt ob dein OS in CPL0 oder CPL3 läuft ist das mehr als schlecht.

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

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #32 am: 18. May 2007, 13:41 »
Ja da hast du vollkommen recht.

 

Einloggen