I don't know if I did it right or not, but I zeroed 1024 Byte from 0x1000:0x0000,
copied the kernel at this place and it still don't work.
I post the code of my bootloader here (if you want it, I'll try to translate all the comments into english):
Code: Select all
[BITS 16]
[ORG 0x0000] ; NICHT 0x7C00 -> Wird später selbst in Register eingetragen
; FAT12 Daten
JMP START
OSName db 'OS '
BytesPerSec dw 512
SecPerClus db 1
RsvdSecCnt 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 00000000h
VolumeLabel db 'NO NAME '
FileSysType db 'FAT12 '
;********************;
; Variablen
LoadMsg db "L",13,10,0
RebootMsg db "P",13,10,0
;-----
BootDrive db 0 ; Speicherort des Bootlaufwerks
DataName db "KERNEL BIN" ; Name des Kernels
DataSektor dw 0
FreeMem dw 512
AbsoluteSector db 0
AbsoluteHead db 0
AbsoluteTrack db 0
;********************;
START:
MOV AX, 0x07C0 ; Vorbereiten für den Sprung zu "MAIN"
MOV ES, AX ; ES -> Neues Extrasegment
MOV DS, AX ; DS -> Neues Datensegment
JMP WORD 0x07C0:MAIN ; Springe zum 0x07C0:MAIN-Code -> Durch BIOS dorthin kopiert
MAIN:
CLI ; Interrupte verbieten
MOV AX, 0x9000 ; Vorbereiten für Verschiebung des Stacks
MOV SS, AX ; Verschiebe den Stack nach 0x9000
XOR SP, SP ; Stackpointer auf Null setzen -> Keine Variablen auf dem Stack
STI ; Interrupte erlauben
MOV [BootDrive], DL ; Laufwerk speichern, von dem gebootet worden ist
MOV SI, LoadMsg
CALL PRINT
CALL ZeroMemory
CALL READ_FAT
MOV SI, LoadMsg
CALL PRINT
CALL READ_ROOT
MOV SI, LoadMsg
CALL PRINT
MOV SI, DataName
CALL READ_ROOT_FILE
MOV WORD [FreeMem], 0
MOV BX, 0x1000
MOV ES, BX ; ES -> Segment für die Speicherung des Kernels
XOR BX, BX ; BX -> Offset für die Speicherung des Kernels (BX = 0)
CALL READ_FILE ; Kernel wird an die Adresse 1000:0000 geladen (ES:BX) -> entspricht absoluter Adresse 0x10000
XOR BX, BX
CALL EXEC_FILE
;************************************************;
; Ausgabe von Text
; DS:SI -> Mit "0" endender String
;************************************************;
PRINT:
LODSB
OR AL, AL ; Letztes Zeichen?
JZ SHORT .1 ; Wenn ja, stoppe die Zeichenausgabe
MOV AH, 0x0E
MOV BX, 0x0007
INT 0x10
JMP SHORT PRINT
.1:
RETN
;************************************************;
; Speicher mit 0 überschreiben
;************************************************;
ZeroMemory:
PUSH ES
PUSH DI
MOV CX, 1024
MOV AX, 0x1000
MOV ES, AX
XOR AX, AX
MOV DI, AX
REP STOSB
POP DI
POP ES
RET
;************************************************;
; CX -> Anzahl der Sektoren die gelesen werden sollen
; AX -> Anfangssektor(1. Durchgang, alle anderen Durchgänge: Sektor der gelesen wird)
; ES:BX -> Speicher zu dem geschrieben wird
;************************************************;
READ_SECTORS:
PUSH DI
MOV DI, 5 ; Error Zähler (Maximal 5 Errors beim Lesen erlaubt)
.1:
PUSH AX
PUSH CX
PUSH DX
CALL LBAToCHS
MOV AX, 0x0201
XOR CX, CX
MOV CH, BYTE [AbsoluteTrack]
; SHR CX, 2
ADD CL, BYTE [AbsoluteSector]
MOV DH, BYTE [AbsoluteHead]
MOV DL, BYTE [BootDrive]
INT 0x13 ; Lesen nach ES:BX
JNC SHORT .2 ; Überprüfen ob beim Lesen ein Fehler aufgetreten ist
XOR AX, AX ; Wenn ja, Wiederholung einleiten...
INT 0x13 ; Diskettenlaufwerk zurücksetzen
DEC DI ; Errorzähler verringern (Wenn 0 -> Lesevorgang gescheitert)
POP DX
POP CX ; CX wiederherstellen (Der Sektor muss nochmals gelesen werden)
POP AX ; AX wiederherstellen (Der Sektor muss nochmals gelesen werden)
JNZ SHORT .1 ; Wiederholung durchführen
POP DI
JMP Failure
.2: ; Kein Fehler beim Lesen des Sektors
POP DX
POP CX
POP AX
ADD BX, WORD [BytesPerSec]
INC AX ; Nächster Sektor
LOOP .1 ; Zum Einlesen springen
POP DI
RET
READ_FAT:
MOV AX, [RsvdSecCnt] ; AX -> Startsektor(-Cluster) der FAT Tabelle
MOV CX, WORD [FATSize] ; CX -> Größe der FAT Tabelle in Sektoren(Clustern)
MOV BX, WORD [FreeMem] ; BX -> Adresse von freiem Speicher
CALL READ_SECTORS ; Sektoren einlesen
MOV WORD [FreeMem], BX ; Adresse von freiem Speicher in "FreeMem" schreiben
RET
;************************************************;
; Laden des Root Verzeichnisses in den Speicher
;
;************************************************;
READ_ROOT:
XOR CX, CX
MOV AX, 32
MUL WORD [RootEntCnt]
DIV WORD [BytesPerSec]
XCHG AX, CX ; CX -> Größe des Root Ordners in Sektoren(Clustern)
MOV AL, [NumFATs]
MUL WORD [FATSize]
ADD AX, [RsvdSecCnt] ; AX -> Startsektor(-Cluster) des Root Ordners
MOV BX, WORD [FreeMem] ; BX -> Adresse von freiem Speicher
MOV WORD [DataSektor], AX
ADD WORD [DataSektor], CX ; [DataSektor] -> 1. Datensektor
CALL READ_SECTORS
MOV WORD [FreeMem], BX ; Adresse von freiem Speicher in "FreeMem" schreiben
RET
;************************************************;
; Suchen einer Datei im Root Verzeichnis
; DS:SI -> Name der Datei die gesucht werden soll
;
; Rückgabe:
; AX -> Eintrag aus der FAT Tabelle, Zeiger auf ersten Cluster der Datei
;************************************************;
READ_ROOT_FILE:
XOR CX, CX ; CX auf 0 setzen
MOV AX, 32 ; 32 in AX schreiben (Größe eines Eintrages im Root Verzeichnis in Byte)
MUL WORD [RootEntCnt] ; Mit der Anzahl an maximalen Einträgen multiplizieren
XCHG CX, AX ; Werte von AX und CX austauschen
MOV AX, WORD [FreeMem]
SUB AX, CX
MOV CX, WORD [RootEntCnt] ; CX -> Anzahl der maximalen Einträge im Root Verzeichnis (Vorbereitung auf Schleife)
MOV DI, AX ; DI -> Anfang des Root Verzeichnisses im Speicher
.1:
PUSH CX
MOV CX, 0x000B
MOV SI, DataName
PUSH DI
CLD ; Direction Flag auf 0 setzen
REPE CMPSB ; Vergleiche Dateinamen
POP DI
JE SHORT .2 ; Wenn Dateinamen gleich, springe zu .2
POP CX
ADD DI, 0x0020
LOOP .1
XOR AX, AX
RET
.2:
INC SP
INC SP
MOV AX, WORD [DI+26] ; DI+26 -> Zeiger auf den ersten Cluster der Datei
RET
;************************************************;
; Lesen einer Datei in den Speicher
; AX -> Zeiger auf den ersten FAT Cluster der Datei
; ES:BX -> Speicher, zu dem die Datei geschrieben werden soll
; DS -> Segment in dem der Bootloader anfängt
;
; Rückgabe:
; ES:BX -> Zeiger auf den Beginn der Datei im Speicher
;************************************************;
READ_FILE:
PUSH AX
;PUSH AX
CALL ClusterToLBA ; AX -> Zeiger auf die Datei im Datenbereich
XOR CX, CX ; CX auf 0 setzen
MOV CL, BYTE [SecPerClus] ; CX -> Anzahl der Sektoren die gelesen werden sollen
MOV BX, WORD [FreeMem] ; BX -> Freier Speicher
CALL READ_SECTORS
MOV WORD [FreeMem], BX
POP AX
XOR DX, DX ; DX auf 0 setzen (Vorbereitung für Rechnung)
MOV BX, 0x0003 ; 3 in BX schreiben
MUL BX ; AX mit BX multiplizieren
DEC BX ; BX um 1 verringern (BX = 2)
DIV BX ; DX -> AX % 2 (-> Erkennung ob AX gerade oder ungerade)
MOV BX, WORD [BytesPerSec]
ADD BX, AX
MOV AX, WORD [DS:BX]
CMP DX, 1 ; Erkennung ob DX 0 oder 1 enthält (-> AX gerade oder ungerade)
JZ .2 ; Wenn gerade, springe zu .2
.1:
AND AX, 0000111111111111b ; Lösche die Bits 9-12 (bzw. 8-11, wenn die Zählung bei 0 anfängt)
JMP SHORT .3
.2:
SHR AX, 4 ; verschiebe alle Bits in AX um 4 nach rechts und fülle die Lücke mit 0 (z.B. 0101110110010101 -> 0000010111011001)
.3:
CMP AX, 0x0FF0
JB READ_FILE
RET
;************************************************;
; Ausführen einer Datei im Speicher ES:BX
; ES -> Speichersegment
; BX -> Offset
;************************************************;
EXEC_FILE:
PUSH ES
PUSH BX
RETF ; Springe "zurück" zu ES:BX
;************************************************;
; Convert Cluster to LBA
; LBA = (cluster - 2) * sectors per cluster
; AX -> Logical Adress to convert
;************************************************;
ClusterToLBA:
DEC AX
DEC AX
MOV CL, BYTE [SecPerClus]
MUL CL
ADD AX, WORD [DataSektor]
RET
;************************************************;
; Konvertiere LBA Adresse zu CHS
; AX -> LBA Addresse zum konvertieren
;
; absolute sector = (logical sector / sectors per track) + 1
; absolute head = (logical sector / sectors per track) MOD number of heads
; absolute track = logical sector / (sectors per track * number of heads)
;
;************************************************;
LBAToCHS:
PUSH BX
PUSH CX
PUSH DX
XOR BX, BX
XOR DX, DX
XCHG AX, BX
MOV AX, WORD [NumHeads]
MUL WORD [SecPerTrack]
XCHG AX, BX ; BX -> [NumHeads] * [SecPerTrack]
DIV BX
MOV BYTE [AbsoluteTrack], AL
MOV AX, DX
XOR DX, DX
DIV WORD [SecPerTrack]
MOV BYTE [AbsoluteHead], AL
INC DL
MOV BYTE [AbsoluteSector], DL
POP DX
POP CX
POP BX
RET
Failure:
MOV SI, RebootMsg
CALL PRINT
XOR AH, AH
INT 0x16
INT 0x19
times 512-($-$$)-2 db 0 ; Größe des Bootloaders auf 512 Byte erhöhen durch Auffüllen des freien Plaztes mit Nullen
dw 0AA55h