Autor Thema: Merkwürdiges Problem  (Gelesen 9472 mal)

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« am: 07. September 2004, 19:43 »
Hi,
ich hab ein ganz merkwürdiges Problem an dem ich jetzt 6 std dran sitze und es einfach nicht verstehe:
Dies ist meine main.c:

const char *tutorial3;
const char *Test;
//extern unsigned int EnableA20Gate();

void main()
{
    //Bildschirm löschen
    //clrscr();
    //Begruessung
    //writeln("Wilkommen in Sovs Os");
    //A20Gate aktivieren
    //writeln("Versuche A20Gate zu aktivieren...");
      A20gate_enable();
      //Endlosschleife
      for(;;);
}

const char *tutorial3 = "Sov`s Os in Protected-Mode";
const char *Test = "Dies ist ein Test in Main.c";

Immer wenn ich das Kommentar vor clrscr weg nehme wird der screen geleert, jedoch die Writeln in A20gate_enable nicht mehr angezeigt.
Mit kommentar erscheinen dann die Ausgaben von A20gate.
Wenn ich das Kommentar vor writeln("Wilkommen in Sovs Os"); weg nehme
passiert in bochs folgendes: Panic Device CPU
Message: prefetch: running in bogus memory
Kill simulation und dann stürzt er ab.
Das gleiche passiert, wenn ich die kommentare vor //writeln("Versuche A20Gate zu aktivieren..."); weg nehme.
Aber in der funktion a20gate... habe ich auch ausgaben mit writeln("Text");
und die werde einwandfrei ausgegeben.
Help!!!
Wer weiß was das sein könnte??
Ich habe echt keine Ahnung mehr woran es liegen könnt.
Gruß sov21

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 07. September 2004, 20:38 »
Das Problem mit dem clrscr ist jetzt weg, nach dem diePIC umprogrammeirung noch eingebunden habe.
Aber das writeln-Prob ist immer noch da.
Kann es sein, daß wenn man die Funtionen in zu viele Dateien aufspeltet und diese dann linkt, irgendwie eine funktion von einer anderen im Code zuweit weg liegt, so daß sie von dort nicht erreichbar ist??

