Page 1 of 1

Using int 0x13 to write to disk

Posted: Wed Apr 19, 2017 2:43 pm
by kurmasz
When I use BIOS int 0x13 to write to disk, I get an error, unless the sector number is 1 or 2.

I am using VirtualBox and booting from a virtual floppy disk. When I query for the drive parameters, ch=0x4f and cl=0x12; but, when I set cl=0x3 when writing, I get an error and al=1. Am I misinterpreting the results of the query?

Code: Select all

       
       // "initialization" code is also included below, but removed here for clarity
       // at this point, dl is unchanged from its initial value.

        mov $0x08, %ah
        int $0x13

        PUTC $'c
        PRINT_HEX <%ch>
        PUTC
        PRINT_HEX <%cl>
        PRINT_NEWLINE

        mov initial_dl, %dl

        // test write                                                                                                                                    
        mov $0x03, %ah
        mov $1, %al
        mov $end_of_s1, %bx
        mov $0, %ch
        mov $0x3, %cl
        mov $0x00, %dh
        int $0x13

        jc is_error

        PUTC $'n
        PUTC $'o
        jmp finish

is_error:
        PUTC $'e
        PUTC $'r

finish:
        PRINT_HEX <%ah>
        PUTC
        PRINT_HEX <%al>
        PRINT_NEWLINE

        jmp .

end_of_s1:
        .asciz "MESSAGE at end of Stage 1"


This is the complete coe

Code: Select all

.code16
.section .boot
        /*******************************************************************                                     
         *                                                                                                       
         * Initial set up (including the stack)                                                                  
         *                                                                                                       
         ******************************************************************/

        // disable interrupts                                                                                    
        cli

        /* Set %cs to 0. (If I understand this correctly, in real                                                
        mode, the ljmp instruction sets both the CS (code segment)                                               
        register as well as the EIP. $1f is the next label with a                                                
        value of "1", which appens to be on the next line. Thus, this                                            
        instrucion assures that the CS register is set to the segment                                            
        containing the code we are currently running                                                             
        */
        ljmp $0, $1f
        1:

        /* Sets %ax to 0.  (I'm not sure why we're not using mov.) */
        xor %ax, %ax

        /* Set all the segment registers to 0, just so we know for sure                                          
        what's going on. */
        mov %ax, %ds
        mov %ax, %es
        mov %ax, %fs
        mov %ax, %gs

        mov %ax, %bp
        mov %ax, %ss
        mov %bp, %sp


        /* Store the initial dl to load stage 2 later on. */
        mov %dl, initial_dl
        jmp after_locals
initial_dl: .byte 0
after_locals:


        PUTC $'g
        PRINT_HEX <%dl>
        PRINT_NEWLINE

        mov $0x08, %ah
        int $0x13

        PUTC $'c
        PRINT_HEX <%ch>
        PUTC
        PRINT_HEX <%cl>
        PRINT_NEWLINE

        mov initial_dl, %dl

        // test write                                                                                            
        mov $0x03, %ah
        mov $1, %al
        mov end_of_s1, %bx
        mov $0, %ch
        mov $0x3, %cl
        mov $0x00, %dh
        int $0x13

        jc is_error

        PUTC $'n
        PUTC $'o
        jmp finish

is_error:
        PUTC $'e
        PUTC $'r

finish:
       PRINT_HEX <%ah>
        PUTC
        PRINT_HEX <%al>
        PRINT_NEWLINE

        jmp .

end_of_s1:
        .asciz "MESSAGE at end of Stage 1"

Re: Using int 0x13 to write to disk

Posted: Wed Apr 19, 2017 3:23 pm
by Brendan
kurmasz wrote:When I use BIOS int 0x13 to write to disk, I get an error, unless the sector number is 1 or 2.

I am using VirtualBox and booting from a virtual floppy disk. When I query for the drive parameters, ch=0x4f and cl=0x12; but, when I set cl=0x3 when writing, I get an error and al=1. Am I misinterpreting the results of the query?
If it works for sectors 1 and 2, but doesn't work for sector 3 when everything else is the same; then I'd assume you're using a floppy disk image in an emulator that is only 1024 bytes or 2048 bytes. To fix that use something (e.g. dd, NASM, etc) to create a 1440 KiB file with your code at the start and the rest full of zeros.

A better idea is to write a custom tool that creates floppy images to suit your OS. For example, mine takes several command line arguments (the type of the floppy disk and the file names for things my OS needs - boot loader, "initial RAM disk", etc) and does some calculations to figure out which sectors each thing should use, then generates a correct BPB to suit the type of floppy disk (and a little more info that my boot loader uses). Of course my boot loader uses the fields in the BPB (so it can get LBA to CHS conversion right). This makes it fairly trivial for me to generate (working) floppy disk images for any standard floppy disk format (1680 KiB, 1200 KiB, 1440 KiB, ..., 160 KiB).


Cheers,

Brendan

Re: Using int 0x13 to write to disk

Posted: Fri Apr 21, 2017 2:32 pm
by kurmasz
That was it, thank you. (I thought the VM would just expand the .img file, if necessary.)

So, now the "OS" runs and writes data to the virtual floppy; but, it writes the wrong data to the floppy (and I can't tell where the data that is being written is coming from). Again, the code works on a real machine, just not on the VM. (However, the real machine is booting from a USB stick, not a floppy.) Are there any other beginner mistakes I should look for?

Re: Using int 0x13 to write to disk

Posted: Sat Apr 22, 2017 4:31 pm
by SpyderTL

Code: Select all

ljmp $0, $1f
I'd be suprised if this actually works.

Try changing your label to "start:" and change your ljmp statement to match. You shouldn't need the $.