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


  • Mod

    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?


  • Mod

    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
    

  • Mod

    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


  • Mod

    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!!!


Anmelden zum Antworten