Autor Thema: Bootloader hängt auf neueren PCs  (Gelesen 6807 mal)

livinskull

  • Beiträge: 27
    • Profil anzeigen
    • Livinskulls site
Gespeichert
« am: 28. June 2006, 21:19 »
Hallo,

ich habe folgendes Problem:
mein Bootloader bootet auf meinem alten PC problemlos; sobald ich aber versuche, ihn auf einem neueren PC (Pentium aufwärts) zu starten haengt der PC einfach. Weiss hier zufaellig jemand woran dass liegen koennte?

Der Bootsektor:

;#######################################################################
;BOOTSECTOR zum laden einer binären Kernel-Datei aus dem Root-Verzeichnis

%include "../Macros16.asm"

;BOOTSECTOR_INFOBLOCK
start:
org 0x7C00
jmp boot
OSName db "LIVINOS "
BytesPerSec dw 512
SecPerClus db 1
ResvdSecCnt dw 1
NumFATs db 2
RootEntCnt dw 224
TotSec dw 2880
MediaType db 0xF0
FATSize dw 9
SecPerTrack dw 18
NumHeads dw 2
HiddenSec dd 0
TotSec32 dd 0
DrvNum db 0x00
Reserved db 0
BootSig db 0x29
VolumeID dd 1
VolumeLabel db "LIVINOS    "
FileSysType db "FAT12   "
;########################################################################
;BOOTSECTOR_CODE_START
boot:

cli ;Interruptflag löschen (keine Interrupts zulassen)
mov ax, 0x9000
mov ss, ax ;Stacksegment auf AX(0x9000) setzen
xor sp, sp ;Stackpointer auf 0 setzen
sti ;Interruptflag setzen (Interrupts wieder zulassen)

mov [bootdrive],dl

push WORD MsgLoading
call func_PrintString
inc sp
inc sp

call func_FindFileSector ;Startsektor der Kerneldatei finden lassen (Rückgabe in AX)
or ax, ax ;AX = 0? -> Datei nicht gefunden
jz KernelNotFound ;Zur Ausgabe (File not found) springen

call func_ReadFATTable ;FAT-Tabelle in den Speicher lesen lassen

mov bx, 0x1000 ;Segmentadresse festlegen an die der Kernel geladen werden soll
mov dx, [RootEntCnt] ;Startsektor der Datensektoren errechnen
shl dx, 5
add dx, [BytesPerSec]
dec dx
shr dx, 9
add [Temp], dx ;Und das Ergebnis in Temp-Variable speichern


LoadKernelFile:
mov dx, [Temp] ;Startsektor der Datensektoren in DX schreiben
add dx, ax ;Zum Startsektor der Datensektoren den Startsektor der Datei addieren
dec dx ;DX um 2 verringern
dec dx ;Zweimal "dec dx" braucht weniger Bytes als einmal "sub dx, 2"
push bx ;Segmentadresse an die der Sektor gelesen werden soll auf den Stack pushen
push dx ;Sektornummer die gelesen werden soll auf den Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen

push ax ;FAT-Eintrag-Nummer auf den Stack pushen
call func_ReadFATEntry ;Wert des FAT-Eintrags lesen (Rückgabe in AX)
;add sp, 2 ;1 Parameter vom Stack löschen
inc sp
inc sp

cmp ax, 0xFFF ;Ist das der letzte FAT-Eintrag der Kernel-Datei?
je ExecuteKernel ;Wenn Ja -> Springe zum Kernel
add bx, 32 ;Segmentadresse um 32 erhöhen. Dort wird der nächste Sektor hingelesen
jmp LoadKernelFile ;Springe wieder nach oben um nächsten Sektor der Kernel-Datei zu lesen

ExecuteKernel:
mov ax, 0x1000
push ax ;Segmentadresse an welcher der Kernel ist auf den Stack pushen
xor ax, ax
push ax ;Offsetadresse des Kernels (0) auf den Stack pushen
retf ;Einen FAR-Rücksprung zum Kernel machen

KernelNotFound:
push WORD MsgFileNotFound ;Offset der "File not Found" Meldung auf den Stack pushen
call func_PrintString ;Meldung ausgeben lassen
;add sp, 2 ;1 Parameter vom Stack löschen
inc sp
inc sp

