4

As any programmer in the world at least once in his/her life, I am trying to create my "revolutionary", the new and only one operating system. :D

Well, I am using a virtual emulator (Oracle VM Virtual Box), for which I create a new unknwon operating system, with a vmdk disk. I like vmdk because they are just plain files, so I can paste my boot-loader over the first 512 bytes of the virtual hard disk.

Now, I am trying to read the next sector of this virtual disk, on which I would paste a simple kernel that would display a message.

I have two questions:

  • Am I reading the second segment (the first -512 bytes- is occupied by the bootloader) correctly? CODE:

    ReadDisk:
        mov bx, 0x8000  ; segment
        mov es, bx
        mov bx, 0x0000  ; offset
    
        mov ah, 0x02  ; read function
        mov al, 0x01  ; sectors - this might be wrong, trying to read from hd
        mov ch, 0x00  ; cylinder
        mov cl, 0x02  ; sector
        mov dh, 0x00  ; head
        mov dl, 0x80  ; drive - trying to read from hd
        int 0x13   ; disk int
        jc ReadDisk
        jmp [es:bx]   ; buffer
    

    Here, I get the error message, after checking CF. However, if I use INT 13, 1 to get last status message, AL is 0 - so no error is saved.

  • Am I pasting my simple kernel in the correct place inside the vmdk? What I do is pasting it after the 512th byte of the file, the first 512 bytes, as I said, are the boot-loader. The file would look like this:

    BE 45 7C E8 16 00 EB FE B4 0E B7 00 B3 07 CD 10 <- First sector
    C3 AC 08 C0 74 05 E8 EF FF EB F6 C3 B4 00 B2 80
    CD 13 BE 5D 7C 72 F5 BB 00 80 8E C3 BB 00 00 B4 
    02 B0 06 B5 00 B1 01 B6 00 B2 07 CD 13 BE 4E 7C 
    72 CF 26 FF 27 57 65 6C 63 6F 6D 65 21 00 52 65 
    61 64 69 6E 67 20 65 72 72 6F 72 21 00 52 65 73 
    65 74 74 69 6E 67 20 65 72 72 6F 72 21 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA <- Boot-loader signature
    B4 0E B0 2E CD 10 EB FE 00 00 00 00 00 00 00 00 <- Start of the second sector
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    

So, this is the way I am trying to add the kernel to the second sector. What do you think is wrong with this? Thanks!

UPDATE

O.K. I don't get any error now, but I don't see the loaded code being executed. It should display a point on the window:

;--------------------------------------------
; 'load.asm'
; loaded from 'boot.asm'

[org 0x8000]
[bits 16]

;--------------------------------------------

main:
mov ah, 0x0E  ; print function
mov al, '.'   ; ascii char
int 0x10   ; IO int

jmp $    ; hang
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
ali
  • 10,927
  • 20
  • 89
  • 138
  • You should really head to http://osdev.org/ and ask it there. And read some articles from its wiki. – Griwes Jun 17 '12 at 22:26
  • "However, if I use INT 13, 1 to get last status message, AL is 0 - so no error is saved." The status is actually returned in `ah`, not `al`. Refer to https://github.com/cirosantilli/ralf-brown-interrupt-list/blob/master/inter61a/INTERRUP.B#L1591 -- Besides, all operations return a status in `ah` when they return with `CY` (carry flag set), you don't need to call function 01h explicitly. – ecm Aug 30 '19 at 20:14

2 Answers2

6

One problem is here:

jmp [es:bx]

This will read an address, a 16-bit offset, in fact, from the memory location at the address contained in the registers es (segment portion) and bx (offset portion) and then set ip to that 16-bit offset.

What you may want to use instead is:

jmp some_constant1:some_constant2

This will set cs to some_constant1 and ip to some_constant2. Unsurprisingly, good candidates for these two constants are 0x8000 and 0 respectively since that's the location where your code gets loaded.

Now, the second problem is here:

[org 0x8000]

This org tells NASM to generate code in such a way that it will work if loaded at offset 0x8000. Now, offset 0x8000 is not the same thing as segment 0x8000. If you use jmp 0x8000:0, then you should also use:

[org 0]
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
1

Try again after it fails. I think you will receive an error indication with no message when the disk is spinning up, so the emulator may fail the first time on purpose. Four attempts has worked well for me in both bochs and qemu, but I have not tried it on anything else. You may also want to reset the drive controller before reading to clear any previous errors. Use interrupt 0x13 with al clear and the drive number in dl.


Note: Hardcoding the drive number may work for now, but does not let you support booting from other drives. The BIOS should leave the drive number in dl when starting your bootloader, so you can save that.

ughoavgfhw
  • 39,734
  • 6
  • 101
  • 123
  • I still cannot get what I want. No error is being showed but the code that is loaded into memory is not executed. See update! – ali Jun 17 '12 at 22:25
  • `bh` and `bl` also effect the result of the print function. Personally, I would set the video mode using interrupt 0x10 function 0 and write directly to video memory. Also, if you use 0x8000 as the segment, the linear address is 0x80000, so the `org` directive is wrong. For that program, this would only be a problem if the ram at that location does not exist. If you can, you should connect a debugger and ensure that the processor is jumping to the right location. – ughoavgfhw Jun 17 '12 at 22:56