Autor Thema: Problem mit der IDT  (Gelesen 3136 mal)

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
« am: 02. March 2006, 16:14 »
Hallo,

nach langer Zeit habe ich einmal an meinem OS weiter programmiert und habe es jetzt auch geschafft in den PMode zu schalten. Jetzt möchte ich mit der IDT weiter machen. Ich habe einmal ein Interrupt Deskriptor für die Exception 0 definiert und natürlich die IDT geladen. Dann teile ich durch 0. Jetzt soll eine Nachricht ausgegeben werden. Bochs startet jedoch nur neu. Beim debuggen erscheint folgende Meldung bei der Ausführung des DIV Befehls:

Error: (0) print_guard_results: guard_found ? (stop reason 0)

Ich habe im Forum schon vergleichbare Probleme gelesen jedoch ist dort eine andere Meldung erschienen. Anbei poste ich noch meinen Kernel. Der Bootloader ist fast der selbe, wie der aus den Tutorials. Mein Code wird an 0x10000 geladen.


[BITS 16] ;16 Bit Code erstellen
jmp start ;GDT und IDT überspringen


;;;;;;;;;;;;;;;;; GDT ;;;;;;;;;;;;;;;;;;;;;;

gdt_NULL_Desc: ;Dummy Deskriptor
dd 0
dd 0

gdt_CODE_Desc:
dw 0xFFFF ;Segmentgröße Byte 0/1
dw 0 ;Segmentbasisadresse Byte 0/1
db 0 ;Segmentbasisadresse Byte 2
db 10011010b ;Zugriffsberechtigungen
db 11001111b ;Zusatz + Segmentgröße Bits 16 - 19
db 0 ;Segmentbasisadresse Byte 3


gdt_DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt:
gdt_Limit dw 0 ;Größe der GDT (wird später eingetragen)
gdt_Base dd 0 ;Adresse der GDT (wird später eingetragen)

;;;;;;;;;;;;;;;;; IDT ;;;;;;;;;;;;;;;;;;;;;;

idt_DIV_ERROR:
dw 0
dw 8
dw 0000000011111101b
dw 0

idt:
idt_Limit dw 0
idt_Base dd 0


;;;;;;;;;;;;;;;;; Daten ;;;;;;;;;;;;;;;;;;;;
Data:
VMem_Offset dd 0 ;Offsetadresse zur Textausgabe
PMode_Msg db "Willkommen im PMode",13,0
PMode_Msg2 db "CR",13,0
EX_DIV_ERROR db "Division Error",13,0


start:

cli ;Interrupts ausschalten

mov eax, cs ;EAX auf derzeitiges Codesegment setzen
mov ds, ax ;DS auf Codesegment setzen
shl eax, 4 ;EAX mit 16 multiplizieren (Lineare Adresse
;des Codesegments errechnen)
;;;;;;;;;;;;;;;;;;; GDT laden ;;;;;;;;;;;;;;;;;;;;;
mov [gdt_CODE_Desc+2], ax ;Lineare Adresse des Codesegmentes als
mov [gdt_DATA_Desc+2], ax ;Startadresse des Code- und Datendeskriptors
shr eax, 16 ;eintragen
mov [gdt_CODE_Desc+4], al
mov [gdt_DATA_Desc+4], al

mov eax, cs ;Startadresse der GDT errechnen
shl eax, 4
add eax, gdt_NULL_Desc

mov [gdt_Base], eax ;Startadresse der GDT eintragen
mov [gdt_Limit], WORD gdt - gdt_NULL_Desc -1;Größe der GDT errechnen und eintragen

lgdt [gdt] ;GDT laden

;;;;;;;;;;;;;;;;;;; IDT laden ;;;;;;;;;;;;;;;;;;;;;
mov eax, cs
shl eax, 4
add eax, DIV_ERROR_VECTOR
mov [idt_DIV_ERROR], ax
shr eax, 0x10
mov [idt_DIV_ERROR+6], ax

mov eax, cs
shl eax, 4
add eax, idt_DIV_ERROR
mov DWORD [idt_Base], eax
mov [idt_Limit], WORD idt - idt_DIV_ERROR

lidt [idt]

;;;;;;;;;;;;;;;;;;; PMODE schalten ;;;;;;;;;;;;;;;;
mov eax, cr0 ;In den Protected Mode schalten,
or eax, 1 ;indem Bit 0 des CR0 Registers auf 1
mov cr0, eax ;gesetzt wird

db 0xea ;FAR-JUMP zum Codesegment
dw PMODE
dw 0x8


[BITS 32] ;32 Bit Code erstellen

PMODE:
mov WORD [gdt_CODE_Desc+2], 0 ;Code Segmentstartaddresse auf 0 setzen
mov WORD [gdt_DATA_Desc+2], 0 ;Daten Segmentstartadresse auf 0 setzen
mov BYTE [gdt_CODE_Desc+4], 0 ;Code Segmentstartaddresse auf 0 setzen
mov BYTE [gdt_DATA_Desc+4], 0 ;Daten Segmentstartadresse auf 0 setzen

mov eax, 2 ;Selektor für das Datensegment erstellen
shl eax, 3

mov ds, ax ;Daten- Stack- und Extrasegment mit
mov ss, ax ;Datensegmentdeskriptor laden
mov es, ax
mov eax, 0 ;FS und GS mit Null-Deskriptor laden
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF ;Stack auf unterhalb der 2 MB Grenze setzen

jmp 0x8:0x10000 + PMODE2 ;Sprung in das "neue" Codesegment