WaitForKeyToReboot:
xor ah, ah ;Auf Tastendruck warten
int 0x16

Reboot:
db 0xEA ;Reboot
dw 0x0000
dw 0xFFFF

;BOOTSECTOR_CODE_END
;########################################################################
;DATABLOCK_START

MsgFileNotFound db "Error",13,10,0 ;Meldung wenn kein Kernel gefunden wurde
MsgLoading db "Load",13,10,0

bootdrive db 0
Filename db "LIVINOS BIN" ;Dateiname des Kernels
Temp dw 0 ;Tempvariable

;DATABLOCK_END
;########################################################################
;FUNCTIONS_START

;------------------------------------------------------------------------
;Funktion um einen NULL-Terminierten String auszugebens
;1. Paramter: Offset an dem sich der String befindet

func_PrintString:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen

pusha ;Alle Register sichern

mov si, [Param1] ;1. Parameter(Offset des Strings) nach SI kopieren
mov ah, 0x0E ;Funktion zur Zeichenausgabe
;mov bx, 0x0007 ;Farbattribut des Zeichens
xor bx,bx
.1:
lodsb ;Zeichen von SI-Pointer nach AL kopieren und SI um 1 erhöhen
or al, al ;AL = 0? String zu Ende?
jz .2 ;Wenn JA -> Springe zum Ende
int 0x10 ;Zeichen ausgeben lassen
jmp .1 ;Wieder nach oben springen um nächstes Zeichen auszugeben

.2:
popa ;Register wiederherstellen

mov sp, bp ;Stackpointer wieder in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um den Startsektor der Kernel-Datei zu finden

func_FindFileSector:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
;sub sp, 2 ;Platz für eine lokale Variable auf dem Stack schaffen
dec sp
dec sp

pusha ;Alle Register sichern

mov ax, 0x9200 ;Segmentadresse festlegen an die ein Sektor zwischengespeichert wird
mov es, ax

mov ax, [FATSize] ;Startsektor des Root-Directorys errechnen
mov bl, [NumFATs]
mul bl
add ax, [ResvdSecCnt]
mov [Temp], ax ;Startsektor des Root-Directorys in Temp-Variable speichern

xor dx, dx ;DX auf 0 setzen (Braucht weniger Bytes als "mov dx, 0")

.E:
cmp dx, [RootEntCnt] ;Wurden schon alle Root-Dir-Einträge durchsucht?
je .A ;Wenn JA -> Datei nicht gefunden

test dx, 15 ;DX durch 16 ohne Rest teilbar?
jnz .B ;Wenn JA -> Nächsten Sektor lesen

push es ;Segmentadresse für zwischenspeichern eines Sektors auf Stack pushen
push ax ;Sektornummer auf Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen
inc ax ;AX um 1 erhöhen (Braucht weniger Bytes als "add ax, 1")
xor bx, bx ;BX auf 0 setzen (Braucht weniger Bytes als "mov bx, 0")

.B: ;Wenn DX NICHT durch 32 OHNE Rest teilbar ist, fahre HIER fort
cmp BYTE [es:bx], 0x0E ;Erstes Zeichen des Root-Dir-Eintrags = 0x0E?
je .D ;Wenn JA -> Nächsten Eintrag lesen
cmp BYTE [es:bx], 0 ;Erstes Zeichen des Root-Dir-Eintrags = 0?
je .A ;Wenn JA -> Keine weiteren Einträge mehr. Datei nicht gefunden


mov si, Filename ;Offset des Dateinamens nach SI kopieren
mov di, bx ;Offset des Root-Dir-Eintrags nach DI kopieren
mov cx, 11 ;11 Zeichen sollen verglichen werden
repe cmpsb ;Solange vergleichen bis CX = 0 oder ungleiche Zeichen
or cx, cx ;CX = 0?
jz .C ;Wenn JA -> Alle Zeichen stimmen überein. Datei gefunden

.D:
inc dx ;DX um 1 erhöhen
add bx, 32 ;BX um 32 erhöhen (Offset des nächsten Root-Dir-Eintrags)
jmp .E ;Wieder nach oben springen um nächsten Eintrag zu vergleichen

