Page 1 of 1
[help] 1st bootloader
Posted: Mon Jan 10, 2011 12:06 pm
by a07859
Hello guys, I tried to make a 1st stage FAT32 boot loader on my 2 GB flash disk. But first of all I like to try the Fat32 BPB on hello world boot loader before I put the loader so i know it's an error on BPB but there is an error. The hello world boot loader not displaying the "hello world" on screen. I attached my code in code quote.
Code: Select all
org 7c00h
jmp start
nop
bs_OEM db "MSDOS5.0"
A_BF_BPB_BytesPerSector DW 200h
A_BF_BPB_SectorsPerCluster DB 8h
A_BF_BPB_ReservedSectors DW 01f0h
A_BF_BPB_NumberOfFATs DB 02
A_BF_BPB_RootEntries DW 0
A_BF_BPB_TotalSectors DW 0
A_BF_BPB_MediaDescriptor DB 0f8h
A_BF_BPB_SectorsPerFAT DW 0
A_BF_BPB_SectorsPerTrack DW 03fh
A_BF_BPB_Heads DW 0ffh
A_BF_BPB_HiddenSectors DW 080h
A_BF_BPB_HiddenSectorsHigh DW 0h
A_BF_BPB_BigTotalSectors DW 3f00h
A_BF_BPB_BigTotalSectorsHigh DW 03ch
A_BF_BPB_BigSectorsPerFat DW 0f08h
A_BF_BPB_BigSectorsPerFatHi DW 0h
A_BF_BPB_ExtFlags DW 0
A_BF_BPB_FS_Version DW 0
A_BF_BPB_RootDirStrtClus DW 2
A_BF_BPB_RootDirStrtClusHi DW 0
A_BF_BPB_FSInfoSec DW 1h
A_BF_BPB_BkUpBootSec DW 6h
A_BF_BPB_Reserved DW 6 DUP (?)
BS_physical dw 80h
BS_bootrecord db 29h
volumeid dd 0AE6DA6B2h
volumelabel db "No Name "
filesystem db "FAT32 "
start:
cli
xor eax, eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; create stack
mov ss, ax
mov sp, 0x7c00
sti
; post message
mov si, msgLoading
call DisplayMessage
hang:
jmp hang
DisplayMessage:
lodsb ; load next character
; test for NUL character
jz .DONE
mov ah, 0x0E ; BIOS teletype
mov bh, 0x00 ; display page 0
mov bl, 0x07 ; text attribute
int 0x10 ; invoke BIOS
jmp DisplayMessage
.DONE:
ret
msgLoading DB "Hello, world!", 0
TIMES 510-($-$$) DB 0
DW 0xAA55
this Code is readable as FAT32 system on windows. I use fasm compiler.
Best regards,
Re: [help] 1st bootloader
Posted: Mon Jan 10, 2011 3:09 pm
by Tosi
Code: Select all
DisplayMessage:
lodsb ; load next character
; test for NUL character
jz .DONE
mov ah, 0x0E ; BIOS teletype
mov bh, 0x00 ; display page 0
mov bl, 0x07 ; text attribute
int 0x10 ; invoke BIOS
jmp DisplayMessage
.DONE:
ret
lodsb doesn't modify any flags, so if you ever want that loop to end, you have to manually test that the character is NUL.
Other than that, I don't really know since I've written a lot more 32-bit code than 16-bit.
Re: [help] 1st bootloader
Posted: Tue Jan 11, 2011 2:51 pm
by gboers
Well I see something ^^
The
is wrong since EAX is a 32bit register.
You need to use 16 bit registers so it would be
I hope that helps.
I am only trying to help out here! my asm is a bit rusty so if I'm wrong please correct me.
Edit:
May I also ask why do you set a page number?
Since you dont need to set it for use in a text mode
Re: [help] 1st bootloader
Posted: Tue Jan 11, 2011 8:18 pm
by Brendan
Hi,
The "xor eax, eax" will work fine on any 80386 or later CPU, just like the "mov fs,ax" and "mov gs,ax". I'd use "xor ax,ax" (and avoid using GS and FS) and test if the CPU is 80386 or later first (and display a nice "This CPU is too old" error message if it isn't), but that's optional. If you want to save some bytes (and you will) it would be a good idea to use "xor ax,ax" (to avoid the size override prefix) and remove the "mov fs,ax" and "mov gs,ax" instructions (as you don't use FS or GS anyway). In the same way, if you're assuming 80386 or later (but not if you're assuming it could be 8086 or something) then you could remove the "cli" and "sti", as 80386 and later CPUs automatically supress IRQs for one instruction after a "mov ss".
The "mov bh, 0x00" is necessary - displaying characters in the wrong display page makes them invisible (although you could combine it with the next instruction and do "mov bx,0x0007").
You could/should make sure you are in text mode first (instead of assuming you are) as it is possible that you aren't (e.g. some sort of chainloader left you in graphics mode), but that is unlikely (despite being technically possible) and it's safe for me to assume this isn't the cause of your problem.
Tosi is entirely correct about the "losb; jz .DONE" bug. The line between these instructions and the unusual indenting of the comment on this line makes me think there was an instruction there (like "test al,al") and it was removed for some reason (in attempt at finding the bug?). This bug would cause the string and lots of other stuff to be printed (maybe about 600 KiB of zeros then random trash), but the "hello world" string would be printed first. If this was the only problem then you would've said "displaying trash after the string" rather than "not displaying the string", so I assume that this isn't the only problem.
However, there are no other problems in that code. So, based on all of the above, I'd assume that either:
- your boot code isn't being written to the correct place (for e.g. maybe it's installed in the first sector of a partition and not in the first sector of the device, and Windows says the partition is FAT but the BIOS is trying to boot from a different sector)
- the BIOS doesn't support booting from USB or doesn't support it properly
- it's being assembled as 32-bit code (in this case the "jmp start" and "nop" would be the same so the BPB would be in the right place, but it would probably crash before it displays anything)
- I was wrong and "not displaying the string" actually does mean "displaying trash after the string"
- something else I didn't think of
Cheers,
Brendan
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 12:35 am
by Chandra
Hi,
try replacing 'jmp start' with 'jmp short start' to make your bootloader valid FAT32 bootloader (3 bytes off start).
I dont know if this is the root of the problem, though.
Regards,
Chandra
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 2:15 am
by Dario
Brendan wrote:
The "xor eax, eax" will work fine on any 80386 or later CPU, just like the "mov fs,ax" and "mov gs,ax". I'd use "xor ax,ax" (and avoid using GS and FS) and test if the CPU is 80386 or later first (and display a nice "This CPU is too old" error message if it isn't), but that's optional. If you want to save some bytes (and you will) it would be a good idea to use "xor ax,ax" (to avoid the size override prefix) and remove the "mov fs,ax" and "mov gs,ax" instructions (as you don't use FS or GS anyway). In the same way, if you're assuming 80386 or later (but not if you're assuming it could be 8086 or something) then you could remove the "cli" and "sti", as 80386 and later CPUs automatically supress IRQs for one instruction after a "mov ss".
Brendan, I enjoy reading your posts. They are by far the most technical on this board.
But seriously, do you have complete Intel's manual in your head?
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 9:31 am
by Firestryke31
Maybe, but probably not. It's just one of those quirks that, once you find it, stays with you. Especially if you stick with low level stuff where tricks like that can save you space or time.
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 9:55 am
by qw
Brendan wrote:In the same way, if you're assuming 80386 or later (but not if you're assuming it could be 8086 or something) then you could remove the "cli" and "sti", as 80386 and later CPUs automatically supress IRQs for one instruction after a "mov ss".
Sorry for being pedantic (because your knowledge
is impressive) but all x86's have shown this behavior since the first 8086's and 8088's. I was able to trace it back as far as the 80286 but I'm sure about the 8086/88 too:
The Intel 80286 Programmer's Reference Manual wrote:Any move into SS will inhibit all interrupts until after the execution of the next instruction.
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 10:25 am
by a07859
Thx guys, it's finally work now. But i have trouble after that. I try to load my loader. But my LBACHS function do not work properly. LBA to CHS formula is:
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)
I try to load my root directory which is locate on LBA sector 0x2000 to memory 0:0x8000.
On BPB my sector per track is 0x3f and number of head is 0xffh.
From the formula it must be C=0 H=0x82 and S=3, but my function show C=0x82 H=3 S=0x82
here is my LBACHS code
Code: Select all
; PROCEDURE LBACHS
; convert "ax" LBA addressing scheme to CHS addressing scheme
; 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)
;*************************************************************************
LBACHS:
xor dx, dx ; prepare dx:ax for operation
div WORD [A_BF_BPB_SectorsPerTrack] ; calculate
inc dl ; adjust for sector 0
mov BYTE [absoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [A_BF_BPB_Heads] ; calculate
mov BYTE [absoluteHead], dl
mov BYTE [absoluteTrack], al
ret
Can someone tell me what's wrong on the function?
Thanks, best regards
Re: [help] 1st bootloader
Posted: Wed Jan 12, 2011 10:52 pm
by Brendan
Hi,
Hobbes wrote:Brendan wrote:In the same way, if you're assuming 80386 or later (but not if you're assuming it could be 8086 or something) then you could remove the "cli" and "sti", as 80386 and later CPUs automatically supress IRQs for one instruction after a "mov ss".
Sorry for being pedantic (because your knowledge
is impressive) but all x86's have shown this behavior since the first 8086's and 8088's. I was able to trace it back as far as the 80286 but I'm sure about the 8086/88 too:
The Intel 80286 Programmer's Reference Manual wrote:Any move into SS will inhibit all interrupts until after the execution of the next instruction.
Heh. I couldn't remember if this was introduced in 80186 or not, and was too lazy to look it up. Instead I wrote "if you're assuming 80386 ... as 80386 and later CPUs automatically supress IRQs" so that my statement is correct regardless of when this behaviour was introduced. I could've written "all Nehalem and later CPUs suppress IRQs" and that would've been correct too.
Cheers,
Brendan
Re: [help] 1st bootloader
Posted: Thu Jan 13, 2011 4:01 am
by qw
Heh, now you're the one being pedantic (not that I blame you). Anyway, the feature was included from the very beginning, except that some very early series of the 8086 were buggy. So we are debating the close to zero percent chance that the code is run on one of those buggy 8086's from 1978 vs. saving two bytes by not explicitly clearing and setting the interrupt flag. Quite a non-issue, but as I said, we were being pedantic.
Re: [help] 1st bootloader
Posted: Thu Jan 13, 2011 8:32 am
by quok
Sometimes, and especially in a boot loader, 2 extra bytes is all you need!
Re: [help] 1st bootloader
Posted: Mon Jan 24, 2011 4:07 am
by a07859
I think the track sector cylinder of the 32 bit must be 8 bit because int 13h store register to 8 bit register
http://osdeverdiary.blogspot.com/