PMODE2:
jmp MAIN ;Zum Ende Springen


MAIN:
sti
mov DWORD [VMem_Offset], 0 ;Videooffset auf 0 setzen
mov dl, 7
mov esi, PMode_Msg ;"Willkommen im PMode"
call putstr

mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov eax, [idt_DIV_ERROR+6]
shl eax, 0x10
mov ax, [idt_DIV_ERROR]
mov eax, 0
div eax


main_loop:
jmp main_loop


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;+------------------------------------------+;
;|Funktion: putstr    |;
;+------------------------------------------+;
;|Gibt Text auf dem Bildschirm aus (Textmodu|;
;|s).    |;
;+------------------------------------------+;
;|esi - String    |;
;|dl - Zeichenfarbe    |;
;+------------------------------------------+;
;|VMem_Offset - aktuelles Offset    |;
;+------------------------------------------+;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

putstr:
pusha
mov edi, 0xB8000 ;Adresse des Videomemories laden
mov eax, [VMem_Offset] ;Offsetadresse des Cursors laden
imul eax, 2 ;verdoppeln da Zeichenattribute folgen
add edi, eax ;di mit Adresse füllen
add esi, 0x10000 ;zur Stringadresse 0x10000 addieren, da Code hier hin geladen wurde und die Labels blos Offsets sind
putstr_loop: ;Hauptschleife zur Zeichenausgabe
lodsb ;Zeichen laden
cmp al, 0 ;Ist Nullzeichen?
je putstr_exit
cmp al, 13 ;Ist Carriage Return?
je putstr_cr
stosb ;Zeichen ausgeben
mov al, dl ;Zeichenfarbe laden
stosb ;Zeichenfarbe abspeichern
jmp putstr_loop ;Hauptschleife

putstr_cr:
mov eax, edi
sub eax, 0xB8000
mov ebx, 0xA0
mov edx, 0
div ebx
mov eax, 0xA0
sub eax, edx
add edi, eax
inc edi
jmp putstr_loop

putstr_exit:
mov eax, edi ;Neues Offset abspeichern
sub eax, 0xB8000
shr eax, 1
mov [VMem_Offset], eax
popa
ret

DIV_ERROR_VECTOR:
cli
pusha
push ds
push es
push gs
push fs
mov esi, EX_DIV_ERROR
mov dl, 3
call putstr
pop fs
pop gs
pop es
pop ds
popa
sti
iret

times 512-($-$$) db 0; ;Da der Linker sich nicht mit ungeraden
;Dateigrößen verträgt, wird diese Datei auf 512
;gepaddet.


Ich hoffe ihr könnt mir ein wenig helfen.
Gruß svler

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #1 am: 02. March 2006, 16:50 »
Hmm... Ich kann dir nicht genau sagen was falsch ist, aber VMware meckert und sagt Stack fault.

bitmaster

Kleiner Tip noch: Hör blos nicht auf die Fehlermeldungen von Bochs, denn die stimmen so gut wie nie.
In the Future everyone will need OS-64!!!

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 02. March 2006, 17:07 »
Ja, Bochs hat wirklich was an der Waffel. Ich habe jetzt das "div" Kommado auskommentiert. Ich dachte jetzt müsste ja die Endlosschleife greifen. Tatsächlich bekomme ich aber denselben Fehler. Erst wenn ich "sti" nach dem MAIN: Label auskommentiere läuft das Programm  in die Endlosschleife. Kann es sein, dass ich beim Interrupt Deskriptor beim 4. und 5. Byte etwas falsch gemacht habe. Vielleich flasch herum??? Denn der Prozessor bekommt ja offensichtlich gar nicht die Möglichkeit eine Exception bzw. einen Interrupt auszulösen.

nukthem

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 02. March 2006, 18:54 »
Hallo!

Ja du hast wahrscheinlich im IDT Deskriptor einen Fehler gemacht. Ich kann im ausführbaren Code keinen erkennen.
Das dritte WORD beim IDT Deskriptor muss folgendes Format haben:

|P|DPL|0|Typ|0|0|0|DWord-Count|

P (Present) muss 1 sein, wenn der Interrupthandler nicht ausgelagert ist
DPL (Privilegierungsstufe) sollte 00 sein
Typ sollte 1110 für ein Interrupt-Gate sein
DWord-Count brauchst du wahrscheinlich nicht und sollte deshalb 00000 sein

Um es nochmal auf den Punkt zu bringen sollte die dritte Zeile nach "idt_DIV_ERROR:" so aussehen:
dw 1000111000000000b
Nun solltest du problemlos deine Exception bekommen ^^

Außerdem solltest du nach dem Label "PMODE:" als erstes das Datensegment aktualisieren und dann erst Code Segmentstartadresse auf 0 setzen:
mov ax, 8
mov ds, ax
mov WORD [gdt_CODE_Desc+2], 0
...
...

Denn damit verhinderst du, dass die Nullen ganzwoanders in den Speicher geschrieben werden, weil in ds ja noch das Realmode Segment steht und nicht der Deskriptor für den P-Mode.

PS: Du solltest auf keinen Fall Code- und Datensegment über den kompletten virtuellen Adreßraum von 4 GB!!!! gehen lassen. Denn erstens hast du wahrscheinlich gar keine 4GB zur verfügung und zweitens sollte das Codesegment auch wirklich nur den Code enthalten den man ausführen will. Sonst kann es durch Programmfehler auch passieren, dass nichtausführbarer Code ausgeführt wird, wodurch der Prozessor abstürzt.

 

Einloggen