.A: ;Wenn die NICHT Datei gefunden wurde, HIER fortfahren
popa ;Alle Register wiederherstellen
xor ax, ax ;AX auf 0 setzen (Braucht weniger Bytes als "mov ax, 0")
jmp .Ende ;Zum Ende Springen

.C: ;Wenn die Datei gefunden wurde, HIER fortfahren
push WORD [es:bx+26] ;Startsektornummer der Datei auf den Stack pushen
pop WORD [Var1] ;Startsektornummer in lokale Variable popen
popa ;Alle Register wiederherstellen
mov ax, [Var1] ;Startsektornummer der Datei nach AX kopieren

.Ende:
mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um einen Sektor zu lesen
;1. Parameter: Logische Sektornummer des Sektors welcher gelesen werden soll
;2. Parameter: Segmentadresse an die der Sektor gespeichert werden soll

func_ReadSector:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
sub sp, 6 ;Platz für 3 lokale Variablen auf dem Stack schaffen

pusha ;Alle Register sichern

;Aus Logischer Sektornummer die CHS Adresse errechnen
mov ax, [Param1] ;Aus logischer Sektornummer den Cylinder errechnen
mov bx, 36
mov dx, 0
div bx
mov [Var1], ax

mov ax, dx ;Aus logischer Sektornummer den Head errechnen
push ax
mov bx, 18
mov dx, 0
div bx
mov [Var2], ax

pop ax ;Aus logischer Sektornummer den Sektor errechnen
mov dx, 0
div bx
mov ax, dx
inc ax
mov [Var3], ax


.1:
mov ax, [Param2] ;Segmentadresse zum speichern des Sektors festlegen
mov es, ax
xor bx, bx ;Offset zum speichern des Sektors festlegen
mov ah, 2 ;Funktion zum Sektorlesen
mov al, 1 ;1 Sektor soll gelesen werden
mov ch, [Var1] ;Angabe des Cylinders an dem der Sektor gelesen werden soll
mov cl, [Var3] ;Angabe des Sektors an dem der Sektor gelesen werden soll
mov dh, [Var2] ;Angabe des Heads an dem der Sektor gelesen werden soll
;xor dl, dl ;Von Laufwerk A: lesen
mov dl,[bootdrive]
int 0x13 ;Sektor lesen lassen
jc .1 ;Bei Fehler nochmal versuchen

popa ;Alle Register wiederherstellen

mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion um einen FAT-Eintrag zu lesen
;1. Parameter: Nummer des Eintrags der gelesen werden soll
;In AX wird der Wert des gelesenen FAT-Eintrag zurückgegeben

func_ReadFATEntry:
push bp ;BP sichern
mov bp, sp ;Stackpointer in BP übertragen
;sub sp, 2 ;Platz für eine lokale Variable auf dem Stack schaffen
dec sp
dec sp

pusha ;Alle Register sichern

mov ax, [Param1] ;Offset errechnen an dem sich der FAT-Eintrag im Speicher befindet
mov bx, 3
mul bx
mov bx, 2
xor dx, dx
div bx

mov bx, 0x9200 ;Segmentadresse angeben an der die FAT-Tabelle im Speicher liegt
mov es, bx
mov bx, ax
mov ax, [es:bx]
mov [Var1], ax ;FAT-Eintrag (16 Bit) in lokale Variable speichern

mov cx, [Param1] ;Testen ob der zu lesende FAT-Eintrag gerade oder ungerade ist
test cx, 1
jz .Gerade ;Wenn GERDADE -> Springe

;Wenn der zu lesende FAT-Eintrag UNGERADE ist, HIER fortfahren
popa ;Alle Register wiederherstellen
mov ax, [Var1]
shr ax, 4 ;FAT-Eintrag(12 Bits) aus den 16 Bits extrahieren
jmp .Ende

.Gerade: ;Wenn der zu lesende FAT-Eintrag GERADE ist, HIER fortfahren
popa ;Alle Register wiederherstellen
mov ax, [Var1]
and ax, 0xFFF ;FAT-Eintrag(12 Bits) aus den 16 Bits extrahieren

.Ende:
mov sp, bp ;Stackpointer in SP übertragen
pop bp ;BP wiederherstellen
ret ;Return

;------------------------------------------------------------------------
;Funktion zum einlesen der FAT-Tabelle in den Speicher

func_ReadFATTable:
pusha ;Alle Register sichern

