Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: nooooooooos am 10. October 2005, 12:56
-
Hallo
Ich bins nochmal. Wenn ich diesen Code mit Bochs, oder Diskette probiere, dann blinkt Bochs oder der Computer Schaltet sich aus. ;16 Bit Code erstellen
jmp start ;GDT überspringen
NULL_Desc:
dd 0
dd 0
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
DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt:
Limit dw 0 ;Größe der GDT (wird später eingetragen)
Base dd 0 ;Adresse der GDT (wird später eingetragen)
idt:
Limite dw 0 ;Größe der GDT (wird später eingetragen)
Basiis dd 0 ;Adresse der GDT (wird später eingetragen)
IDTAnfang:
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
dw Handler, 8, 8E00h, 0
IDTSchluss:
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)
mov [CODE_Desc+2], ax ;Lineare Adresse des Codesegmentes als
mov [DATA_Desc+2], ax ;Startadresse des Code- und Datendeskriptors
shr eax, 16 ;eintragen
mov [CODE_Desc+4], al
mov [DATA_Desc+4], al
mov eax, cs ;Startadresse der GDT errechnen
shl eax, 4
add eax, NULL_Desc
mov [Base], eax ;Startadresse der GDT eintragen
mov [Limit], WORD gdt - NULL_Desc -1 ;Größe der GDT errechnen und eintragen
lgdt [gdt]
mov eax, cs
shl eax, 4
add eax, [IDTAnfang]
mov [Basiis], eax
mov eax,[IDTSchluss]
sub eax,[IDTAnfang]
mov [Limite],eax ;Größe der IDT errechnen und eintragen
lidt [idt] ;GDT laden
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 [CODE_Desc+2], 0 ;Code Segmentstartaddresse auf 0 setzen
mov WORD [DATA_Desc+2], 0 ;Daten Segmentstartadresse auf 0 setzen
mov BYTE [CODE_Desc+4], 0 ;Code Segmentstartaddresse auf 0 setzen
mov BYTE [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
mov al,011h ; IRQ umleiten auf 20h damit keine Fehler ausgelöst wird.
out 020h,al
out 0A0h,al
mov al,20h
out 021h,al
mov al,28h
out 0A1h,al
mov al,4
out 021h,al
mov al,2
out 0A1h,al
mov al,1
out 021h,al
out 0A1h,al
sti
PMODE2:
jmp 0x8:0x10000 + PMODE2
Handler:
mov al,020h
out 020h,al
out 0A0h,al
iret
jmp Handler
Was ist daran falsch. Ich weiss nicht mehr weiter denn im Internet hat es nirgends ein Tutorial das nur eine IDT anlegt. Kann es sein, dass irgendwo im Code eine Exeption ausgelöst wird ? Bitte helft mir ich finde im Netz wirklich nichts und Englisch ist nicht so meine Sprache.
GROSSEN DANK
Dominik
-
Ich bins nochmal.
Und hoffentlich nicht das letzte mal. ;)
Wenn ich diesen Code mit Bochs, oder Diskette probiere, dann blinkt Bochs oder der Computer Schaltet sich aus.
Also wenn du es mit Bochs machst, dann blinkt Bochs (was ist damit gemeint?) und wenn du es am Real-PC machst, dann geht der aus (rebootet warscheinlich), richtig?
Was ist daran falsch.
Das ist eine gute Frage, die recht schwer zu beantworten ist. Versuch doch einmal, die Fehlerstelle mit "JMP $" zu ermitteln. Also da ein "JMP $" am Anfang einbauen und schauen, obs noch klappt. Wenn ja, dann das "JMP $" nach die nächste Anweisung oder so. So lange, bis das Problem auftritt. Dann weiß man, wo es ist und kann besser schauen, was nicht stimmt.
Ich weiss nicht mehr weiter denn im Internet hat es nirgends ein Tutorial das nur eine IDT anlegt. Kann es sein, dass irgendwo im Code eine Exeption ausgelöst wird ? Bitte helft mir ich finde im Netz wirklich nichts und Englisch ist nicht so meine Sprache.
Bitte nicht so winseln, das hört sich ja erbärmlich an. ;) Wir sind ja dafür da, dass wir helfen und uns geholfen wird.
http://www.osdever.net/tutorials.php?cat=5&sort=1
Da gibt es Tutorials, allerdings Englisch...
Wie gesagt, steck mal den Fehler ab, dann haben wir ihn sicher gleich. :)
-
Also
Mit dem Blinken von Bochs mein ich einen Neustart. Das " jmp $ " funktioniert bis zum sti. Von da an nüzt es nichts mehr, weil dann warscheninlich der Timer Interupt anfängt zu "timern".
-
Hast du mal mit dem Bochs-Debugger geschaut, was genau passiert? Wohin springt er denn nach dem STI?
-
Gute Idee !!
Aber wie geht das mit dem Debugger. Kannst du mir das mal kurz erklären ???
Danke
-
Also in meinem ganz extrem kurzen Bochs-Tutorial(http://www.chris-soft.de/tutorials/bochs/) (auf Deutsch) habe ich die wichtigsten Funktionen kurz erklärt, ist wirklich kurz genug, um einen schnellen Einblick zu kriegen.
Ansonsten frag einfach weiter.
-
Wenn ich meine Bochs-Konfigurationsdatei mit dem Debugger starte, meldet Bochs :"directive C not understood :" Diese Meldung kommt aber nicht wenn ich den normalen Bochs starte.
Wenn ich allerdings den Debugger starte und meine Kon.. Datei übers Menu auswähle geht es. Wenn ich dann mit "lb" eine Adresse eingebe und c drücke dann kommen hunderte Zeilen von "CPU Loop" Und das "Computer Fenster" von Bochs blinkt nicht wie es das im normalen Bochs Betrieb würde. Was bedeutet das ???
Danke
-
Also die Meldung "CPU_LOOP 1" habe ich auch schon öfter zu sehen gekriegt. Passiert in der Regel, wenn man in einem Speicherbereich landet, der (a) nicht existiert (weil Adresse zu hoch) oder (b) nur noch voll mit Nullen steht, also kein richtiges Programm mehr enthält.
Setze deinen Breakpoint vorher an oder gehe direkt im Einzelschritt durch den Code, da stimmt schon vorher was nicht.
-
Wenn ich den Code ab Anfang in Einzelschritten durchgehe, dann sehe ich Befehle die ich nie geschrieben habe. Was bedeutet denn das ??
Vielen Dank
Dominik
-
Tja, das ist mir auch schon passiert - passiert jedem mal. Also entweder bist du bei einer falschen Adresse gelandet (beobachte mal beim Debuggen die Adresse zu Beginn der Zeile), oder du überschreibst dir irgendwo deinen eigenen Code.
Plan B: Gib uns mal das kompilierte Objekt, ist ja nicht so groß, oder? Dann debugge ich das mal selbst.
-
Die Dateien kannst du dir hier (http://webere.we.funpic.de/OS/) herunterladen.
Vielen Dank
Dominik
-
Hi,
also ich bin noch nicht zum Debuggen gekommen, aber mir ist ein Fehler aufgefallen:
Limite dw 0
Basiis dd 0
[...]
mov [Basiis], eax
mov eax,[IDTSchluss]
sub eax,[IDTAnfang]
mov [Limite],eax
Das kann so natürlich nicht funktionieren: Zuerst schreibst du die vier Byte "Basiis" und anschließend weitere vier (!) Byte "Limite", dabei ist das Limit nur mit zwei Bytes definiert. Du überschreibst also zwei Bytes der Basis.
Schau mal, ob du so weiter kommst, ansonsten schau ich nochmal.
Gruß!
-
Also diesen Fehler verbessere ich so:
Limite dw 0
Basiis dd 0
[...]
xor ax,ax
mov eax, cs
shl eax, 4
add eax, [IDTAnfang]
mov [Basiis], eax
xor ax,ax
mov ax,[IDTSchluss]
sub ax,[IDTAnfang]
mov [Limite],ax
lidt [idt]
Das Programm läuft allerdings immer noch nicht korrekt.
Gruss
Dominik
-
Wäre gut, wenn du die Zeile angeben könntest, ab der in Bochs nicht mehr das passiert, was in deinem Code passieren soll (also Debuggen und die entsprechende Zeile hier angeben), das wäre für mich einfacher.
-
Wenn ich die Datei debugge dann komme ich (noch im Bootloader) bis zu "0x7c38" Dort beginnt die Schleife, welche das Wort "Loading..." schreibt. Sobald das Wort fertig geschrieben ist und ich in bochsdbg "s" drücke kommt CPU Loop. Wiso?
Vielen Dank
Dmk
-
Vor heute Abend komme ich nicht dazu, dann werde ich mich aber mal drum kümmern. Ich melde mich dann.
-
Kannst du mal die aktuellste Version ins Verzeichnis stellen und Bescheid geben?
-
Jetzt wär die aktualisierte Version drauf.
-
Hi,
nimm's mir nicht übel, aber das Image in deinem Verzeichnis kann UNMÃGLICH dem Kernel-Source entsprechen, den du da mit rein gepackt hast.
Der erste JMP-Befehl im Kernel stimmt noch, aber was danach in Bochs zum Debuggen bereit steht ist auch exakt das, was ich im Hex-Editor in deinem Image an der entsprechenden Stelle finde.
Fazit: Ich komme nicht weiter.
Gruß.
-
Ah habe vieleicht vergessen zu sagen, dass im Image vor dem Kernel noch der Bootloader kommt. Den Code ist auch im Verzeichnis.
Dmk
-
Das ist mir schon klar, dass der Bootloader die ersten 512 Byte vom Image ausmacht und ab dem 513. Byte der Kernel dann kommt. Aber in dem von dir angegebenen Sourcecode steht im kernel zuerst der JMP-Befehl und dieser verweist auf die Stelle 01a7. Dort sollte dann der CLI-Befehl stehen - jedenfalls laut Source. Tatsächlich steht dort aber ein MOV-Befehl. Das kann man in Bochs sehen und auch im Image, wenn man einen Hex-Editor zu rate zieht.
Fakt: Der Kernel-Source und das Image passen nicht zusammen. Und somit ist es mir auch nicht möglich zu sagen, wo dein Fehler steckt.
-
Ja also bei mir hat es da noch geklappt. Ich hab jetzt das Image extra nochmals neu "kompiliert". Sonst weiss ich nicht mehr weiter.
-
Hi,
also nimm's mir nicht übel, wenn ich dir das hier mal ganz direkt sage: Ich bin ein wenig sickig.
Ich habe dir schon geschrieben, dass das Image in deinem Verzeichnis unmöglich mit dem Sourcecode des Kernels übereinstimmen kann und du hast mir gesagt, jetzt wäre alles passend und so.
Ist es nicht!
Also es gibt zwei Möglichkeiten: Entweder dein Assembler ist hinüber (halte ich für nicht so wahrscheinlich, aber die Möglichkeit will ich zumindest mal in Betracht ziehen) oder aber du bist nicht in der Lage, eine überalterte Version deines Images zu überschreiben.
Aber okay, ich möchte nicht beleidigend wirken, daher schreibe ich dir einfach detailiert auf, was mir nicht passt:
Im Hex-Editor finde ich an den Adressen 0000 bis 01ff den Bootsektor. Ab 0200 findet sich dann der Kernel. Soweit in Ordnung.
An Stelle 0200 steht:
0200 e9 a4 01
Das entspricht dem "jmp start" in deinem Kernel-Source, nämlich "jmp 0x1a7".
An dieser Stelle (plus 0200, wegen dem Bootsektor) finde ich folgendes:
03a7 b0 4b
Das wiederum bedeutet "mov al, 0x4b". In deinem Kernel finde ich an dieser Stelle aber ein "cli".
Ich wiederhole: Das Image, das du uns mitgegeben hast, gehört nicht zu den mitgelieferten Sourcen.
Gerne helfe ich dir bei deinem Problem weiter, aber ich glaube, dass du erstmal ein eigenes Problem mit dem Zusammenbasteln deines Images lösen möchtest. Und wenn du das gefunden hast, gib Bescheid, dann helfe ich gerne weiter.
Vielleicht beschreibst du einfach mal, wie du womit übersetzt und dann das Image bildest, vielleicht machst du da ja unbewusst einen Fehler...
Nimm mir meine harschen Anfangsworte bitte nicht übel!
Gruß!
-
Also, ich kompiliere zuerst die boot und kernel Datei mit Nasm zu Bin-Dateien. Dann kopiere ich diese mit dem "copy" Befehl zu einem Image zusammen.
Vieleicht hilft das
Dmk
-
Das ist korrekt soweit - der Fehler muss irgendwo anders liegen. Ich bleibe dabei: Das Image entspricht nicht dem Source.
-
Ich weiss. Ich lad dir jetzt noch das Binary und die Bochs-Konfigurationsdatei hoch, damit du es selbst nomals kompilieren usw. kannst. (Ich denk mal du hast NASM) Wenn es dann immer noch nicht stimmt weiss ich nicht mehr weiter.
Gruss
Noooooooooos
PS: Ich fahre diese Woche in die Ferien, darum kann es sein, dass ich nicht so schnell antworten kann.
-
Ich weiss nicht mehr weiter. Ich hab keine Ahnung, warum das Image nicht stimmt. Ich bin jetzt von den Ferien zurück und werde mir nochmal alles anschauen.
Gruss
Noooooooooos
-
Ich gestehe, dass ich mich in der letzten Woche nicht drum gekümmert habe, aber es ist nicht in Vergessenheit geraten! Poste hier, falls du was raus kriegst.
-
So. Ich hab jetzt das ganze Image durchgemacht bis zum sti. Bei mir funktioniert es. Es ist eigentlich komisch, denn nach dem sti hab ich nur meine Endlosschleife, welche ich auch im Bochs-Debugger sehe. Vom Timer-Interupt merkt man nichts.
An Stelle 0200 steht:
0200 e9 a4 01
Das entspricht dem "jmp start" in deinem Kernel-Source, nämlich "jmp 0x1a7".
An dieser Stelle (plus 0200, wegen dem Bootsektor) finde ich folgendes:
03a7 b0 4b
Warum "An dieser Stelle plus 0200, wegen dem Bootsektor", ich denke man kann im B-Debugger einfach ein "s" eingeben, dann springt Bochs doch völlig alleine zum Ziel des Sprunges.
Jedenfalls kommt nach dem sti die planmässige Endlosschleife und nirgends etwas vom Timer. Was bedeutet das, muss ich vieleicht dem Computer etwas besseres als die Schleife geben ??
-
Wenn du also immer Einzelschritte ausführst funktioniert alles, aber falls du den Code durchlaufen läst stürtzt Bochs/der PC ab?
-
Jep, genau so.
Nooooooooooos
-
Habt ihr denn alle in euerem OS schon Interrupts ?
Hat es bei euch geklappt ?
Kann es sein, dass der Fehler ausserhalb vom IDT-Zeugs liegt ?
Gruss
Dominik
-
hi,
also mein OS hat schon eine IDT und Interrupts, ich hatte auch nie wirklich Probleme damit. Ich initialisiere meine IDT auch erst im PMode.
Du musst auch drauf achten, dass "lidt [ds:xx]" wirklich die IDT-Adresse bilden, nicht dass sich DS und ein entsprechender ORG Befehl in die Quere kommen !
Wenn du nicht weiterkommst, kann ich dir ja mal ein wenig von meinem IDT Code zeigen/hier posten.
cu,
stefan2005
-
Ãhm, ja ich wäre vieleicht mal froh um einen einzelnen Eintrag in deiner IDT und um das ganze Zeugs um die Adressen und die "Anmeldung" der IDT. Dann könnt ich ihn mal mit meinem Code verglichen.
Gruss
Nooooooooos
-
hi,
ok, hier die wichtigsten Funktionen meiner IDT.
"InitIDT" rufe ich erst auf, nachdem ich in den PMode geschalten hab.
ist jedoch in Delphi Langauge bzw halt Pascal geschrieben, sollte aber verständlich sein :)
type
TIDTR = packed record
Limit : Word;
BaseAddr : Cardinal;
end;
TIDT = packed record
Offset_Low : Word;
Segment : Word;
Attributes : Word;
Offset_High : Word;
end;
var IDTR : ^TIDTR = Pointer($B000);
gIDT : Array of TIDT = Pointer($B006);
procedure InitIDT;
begin
IDTR.Limit := 256*SizeOf(TIDT)-1;
IDTR.BaseAddr := $B006;
asm
lidt [$B000]
end;
end;
procedure RegisterIDTEntry(IntNumber: Word;ProcPointer: Pointer;DPL: Cardinal);
var Attributes : Word;
begin
If DPL = 0 then Attributes := $8E00
Else If DPL = 1 then Attributes := $AE00
Else If DPL = 2 then Attributes := $CE00
Else Attributes := $EE00;
gIDT[IntNumber].Offset_Low := (Integer(ProcPointer) AND $FFFF);
gIDT[IntNumber].Offset_High := (Integer(ProcPointer) SHR 16);
gIDT[IntNumber].Segment := $8;
gIDT[IntNumber].Attributes := Attributes;
end;
Wenn du noch Fragen hast, auch bzg. des Codes kannst du sie ruhig stellen.
cu,
stefan2005
-
Ja also zuerst mal, wie bindet man den Delphi-Code ein ??? Und kannst du mal einen einzelnen Eintrag in der IDT posten ?? Und was für Label musst du in und um die IDT hinmachen ? Und oder in Delphi folgt nach ":" Kommentar.
Vielen Dank
Noooooooooos
-
Also, ich finde das irgendwie komisch, denn im Debugger arbeitet das Programm wie gewünscht, aber sonst nicht. Weiss wirklich niemand, an was das liegen könnte ??????
Vielen Dank
Noooooooooos
-
Ãhm, das ist jetzt vieleicht eine blöde Frage, aber wenn ich als Selektor in der IDT den zweiten Eintrag (nach dem null-Deskriptor) muss ich in der IDT 8 oder 16 oder 2 oder 4 schreiben ?
Reicht der Stack vom Real-Mode auch im PM. Könnte das Problem daran liegen, dass nach dem "iret" im Stack nicht die richtige Adresse gnommen wird.
Und wie soll ich den Timer einschalten, mit welcher Frequenz?
Danke
NOOOOOOOOOOOOOOOS