Weil ich linke wie folgt:
ld -i -e _main -Ttext 0x1000 -o kernel.o main.o video.o ports.o A20Gate.o pic.o
Kann mir jemand helfen?? :-(
Gruß sov21

gurru

  • Beiträge: 42
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 07. September 2004, 23:22 »
Zitat
sov21 postete
Kann es sein, daß wenn man die Funtionen in zu viele Dateien aufspeltet und diese dann linkt, irgendwie eine funktion von einer anderen im Code zuweit weg liegt, so daß sie von dort nicht erreichbar ist??
Das würde höchstens einen Linkerfehler geben, daran kanns nicht liegen
Auch glaube ich kaum, das dein Projekt größer als 4 GB-Byte ist(die Sprungreichweite im Protected Mode)

mfg gurru

Lizer

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 08. September 2004, 12:53 »
Der Fehler liegt in writeln() oder clrscr(). Poste die doch mal. Benutzt du eine Varibale für die Zeichenattribute? Hast du vergessen, nach dem Bildschirmleeren wieder einen sichtbaren Wert einzustellen? Könnte der Wert sonst wie verändert worden sein? Liegt er in einer Header? Wenn ja, schreib ihn in eine .C-Datei und greife nur über Funktionen darauf zu, die in der selben Datei sind. Niemals das "extern" vergessen. Das alles gilt auch für die Variable in der du die Cursor-Position speicherst.

Wie gesagt, poste deine clrscr() und die writeln(), dann kann man dir besser helfen.

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 08. September 2004, 16:06 »
Also hier mal meine funktionen:
void clrscr()
{
  unsigned char *vidmem = (unsigned char *)0xB8000;
  const long size = 80*25;
  long loop;

  // Clear visible video memory
  for (loop=0; loop<size; loop++) {
    *vidmem++ = 0;
    *vidmem++ = 0xF;
  }

  // Set cursor position to 0,0
  out(0x3D4, 14);
  out(0x3D5, 0);
  out(0x3D4, 15);
  out(0x3D5, 0);
}

//Print mit newline
void writeln(const char *_message)
{
  unsigned short offset;
  unsigned long i;
  unsigned char *vidmem = (unsigned char *)0xB8000;

  // Read cursor position
  out(0x3D4, 14);
  offset = in(0x3D5) << 8;
  out(0x3D4, 15);
  offset |= in(0x3D5);

  // Start at writing at cursor position
  vidmem += offset*2;

  // Continue until we reach null character
  i = 0;
  while (_message != 0) {
    *vidmem = _message[i++];
    vidmem += 2;
  }

  // Set new cursor position
  //offset += i;
  offset += 80;// - offset;
  out(0x3D5, (unsigned char)(offset));
  out(0x3D4, 14);
  out(0x3D5, (unsigned char)(offset >> 8));
}
Beide sind in Video.c die mit dem kernel gelinkt wird.
Dann noch einen Auszug aus A20gate, wo es ja funktioniert:
void A20gate_enable()
{
    //Var deklaration
    unsigned char RetVal;
    int weiter = 0;

    //A20-Gate aktivieren

    //A1:
    while (weiter == 0)
    {
        if ((in(0x64)&0x02) != 0x02)
        {
            writeln("Lesebefehl an Tastatur-Controller senden...");
            out(0x64, 0xD0);
            weiter = 1;
        }
        else
        {
            writeln("1.Tastatur-Controller nicht bereit, warten...");
        }
    }
    weiter = 0;
Ich weiß echt nicht woran es liegt, außer daß ich noch keine var habe in der ich cursor pos speichere, aber das kanns nicht sein, weil er stürzt ja ab und schreibt nicht in einen nicht sichtbaren Bereich.
Gruß sov21

Lizer

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 09. September 2004, 08:29 »
Hast du mal die Cursor-Werte überprüft, die du bekommst? Wenn die Werte außerhalb des vidmems sind, ist es kein Wunder wenn du nichts siehst. Im allgemeinen ist es sowieso besser, eine Variable für den Cursor anzulegen, als die Werte jedesmal auszulesen.
Zitat
while (_message != 0) {
*vidmem = _message[i++];
vidmem += 2;
}
Was'n das? Mach doch aus vidmem lieber ein unsigned short Array und berechne die werte mit (zeichen | 0x0700). Mir fällt grad auf, dass du das Charcter Byte zuerst schreibst. Versuch es mal mit _message[++i] oder eben mit unsigned short.

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 09. September 2004, 15:54 »
Danke für den Vorschlag, aber eigentlich dürfte das nicht mein Momentanes Prob sein, weil in den Unterfunktionen für a20Gate und PIC init kann ich ohne probs auf den VideoMem zugreifen und etwas auf den Screen printen,
nur in main nicht. Wenn ich das da mache stürzt er ab.
Dafür muß es doch einen Grund geben!
Gruß sov21

mastermesh

  • Beiträge: 341
    • Profil anzeigen
    • http://www.kostenloser-laptop.de/
Gespeichert
« Antwort #7 am: 10. September 2004, 15:06 »
Ich hatte mal ein ähnliches Problem. Beschreib mal, wie dein Kernel gebootet wird.

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 12. September 2004, 22:30 »
Das ist ein großteil des Bootloaders, den ich verwende.
Hier hab ich nur am ende die gdt für das umschalten in den PM nicht mit gepostet.
Bootloader:

[BITS 16]       ; We need 16-bit intructions for Real mode

[ORG 0x7C00]    ; The BIOS loads the boot sector into memory location 0x7C00        


reset_drive:
        mov ah, 0               ; RESET-command
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        mov ax, 0
        mov es, ax
        mov bx, 0x1000          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command
        mov al, 17              ; Number of sectors to read = 17
        mov ch, 0               ; Cylinder = 0
        mov cl, 02h             ; Sector = 2
        mov dh, 0               ; Head = 0
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        cli                     ; Disable interrupts, we want to be alone

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 08h:clear_pipe      ; Jump to code segment, offset clear_pipe


[BITS 32]                       ; We now need 32-bit instructions
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

        jmp 08h:01000h          ; Jump to section 08h (code), offset 01000h

Danach springe ich in die Main.
Gruß sov21

mastermesh

  • Beiträge: 341
    • Profil anzeigen
    • http://www.kostenloser-laptop.de/
Gespeichert
« Antwort #9 am: 13. September 2004, 13:31 »
Bist du dir sicher, dass 17 Sektoren ausreichen? Könnt ja sein, dass dein Kernel größer ist...

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 13. September 2004, 15:42 »
Die reichen schon aus.
Weil, wenn ich andere Module rausnehme,
und dann writeln in main aktiviere gehts auch nicht.
Und wenn writeln nicht aktiv ist, dann geht alles gut.
Also zu wenig platz für den Kernel hab ich nicht.
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #11 am: 13. September 2004, 18:31 »
Das was du mit deinem Stack machst gefällt mir da irgendwie garnicht^^
Es ist besser den gleich als erstes vor dem ersten int zu initialisieren, wer weiß wo der sonst hinzeigt, ausserdem vergisst du im PM Teil des ASM dann dich ums ebp Register zu kümmern. Ausserdem solltest du bedenken dasein Stack nach unten wächst! also die Adresse kleiner wird, wenn also der Stack über deinem Kernel liegt (Kernel 0x1000 Stack 0x90000) kann es sein das der Code irgendwann überschrieben wird (ich geh davon aus das Code und Datensegment die selbe Basisadresse haben) Ok der Abstand 0x1000->0x90000 ist relativ gross aber man weiss nie was irgendwann kommt, und wenn du irgendwann einen Fehler erhällst der daran liegt findest du den garantiert nicht;)
Kann sein das alles kleinlich klingt aber ich versuche alle möglichen Fehler soft wegzukriegen bevor da ein Problem draus werden kann, genauso wie ich immer versuche Code möglichst klein zu halten^^ Mein Bootloader ist beispielweise so programmiert das exakt 512 Byte genutzt werden, wenn ich ein nop reinsetzte gibts ne Fehlermeldung weil zuviel Code wäre;)
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

