von Bootloader den Kernel anspringen



  • Hallo!

    Bin gerade dabei, mich an einem kleinen OS zu versuchen.
    Hab nun schon einige kleine Versuche im Kernel umgesetzt, jetzt ist das 512 byte Limit erreicht.

    Gut, also habe ich mir einen Bootloader gebastelt.
    Den Kernel hab ich nun angepasst indem nun org 0x10000 oben hinschreibe.
    Außerdem setze ich ss, ds und es auf 0x1000.
    Mit jmp 0x1000:0 springe ich den Kernel an.

    Nun scheint zwar teilweise Kernelcode ausgeführt zu werden (es wird der Text aus der main loop ausgegeben), allerdings funktioniert sonst fast nichts.
    Keine Timer Interrupts, Funktionsaufrufe mit call schlagen teilweise fehl, usw...

    Was muss ich sonst noch beachten, wenn ich vom Bootloader aus den Kernel anspringe? cs wird mir ja hoffentlich richtig gesetzt, wenn ich jmp 0x1000:0 mache, oder?

    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId317268

    Hier der Code aus dem henkessoft.de Tutorial, laut dem es mit den beiden Änderungen getan wäre.

    ;---neu---
      mov ax, 0x1000  ; set up segments
      mov ds, ax
      mov es, ax
    ;---neu---
    
      mov si, welcome
      call print_string
    
    loop:
      mov si, prompt
      call print_string
    
     ... (siehe oben)
    
    .done:   
      stc            ; equal, set the carry flag
      ret
    
    ;---neu---
      times 512-($-$$) hlt ; no boot signature
    ;---neu---
    


  • Was muss ich sonst noch beachten, wenn ich vom Bootloader aus den Kernel anspringe?

    Mir fällt spontan nichts ein - der Kernel findet das System so vor, wie der Bootloader es hinterlassen hat. Je nach Sprungadresse kann es natürlich ratsam sein, Stackpointer, etc. neu zu setzen.

    Funktionsaufrufe mit call schlagen teilweise fehl

    -> Stackpointer? Codesegment (CS-Register)?



  • Fuer Funktionsaufrufe mit call musst du, wie schon gesagt, den Stack richtig setzen. Also SS korrekt laden und SP auf eine hohe Adresse setzen (der Stack waechst abwaerts).
    Bezueglich der Timer-Interrupts: Hast du auch Interrupts mit sti erlaubt und den Handler richtig gesetzt (die IRQs sind im Realmode vom Bios her glaub ich etwas anders gemapped, damit sie nicht mit den BIOS-Interrupts kollidieren). Ausserdem musst du dem PIC immer mitteilen, dass du den Interrupt abgebarbeitet hast, sonst merkt er sich neue nur, ohne sie an die CPU weiter zu leiten (Code ist weiter unten im Tutorial in C, sollte sich aber auch in ASM bewerkstelligen lassen).



  • hab den fehler gefunden, im IVT hab ich noch das "alte" segment 0 angegeben, von der zeit, als der kernel noch im segment 0 zu finden war.
    jetzt, da er ja im segment 0x1000 liegt, muss ich natürlich die adresse anpassen.

    folglich ist im falle eines interrupts irgendein mehr oder weniger zufälliger code ausgeführt worden.

    ; IVT, Eintrag 8 (PIT) setzen auf den Handler pit_handler
    	; | segment | offset | <-- 4byte insgesamt
    	xor ax,ax ;mov ax, IVT_SEGMENT_NR
    	mov gs,ax
    	mov bx,PIT_IRV_NR
    	shl bx,2 ;bx=bx*4
    	mov word [gs:bx], pit_handler
    	add bx,2
    	mov ax,SEGMENT_NR <-- hier war noch 0x0 angegeben!
    	mov word [gs:bx], ax
    

Anmelden zum Antworten