mov bx, 0x9200 ;Segmentadresse festelegen an welche die FAT-Tabelle gelesen werden soll
mov ax, [ResvdSecCnt] ;Startsektor der FAT-Tabelle eintragen
mov cx, [FATSize] ;Anzahl der FAT-Tabellen-Sektoren eintragen
.A:
push bx ;Segmentadresse auf den Stack pushen
push ax ;Sektornummer auf den Stack pushen
call func_ReadSector ;Sektor lesen lassen
add sp, 4 ;2 Parameter vom Stack löschen
inc ax ;Nächsten Sektor auswählen
add bx, 32 ;Segmentadresse um 32 erhöhen (Dort wird nächster Sektor gespeichert)
loop .A ;Solange wiederholen bis alle Sektoren gelesen wurden

popa ;Alle Register wiederherstellen

ret ;Return

;------------------------------------------------------------------------

;FUNCTIONS_END
;########################################################################


times 512-($-$$)-2 db 0 ;Den Rest des Bootsektors mit Nullen Füllen
dw 0xAA55 ;0xAA55 am Ende des Bootsektors schreiben



Danke


ST-225

  • Beiträge: 43
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 29. June 2006, 14:30 »
Das Problem könnte darin liegen, dass der pc den FAT12-Teil am Anfang auch mit ausführt. Das kann sich dann auf jedem PC anders verhalten. Füg' einfach mal an den anfang ein jmp boot , vielleicht funktionierts dann schon.

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 29. June 2006, 14:54 »
Hat er ja schon (in der 3. Zeile nach dem Bootsector_Infoblock Kommentar).

@livingskull: Kannst du die Fehlerquelle irgendwie einschränken. Also in welcher Funktion der auftritt etc? Weil so ist das ne ganze Menge Code ;)

Ansonsten könnte der Fehler vielleicht noch am anderen BIOS liegen. Soweit ich weiß unterscheiden die sich teilweise recht deutlich, z.B. ob Register bei einem BIOS-Int verändert werden.

livinskull

  • Beiträge: 27
    • Profil anzeigen
    • Livinskulls site
Gespeichert
« Antwort #3 am: 29. June 2006, 16:40 »
@DarkThing:
Ich glaube der Fehler liegt ziemlich weit vorne, da der PC nicht einmal die "Load" Nachricht anzeigt. Also entweder davor, oder es ist die printstring-funktion selber

PS: der Code passt gerade noch in den Bootsektor...

Thx


bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #4 am: 29. June 2006, 17:20 »
hi,

cli
mov ax,0x9000
mov ss,ax
xor sp,sp
sti


ändere das mal so:

cli
xor ax,ax
mov ds,ax
mov es,ax
mov ax,0x9000
mov ss,ax
xor sp,sp
sti



Mag zwar nicht der Fehler sein den du suchst, aber manche PCs haben beim start nicht Null in ds und es drin.

bitmaster
In the Future everyone will need OS-64!!!

livinskull

  • Beiträge: 27
    • Profil anzeigen
    • Livinskulls site
Gespeichert
« Antwort #5 am: 29. June 2006, 19:43 »
Danke, werde beides mal ausprobieren


bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 29. June 2006, 20:35 »
@offtopic "@blueXseven: Wie starte ich das Programm zur Auflösung bei deinem OS?"
In the Future everyone will need OS-64!!!

thetrue

  • Beiträge: 216
    • Profil anzeigen
    • http://www.the-true.net
Gespeichert
« Antwort #7 am: 29. June 2006, 20:42 »
Zitat
@offtopic "@blueXseven: Wie starte ich das Programm zur Auflösung bei deinem OS?"


öhm F10
thetrue way is my way

livinskull

  • Beiträge: 27
    • Profil anzeigen
    • Livinskulls site
Gespeichert
« Antwort #8 am: 30. June 2006, 12:06 »
Problem gelöst   \:D/  
Lag am Stack, der an der falschen Adresse war und die Bios-daten überschrieben hat. Der Ordnung halber habe ich auch ds und es mit 0 initialisiert:

cli
xor ax,ax
mov ds,ax
mov es,ax
mov ax,0x8000
mov ss,ax
mov sp,0xFFFF
sti


Danke an Alle,
Livingskull


 

Einloggen