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

Code: Select all

xor   eax, eax
is wrong since EAX is a 32bit register.
You need to use 16 bit registers so it would be

Code: Select all

xor    ax, ax
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?

Code: Select all

mov     bh, 0x00                            ; display page 0
Since you dont need to set it for use in a text mode :roll:

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. =D>
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/