Kernel wird nicht geladen



  • tag,
    ich hab mir jetzt aus irgendsonem Tutorial den stage1-Bootloader genomen und von PrettyOS den stage2-Bootloader(PM) und jetzt funktioniert der Bootloader wenigstens, zumindest mit dem PrettyOS-Kernel.
    nehm ich aber meinen eigenen Kernel (von einem anderen Tutorial) dann schreibt Bochs:

    ...
    Now loading Kernel...
    Floppy Disk Motor switched off...
    Now Switching to Protected mode(PM)...

    und dann kommt nichts mehr außer dass die Floppy-"Lampe" in Bochs ausgeht.
    In der Bochs-Konsole steht auch nichts.

    Mein Format vom Kernel ist/war pe-i386 weil was anderes ging nicht und bei "Binary" sagte mir LD: "cannot perform PE operations..."

    dann hab ich im Makefile auf "binary" gestellt und den Crosscompiler/linker von Lowlevel genommen und er linkt auch wieder richtig aber es kommt das gleiche Problem.
    Assembler ist NASM und Compiler MinGW

    Makefile: http://pastebin.com/1r9XGsDC
    ckernel.c: http://pastebin.com/EMXaNMWy
    kernel32.asm: http://pastebin.com/GU0RPW8J


  • Mod

    Dann nimm doch das Makefile und den Kernel von PrettyOS und lade deinen Code innen rein. Etwas Bewegung muss schon sein. 😉



  • Wie meinst du das jetzt?
    kernel.ld und kernel.asm nehmen und ckernel.c nur die main() reinschreiben!?
    ich hab da grade keine ahnung wie ich da smachen soll


  • Mod

    nur die main() reinschreiben

    Ja, ich würde von etwas Funktionierendem ausgehen, und dann weitere Versuche machen. Fehlermöglichkeiten gibt es zuhauf, das führt zu nichts außer dem üblichen Abbruch der eigenen Versuche. Daher habe ich im Tutorial die Vorgehensweise so beschrieben, dass man sie praktisch exakt nachstellen kann. Da gehören auch die Tools dazu.


  • Mod

    Falls dir meine Vorgehensweise nicht gefällt, hier gibt es weitere praktische Anleitungen:

    http://www.lowlevel.eu/wiki/Teil_1_-_Entwicklungsumgebung (9 Teile; eher Linux-Fans)
    http://www.brokenthorn.com/Resources/OSDev1.html (über 20 Kapitel; MSVC++)



  • mein Problem ist auch irgendwie dass ich schon haufenweise Tutorials ausprobiert habe und es eigentlich fast immer zu dauerneustarts und fehlermeldungen in bochs gekommen ist.

    irgendwie scheint es am ckernel zu liegen.
    wenn ich schreibe:

    void _main()
    {
    asm("hlt");
    }
    

    dann schreibt BOCHS in die konsole:
    WARNING: HLT instruction with IF=0!

    aber er schreibt den Text nicht wenn ich das schreibe:

    void _main()
    {
    	char *Text = "Welcome to Protected Mode";  
    	char *VideoMem = (char*)0xA8000;  
    
    	while(*Text)  
    	{  
    		*VideoMem = *Text;  
    		*VideoMem++;  
    		*VideoMem = 7;  
    		*VideoMem++;  
    		*Text++;  
    	}
    for(;;){};
    }
    

    😕


  • Mod

    Probiere mal 0xB8000 anstelle 0xA8000, VideoMem++ anstelle *VideoMem++ und zum Schluss nur Text++ anstelle *Text++.
    Siehe: http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId483279 und http://www.henkessoft.de/OS_Dev/Bilder/Speicherbelegung.JPG



  • 🙂 danke funktioniert jetzt.

    //kann ich es eigtenltich erstmal vernachlässigen dass Qemu immernoch immer neustartet?



  • ok, wieder nen neues problem.
    wenn ich jetzt den video.c code vom PrettyOS-Tutorial in ckernel.c schreibe funktioniert dieser auch, aber wenn ich das wie im Tut. getrennt in die video.c schreibe und in der ckernel.c das mit

    extern...
    

    mache bleibt er wieder bei "now switching to protected mode(pm)..." stehen.

    void k_clear_screen()
    {
        unsigned long* vidmem = (unsigned long*) 0xb8000;
        unsigned long i=0;
        while(i<(40*25))
        {
            vidmem[i] = 0x0A200A20; // intensive green on black, Space (0x20)
            ++i;
        };
    };
    
    unsigned int k_printf(char* message, unsigned int line, char attribute)
    {
        char* vidmem = (char*) 0xb8000;
        unsigned int i = line*80*2;
    
        while(*message!=0)
        {
            if(*message=='\n') // check for a new line
            {
              line++;
              i=(line*80*2);
              *message++;
            }
            else
            {
              vidmem[i]=*message;
              *message++;
              ++i;
              vidmem[i]=attribute;
              ++i;
            }
        };
        return 1;
    };
    
    inline void outportb(unsigned int port,unsigned char value)
    {
        asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
    };
    
    void update_cursor(int row, int col)
    {
        unsigned short position=(row*80) + col;
    
        // cursor HIGH port to vga INDEX register
        outportb(0x3D4, 0x0E);
        outportb(0x3D5, (unsigned char)((position>>8)&0xFF));
        // cursor LOW port to vga INDEX register
        outportb(0x3D4, 0x0F);
        outportb(0x3D5, (unsigned char)(position&0xFF));
    };
    

  • Mod

    Ist doch schön, dass es nun bei dir klappt. Du solltest in kleinen Schritten experimentieren, damit Du die Fehlerursache selbst erkennen und beheben kannst.
    Coden und anschließend um Hilfe rufen ist bei OSDev nicht ernsthaft durchführbar. ;):D



  • wenn man das problem irgendwo erkennen könnte.. 😞
    egal ich probier mal weiter...



  • ruf ich clear_screen auf aus video.c wird der bildschirm geleert, aber wenn ich danach andere Methoden aufrufe passiert das nicht.
    In der Bochs-Konsole steht dann

    WARNING: HLT instruction with IF=0!

    aber es steht ja nirgendswo HLT bzw. asm("hlt"); in video.c
    das kommt halt auch wenn ich ne andere Methode aus video.c an den Anfang schreibe (nachdem diese ausgeführt wurde). 😕 ^^



  • *message++; <-- Bei sowas ist das * überflüssig (wie ehenkes sagte). Du willst den Pointer ja nur verschieben, nicht dereferenzieren.

    Ansonsten fehlts mir irgendwie an code... Ich hab nicht ganz den Überblick, wie dein OS jetzt aussieht. Wo steht jetzt ein hlt? Wie werden jetzt welche Funktionen aufgerufen und deklariert? Wann passiert jetzt was?

    wenn ich jetzt den video.c code vom PrettyOS-Tutorial in ckernel.c schreibe funktioniert dieser auch, aber wenn ich das wie im Tut. getrennt in die video.c schreibe und in der ckernel.c das mit
    extern...
    mache bleibt er wieder bei "now switching to protected mode(pm)..." stehen.

    Dann machst Du sicherlich was falsch. Aber wenn wir keinen Code zu sehen kriegen (der die entsprechenden Stellen zeigt), können wir dir nicht helfen 🙂



  • ckernel.c:

    extern void clear_screen();
    extern void update_cursor(int row, int col);
    extern void print(char* Text, char attribute);
    
    int _main()
    {
        clear_screen();
        print("Hallo", 0x07);
    
        for(;;);
        return 0;
    }
    

    video.c:

    #include "video.h"
    
    inline void outportb(unsigned int port,unsigned char value)
    {
        asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
    }
    
    void update_cursor(int row, int col)
    {
        position=(row*80) + col;
    
        // cursor HIGH port to vga INDEX register
        outportb(0x3D4, 0x0E);
        outportb(0x3D5, (unsigned char)((position>>8)&0xFF));
        // cursor LOW port to vga INDEX register
        outportb(0x3D4, 0x0F);
        outportb(0x3D5, (unsigned char)(position&0xFF));
    }
    
    void print(char* Text, char attribute)
    {
        while(*Text)
        {
            *vidmem = *Text;
            vidmem++;
            *vidmem = attribute;
            vidmem++;
            Text++;
        }
    }
    
    void clear_screen()
    {
        i = 0;
        while(i < 4000)
        {
            vidmem[i] = ' ';
            ++i;
            vidmem[i] = 0x07;
            ++i;
        }
    }
    

    video.h

    #ifndef VIDEO_H
    #define VIDEO_H
    
    char* vidmem = (char*) 0xB8000;
    unsigned int i;
    unsigned short position;
    
    inline void outportb(unsigned int port,unsigned char value);
    void update_cursor(int row, int col);
    void print(char* Text, char attribute);
    void clear_screen();
    
    #endif
    

    clear_screen(); macht er und dann steht da "warning: HLT..."
    und print("Hallo", 0x07); macht er nicht mehr.



  • Sooo... Jetzt weiß ich auch, worum es geht. (Auch wenn ich nicht genau weiß, warum dein Code nicht tut, was er soll.) 🙂

    Das Schlüsselwort "extern" ist übrigens in dem Zusammenhang. in dem Du es nutzt, nicht nötig, wenn auch nicht schädlich. Es ist nur bei Variablendeklarationen nötig, weil diese Variablen andernfalls bereits definiert sind und damit angelegt werden.
    Zudem solltest Du den Header video.h includieren, statt in main.c die Funktionen zu deklarieren 😉

    Allerdings hast Du an entscheidenden Stellen das Schlüsselwort "extern" vergessen, auch wenn das vermutlich bei deinem Code (noch) kein spürbares Problem darstellt. Du darfst _niemals_ in einem Header Variablen definieren (sondern nur mit extern deklarieren), weil dann in jeder Datei, die den Header includiert, eine eigene Variable angelegt wird. Das sollte dann zu Linkerfehlern führen. (GCC benimmt sich da eigenartig, ich empfehle, Code mit dem Flag -fno-common zu übersetzen, damit solche Fehler angezeigt werden)
    Von den Variablen, die derzeit global sind, solltest Du i aber zu einer lokalen Variable von clear_screen machen.

    Ansonsten fallen mir in deinem Code keine Fehler auf.


  • Mod

    Ich sehe auf die Schnelle auch keinen Grund, warum das stoppt. Hast du diese print-Funktion nicht schon erfolgreich verwendet? Wo genau steigt der Code aus?
    Teste mit bochs debugger.

    http://www.henkessoft.de/OS_Dev/OS_Dev2.htm#mozTocId939575



  • http://www8.pic-upload.de/26.02.11/oblbzbmdads.jpg

    der springt wohl nach clear_screen direkt ans/hinters ende vom ckernel, im asm-kernel der den ckernel läd steht nach dem call auch cli und hlt.

    wenn ich

    clear_screen();
    asm("hlt");
    print("Hallo", 0x07);
    

    schreibe, schreibt der Debugger das Gleiche (hält nicht bei asm("hlt"); ) und wenn ich das
    asm("hlt");
    ans Ende von void clear_screen() (nach der while-schleife) schreibe bleibt er da stehen. also hört er irgendwie nach clear_screen mit dem ckernel auf.

    //wenn ich das print("Hallo", 0x07); vor clear_screen() aufrufe schreibt er erst garnicht. nur son paar befehle:
    http://www8.pic-upload.de/26.02.11/x8cvyq5l6xw.jpg
    (nach leave kommt wieder cli, hlt)


  • Mod

    Das Problem sollte bei print oder in deinem makefile liegen.
    Verwende mal unsigned char (außer bei Text).
    char ist normalerweise signed char.
    Sollte aber eigentlich nicht der Grund sein.
    Immerhin kannst Du nun mit dem Debugger umgehen.
    Gehe schrittweise durch und analysiere genau.



  • ich hab das jetzt nochmal vereinfacht und nach meinem wissen ne "zeichnung"/screenshot gemacht (find ich wirklich verwirrend):

    http://www8.pic-upload.de/26.02.11/2nyfhxitfkvs.jpg


  • Mod

    http://www.henkessoft.de/C/C-Programming Under The Hood.htm
    Dort findest Du die Abläufe beim Aufruf einer C-Funktion.

    Ansonsten: Analytisch gehst du das Thema nun wirklich gut an. Auf diese Weise wirst Du es schaffen. Immer nur einen Schritt nehmen und alles checken.


Anmelden zum Antworten