Fat12 bootloader
-
Hallo, ich hab ein kleines Fat12-bl Problem...
theoretisch ist alles ganz einfach.. also das rootdir wird geladen, ebenso
die FAT-Tabelle, die Kernel-Datei wird auch gefunden aber das laden geht schief.. bitte um Hilfe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; Load the kernel ;;;;;;; ax = number of fist sector where ;;;;;;; the kernel resides on the floppy ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; loadKernel: xor bx, bx .start: add ax, 31 mov cx, 1 mov [LoaderOffset], word bx push ax call readSectors pop ax sub ax, 31 call readFatEntry cmp ax, 0x0FFF ;0x0FFF means we have reached the last sector of the file je .done mov bx, [LoaderOffset] add bx, 512 jmp .start .done: ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;readFatEntry ;;;;; ax = number of the entry ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; readFatEntry: push ax mov bx, 3 ; we want one fat-entry that is 3/2 (1.5) byte mul bx xor dx, dx mov bx, 2 div bx mov bx, 0x07E0 ; remember our fat is at 0x07E0!!! mov es, bx mov bx, ax ; move to the fat entry described by ax mov ax, word [es:bx] ; and write the (16)bits from there into ax mov cx, ax pop ax test ax, 0x0001 ; are we at an even or an odd cluster? (perform logical AND) jnz OddCluster EvenCluster: and cx, 0x0FFF ; we only want the 12 lower bits (1.5 Byte) jmp finished OddCluster: shr cx, 4 ; we oly want the 12 higher bits (1.5 Byte) finished: mov ax, cx ; ax = cx = extracted 12bit of the fat entry ret
so, das ist der wichtige Ausschnitt.. danke für Hilfe
mfg vikingspirit
-
ist ein bisschen umständlich, aber ich sehe keinen fehler, vielleicht solltest du doch mal readSectors zeigen, vielleicht gibts irgendwelche seiteneffekte.
zur verdeutlichung, readFatEntry könnte z.b. so aussehen:FatSeg dw 0x07E0 ; remember our fat is at 0x07E0!!! readFatEntry: lea ax, [ax+2*ax] ; ax *= 3 mov es, word [cs:FatSeg] shr ax, 1 ; ax /= 2 - carry signals odd sector mov ax, word [es:ax] jc OddCluster EvenCluster: and ax, 0x0FFF ret OddCluster: shr ax, 4 ret
braucht halb so viele befehle und verändert auch nicht unnötig register
-
@camper:
Dir ist aber schon klar, dass mit ax nicht adressiert werden kann, oder?
-
ach gott, ja du hast nat. recht, da war doch was mit 16bit und umständlicher adressierung :p
naja, dann eben so:FatSeg dw 0x07E0 ; remember our fat is at 0x07E0!!! readFatEntry: mov bx, ax add ax, ax mov es, word [cs:FatSeg] add bx, ax shr bx, 1 mov ax, word [es:bx] jc OddCluster EvenCluster: and ax, 0x0FFF ret OddCluster: shr ax, 4 ret
ist ja nicht viel schlimmer in diesem fall
-
also hier die readSector funktion etc..
main: cli mov ax, 0x2000 ; but stack in a free area after the bootloader mov ss, ax ; set up a 36k Stack. Remember: SP _decreases_ when pushing sth on the stack!! mov sp, 0xA000 ; (from kernel location to beginning of bios video system) sti mov ax, 32 ; get the length of the root directory mul word [RootEntCnt] ; refer to the microsoft documentation on fat12 for more add ax, word [BytesPerSec] ; information on the calculation and FS structure dec ax div word [BytesPerSec] mov cx, ax ; Put the lenghth of the root dir into cx mov ax, [NumFATs] mul word [FATSz16] add ax, word [RsvdSecCnt] call readSectors ; load the root directory into memory mov si, msg_root call write mov si, KernelName ; get the kernels position on the drive (the first sector) call searchKernel mov si, msg_kernelfound call write mov ax, [RsvdSecCnt] ; load the FAT into memory (start at sector 1) mov cx, [FATSz16] ; load it at 0x07E0 call readSectors mov si, msg_fat call write mov ax, [FileStart] mov [LoaderSegment], word 0x1000 call loadKernel mov si, msg_kerneljmp call write jmp 0x1000:0x0000 ; jump to the kernel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; LSN2CHS ;;;;;;; converts a LogicalSectorNumber ;;;;;;; to the Cylinder/Head/Sector format ;;;;;;; LSN is in ax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LSN2CHS: ;SECTORS xor dx,dx mov bx, [SecPerTrack] ; startsector = ax mod SecPerTrack (18) div bx inc dx mov cl, dl ; the remainder of the division is the start sector ;HEAD xor dx,dx mov bx, [NumHeads] div bx mov dh, dl ; head = ax mod 2 ;CYLINDER mov ch, al ; the value that is now in al is the cylinder! ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; Reset the floppy drive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; driveReset: mov dl, 0 mov ah, 0x00 int 0x13 jc driveReset ;on error, try again ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;; Read Sectors into memory ;;;;;; USAGE: ;;;;;; ax = start sector ;;;;;; cx = # of sectors to read ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; readSectors: push ax push cx call driveReset call LSN2CHS .read: mov ax, [LoaderSegment] mov es, ax ; load the sector into the memory right after the bootloader-segment and the mov bx, [LoaderOffset] ; previous loaded sectors mov ah, 0x02 mov al, 0x01 int 0x13 ; interrupt+function "disk-read sectors into memory" jnc continue call driveReset jmp .read continue: add bx, [BytesPerSec] ; advance 512 bytes = destination for the other sectors that are to be read mov [LoaderOffset], bx pop cx pop ax inc ax loop readSectors xor dx, dx mov [LoaderOffset], dx ret ... LoaderSegment dw 0x07E0 ; the segment where the sectors are loaded into mem... ; default value = right after the bootloader LoaderOffset dw 0x0000 ; the offset where the sectors are loaded into mem... default 0 FileStart dw 0x0000
-
was ist mit
xor dx, dx mov [LoaderOffset], dx
so weit ich das erkennen kann, führt das doch dazu, dass jedesmal, wenn ein neues cluster gelesen wird, der inhalt des alten überschrieben wird, da LoaderSegment ja nicht verändert wird.
-
nope... loaderOffset wird auf 0 gesetzt nachdem alle Cluster gelesen wurden..
-> erst nach loop! read Sector wird ja nur einmal pro Ladevorgang aufgerufen... also einmal für das Rootdir, einmal für die fat, und einmal für den kernel.. und bevor der kernel geladen wird, wird loaderSegment verändert damit es nicht versehentlich die fat überschreibt...mfg vikingspirit
-
keinesfalls, readSectors wird ja für jeden einzelnen FatEintrag aufgerufen. in readSectors wird das offset stets am ende auf null gesetzt. in loadKernel wird es zwar jedesmal um 512 erhöht, aber das führt eben nur dazu, dass zwar der erste sector richtig auf offset 0x1000 geladen wird, alle folgenden aber konstant ab offset 512 (mal abgesehen davon, dass du hier implizit von einer clustergrösse von 1 ausgehst, das ist nicht zwingend so). von loadKernel her ist cx immer 1, also wird die loop schleife auch nur einmal ausgeführt werden pro aufruf.
meiner ansicht nach, müssten sowohl diese beiden befehle in readSectors entfernt werden, als auch die entspr. befehle in loadKernel, die das offset erhöhen (weil du das ja bereits vorher in readSectors tust, vor den befehlen, die ich kritisiere).
-
*AUTSCH* Sorry ich bin ein Idiot.... Ahrg natürlich... *Brett vorm Kopf gehabt* danke!!!