Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: Hunter am 05. January 2007, 16:52
-
Hallo,
Mein Betriebssystem ist in drei Teile aufgeteilt (bootloader,system,kernel)
Der Bootloader lädt dabei die Datein system und kernel.bin ... nun tritt bei mit ein sehr seltsamer Fehler auf:
Wenn der Kernel eine größe unter 65536 Bytes hat funktioniert alles wunderbar ... doch wenn ich jetzt eine Codezeile hinzufüge (bsp. Textausgabe) wird der kernel größer als 65536 und bochs startet sofort neu bevor überhaup der Kernel aufgerufen wurde ... meine Vermutung ist dass es am Bootloader liegt ... ich glaube mal gehört zu haben, dass das Bios nur 64KB über die DMA laden kann ...
Ich verzweifle an diesem Problem bitte helft mir ...
Hunter
-
hi,
na ja es ist schwierig das ohne Code zu sagen, aber die Segmentgröße beträgt 64 KB im RealMode, deshalb kann das BIOS nicht mehr als 64 KB hintereinander von einem Datenträger in den RAM lesen.
Liegt die Datei direkt hintereinander auf dem Datenträger oder verwendest du ein Dateisystem wie FAT ?
Bei ersterem trifft warscheinlich das oben beschriebene Problem auf. Eine Möglichkeit dies zu beheben wäre einfach die Datei in mehreren Schritten dann einzulesen (erst bis 64 KB, dann die nächsten 64 KB, usw ...).
Grüsse,
Stefan
-
Ohne code bringt das nicht viel. (wie bereits erwähnt) interesant währe hier der booter insbesondere die rotine die den kernel in den speicher copieren soll. bzw eine grobe erklährung was dein code da so macht. Welche ints verwendest du? von was bootest du? FD, HD oder CD? , ...
In welchen mode copierst du deinen kernel in den speicher? daran gedacht das ein segment nur 64k gross ist (RM)? und du somit nen lustigen überlauf produzierst? zumindest meine vermutung
gruss.
-
Also ich verwende eine Floppy Laufwerk mit FAT12 Dateisystem ... Der Bootloader lädt die Datein Kernel.bin und System.bin, anschließend springt er zur System Datei ... hier werden Vesa,A20,GDT,... initialisiert und dann in den PM geschalten ... der Kernel ist an die Adresse 0x10000 geladen .. dorthin springt er wenn in PM geschalten wurde ... wie gesagt wenn die datei kleiner als 64K ist funznt alles (CD,FD,Paging,Multitasking...)
Hier der Boot-Code
;##########################################################
;########### Bootloader starten ###########
;##########################################################
jmp short start
nop
;##########################################################
;########### FAT Tabelle holen ###########
;##########################################################
%include "FAT.inc"
;##########################################################
;########### ------------------ ###########
;##########################################################
start:
jmp 0x7C0:write_cs
;##########################################################
;########### ------------------ ###########
;##########################################################
write_cs:
mov ax,cs
mov ds,ax
mov es,ax
mov gs,ax
mov fs,ax
mov ax,0xAC0
mov ss,ax
mov sp,0x200 ; stack linear addr 0x7BFF
;##########################################################
;########### Lade-Nachricht ausgeben ###########
;##########################################################
mov si, Loading
call PrintMsg
;##########################################################
;########### Rootverzeichnis festlegen ###########
;##########################################################
mov cx,[Root_Groesse] ; Größe des Rootverzeichnisses
call Sektor_Lesen ; Rootverzeichnis laden
;##########################################################
;######### 1 Prozess ( System.sys ) Laden ########
;##########################################################
mov si,KernelName
mov [DateiSegment] , word 0xFFF
mov [DateiOffset] , word 0x10
call Lade_Sektor ; Lade_Sektor funktion ausführen
;##########################################################
;######### 2 Prozess ( Kernel.sys ) Laden ########
;##########################################################
mov si,SystemName
mov [DateiSegment] , word 0x240
mov [DateiOffset] , word 0x0
call Lade_Sektor ; Lade_Sektor funktion ausführen
jmp 0x240:0x0
hlt
;##########################################################
;########### Sektor Laden ###########
;########### ###########
;########### - Suchen auf A:\ ###########
;########### - Gefundenen Eintrag laden ###########
;##########################################################
Lade_Sektor:
mov bx,0x7C0 ; Segment auf 0x7C0 festlegen ( 0x7C0:0x000 )
mov es,bx ; ES das Segment zuweisen
mov cx , word [MaxRootEntries]
mov di , 0x200
.1:
pusha
mov cx , 0x000B ; CX = 11 weil Fat-Eintrag aus 11 Zeichen besteht
rep cmpsb
popa
je Gefunden ; Wenn Datei gefunden zu Gefunden hüpfen
add di , 32
loop .1
jmp Error
ret
Gefunden:
mov ax , [di+26]
call FAT_2_LBA ; FAT Adresse (DI) in LBA konvertieren
mov [Datei_Start] , ax ; AX (LBA-Adresse) in Datei_Start kopieren
mov ax , [di+28]
call Bytes_2_Sektors ; Berechnen wieviel Sektoren die Bytes in AX entsprechen
mov cx , ax
mov ax , [Datei_Start]
mov [LBA] , ax
;mov si, Datei_Start
;call PrintMsg
call Sektor_Lesen
ret
;##########################################################
;########### Bytes auf Sektoren ###########
;########### aufteilen ###########
;##########################################################
Bytes_2_Sektors:
xor dx,dx ; DX = 0
div word [BytesPerSector]
cmp dx , 0 ; DX mit 0 vergleichen
jz .1 ; Wenn DX = 0 springe zu .1
inc ax
.1
ret
;##########################################################
;########### Wenn Fehler auftritt ###########
;########### alles Ordnungsgemäß beenden ###########
;##########################################################
Error:
mov si , ErrorMsg ; Error Nachricht in SI kopieren
call PrintMsg ; Text ausgeben
xor ax , ax
int 0x16 ; Warte auf Tastendruck (int 16h)
mov ax , 0x64 ; HEX-Wert 0x64 in AX schreiben
out 0x64 , ax ; Computer neu starten
cli
hlt ; Alles anhalten
;##########################################################
;########### Ausgabe von Texten ###########
;##########################################################
PrintMsg:
mov ah , 0x0E
mov bh , 0
mov bl , 15
.1
lodsb
cmp al , 0
je .2
int 0x10
jmp .1
.2
ret
;##########################################################
;########### Sektoren einlesen ###########
;##########################################################
Sektor_Lesen:
mov ax , [LBA]
.1:
push cx ; CX in Stack sichern
call LBA_2_CHS
.2
mov es , [DateiSegment] ; Datei Segment in ES kopieren
mov bx , [DateiOffset] ; Datei Offset in BX kopieren
mov ax , 0x0201 ; AH = 02-Sektor laden | AL = 01-Sektor1
mov dl , [DriveNumber] ; Laufwerknummer ( 00 für A: )
int 0x13 ; Lesen des Sektors
jc .2
add bx , [BytesPerSector] ; BX = BX + 0x200 ( 1 Sektor - 512 Bytes )
mov [DateiOffset] , bx ; Dateioffset ist BX ( Um 512 Bytes größer )
mov si , Ladezeichen ; Punkt für Laden zeichnen
call PrintMsg ; Ausgeben des Punktes
mov ax , [LBA] ; AX = LBA
inc ax ; AX = AX + 1
mov [LBA] , ax ; LBA = AX ( LBA = LBA + 1 )
pop cx ; CX aus Stack wieder auslesen
loop .1 ; CX gibt an wie oft wiederholt wird
mov [DateiOffset] , word 0 ; Wenn fertig, Dateioffset auf 0 setzen
mov dx , 0x3F2 ; Floppy stoppen
mov al , 0x0C
out dx , al
ret
;##########################################################
;########### LBA in CHS umwandeln ###########
;########### LBA auf Tracks,Heads,. aufteilen ###########
;##########################################################
LBA_2_CHS:
xor dx , dx ; DX = 0
mov bx , [SectorsPerTrack] ; BX = 0x0012 ( 18 Sektoren )
div bx
inc dx ; DX = DX + 1
push dx ; DX im Stack zwischenspeichern
xor dx , dx ; DX = 0
mov bx , [NumHeads] ; BX = 0x0002 ( 2 Tracks )
div bx
mov ch , al ; CH = Track
mov dh , dl ; DH = Head
pop ax
mov cl , al ; CL = Sektor
ret
;##########################################################
;########### FAT in LBA umwandeln ###########
;########### alles Ordnungsgemäß beenden ###########
;##########################################################
FAT_2_LBA:
sub ax,0x2 ; AX = AX - 0x2
add ax,[Data_Start] ; AX = AX + 33
ret
;##########################################################
;########### Variablen deklarieren ###########
;##########################################################
Root_Groesse dw 14
Root_Start dw 19
Data_Start dw 33
LBA dw 19
DateiSegment dw 0x7E0
DateiOffset dw 0x0
Datei_Start dw 0
SystemName db "SYSTEM BIN"
KernelName db "KERNEL BIN"
Loading db 13,10,"OS wird geladen ",0
ErrorMsg db 13,10,"Datei nicht gefunden!",0
Ladezeichen db '²',0
;##########################################################
;########### Datei mit 0er ausfüllen ###########
;##########################################################
times 510-($-$$) db 0 ; Mit 0er ausfüllen
sign dw 0xAA55 ; Bootsignatur
-
dein problem liegt in der segment größe von 64k
Sector_Laden:
...
add bx , [BytesPerSector] ; BX = BX + 0x200 ( 1 Sektor - 512 Bytes )
mov [DateiOffset] , bx ; Dateioffset ist BX ( Um 512 Bytes größer )
...
wenn du mehr als 64k größe datein lädst, dann wird bx irgendwasnn von 0xffff(64k) auf 0x0000 umspringen dabei wir d aber das Cary-Flag gesetzt, du kanst dies also durch eine korrektur des segments wieder wett machen
..
add bx , [BytesPerSector] ; BX = BX + 0x200 ( 1 Sektor - 512 Bytes )
mov [DateiOffset] , bx ; Dateioffset ist BX ( Um 512 Bytes größer )
jnc .0001
add word [DateiSegment], 0x1000
.0001
...
-
Danke M.Nemo , hab jetzt die Codezeilen geändert ... doch das Problem ist trotzdem noch vorhanden ... :|
-
Sorry ... hab nochn anderen kleinen Fehler von mir gefunden ... doch wenn ich jetzt die änderung von M.Nemo vornehme hängt das OS beim Laden der Datein ...
-
Überschreibt die kernel.sys nicht die system.sys?
bitmaster
-
Wiso soll Kernel.sys die system.sys überschreiben ?? Die System Datei ist auf 0x2400 geladen der Kernel startet bei 0x10000 .. oder was meinst du? :?
-
Nja,
FFFh * 16 = FFF0h + 10h = 10000h
240h * 16 = Start = 2400h + 65536 (z.B. wenn der kernel 64 KByte groß ist) = Ende = 12400h
bitmaster
-
Versteh ich jetzt nicht ... die Datei System.sys ist ja nur ca. 2K groß
System:
0x2400 + 0x800 = 0x2C00
Kernel:
0x10000
-
Achso, weil in deinem geposteten code bzw. in den Kommentaren steht das die sysem.sys ab 10000h geladen wird und nicht die kernel.sys. Da habe ich mich vertan, habe mir jetzt nicht die Dateinamen angeguckt. sorry
bitmaster
-
Gefunden:
....
mov ax , [di+28]
call Bytes_2_Sektors ; Berechnen wieviel Sektoren die Bytes in AX entsprechen
mov cx , ax
....
wenn die datei größer als 64k ist, dann passt die größe nicht in ax und somit stimmt auch nicht die anzahl der zu lessenden sectoren
und noch ein paar sachen die mir aufgefallen sind:
1. dein bootloader geht davon aus, dass alle sectoren einer datei schön hintereinander angereit sind, dass ist aber nur selten der fall
2.write_cs:
...
mov ax, 0xAC0
mov ss, ax
mov sp, 0x200 ; stack linear addr 0x7bff
;0x0AC0:0x0200 liner = 0xAE00 nicht 0x7bff
3. du hast oftermal so sachen wie
jmp blabla
ret
das ret wird aber nie ausgefürt
-
Hallo,
so hab das Problem mit der Anzahl der Sektoren behoben ... doch leider wird das System (od. Emulator) nach aufruf des Kernels neu gestartet ... VM-Ware meldet einen "Kernel Stack Fault (HW reset)" ... hätte vl. noch jemand eine Vermutung woran es liegen könnte ??
Hunter
-
Der Fehler liegt wohl dann im Kernel. Kanst du das ma posten? Lauft dein Kernel im PM oder RM?
Das Problem mit dem Neustarten hatte ich auch schon. Woran es genau gelegen hat hab ich nicht raus bekommen. Ich schätze ma das es Fehler mit den Diskriptoren war.