sov21

  • Beiträge: 53
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 13. September 2004, 23:47 »
@Roshl:
Also meinst du ich sollte den Stack vor vor dem einlesen der Daten von der Disk
initialisieren und den Kernel hinter den Stack legen??
Warum muß man sich um ebp kümmern??
Was passiert wenn ich es nicht mache??

Ich finde es toll, wenn man einen guten Code hat, aber immerhin bin ich noch totaler Anfänger. Habe Os-proggen erst vor 4 Wochen angefangen, und deshalb leider noch nicht so die Ahnung, was man optinieren kann.
Deshalb bin ich auch sehr dankbar, wenn du mir tipps gibst.
Leider kann es dann nur passieren, daß ich dann zur realisierung dieser noch ein paar mal Nachfragen muß.
Meinst du mein Prob könnte wirklich an diesen Dingen liegen??
Gruß sov21

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #13 am: 15. September 2004, 14:52 »
Man muss sich nicht zwangläufig ums ebp kümmern, ist ne Angewohnheit aus der C-Calling Konvention, ich habs aber lieber wenn ich weiß wie die Register aussehen wenn ich damit arbeiten will und nach dem Bios weiß man das nich, denn wer weiß was das Bios damit gemacht hat, deswegen auch zuerst Stack einrichten. Beispiel:
Angenommen du hast den Stack nicht initialisiert, der zeigt sonstawohin, zum Bleistift ss=1000h esp=186h (is nurn Beispiel, aber wer weiß!!) so und du schreibst den Code auch irgendwo im 1000h'er Segment ,dann veränderst du erstens den Stack und ein Rücksprung funzt nicht mehr, oder dein Stack ändert deinen Kernel code und aus die Maus,dein Code funzt nicht mehr.
Beispiel 2:
Falls du ihn initialisierst.
Dein Kernel liegt an Addi 1000h:0 , der Stack bei 1000h:600h.
So Stack wächst nach unten also würde alles was unter 1000h:600h steht vom Stack "gefährdet" sein. Machst dus andersrum wird der Stack nachoben von ebp begrenzt also gefährdet deinen Code nicht da er nur nach unten schreibt und dein Code wird ja nicht im Stack rumpfuschen wenn dus ihm nicht sagst^^
Also jedes Register sollte so sein, dass man weiß was drin steht, sonst weiß man nie was der Prozessor damit anstellt^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

 

Einloggen