Bootloader Strange Behavior
Asked Answered
G

2

7

I have been trying to design a simple OS, just the boot sector, and 16-bit real mode with interrupts. I have finally been able to make the OS / bootloader, that I tested in virtual box, and it worked.

I then burned the image to a CD, and booted it to my older desktop, with a Pentium 4, BIOS revision A05, and 1GB of RAM, and it worked perfectly - a simple OS that prints a "header" to the top of the screen, all it does it allow you to type to the screen, with a few keys registered to navigate the cursor.

I then plugged the disc into my 1 year old laptop, with an i5 processor, and 2.6 GB of RAM, and the A05 BIOS Revision, and the cursor seems to move randomly, printing random characters at high speeds, finally stopping at the anscii character 235 (part of the extended character table), at which point the keyboard works fine, keys designated to move the cursor work fine, just the header. This is the computer I tested it on, compilied it on, wrote it on, and burnt the CD with. (I used Linux Mint 12 OS)

I have jumped through all the "hoops" I thought I needed to do: Made an iso image that follows El Torito 'no-emulation' boot standard, boot signature, 512 bytes, and written to the correct sector.

Is it a problem with my code, did I not do something, or is this just normal?

Here is my Code (NASM x86 Syntax):

    ;**************************
    ; Note OS, Experimental OS
    ;**************************
    [org 0x7C00]
    [bits 16]
    start:
    jmp loader                           ;jump to the actual start of bootloader
    times 8 - ($ - $$) db 0          ;pad eight bytes

    ;*********************
    ;El Torito Boot Info Table
    ;*********************

    ;in nasm, I couldn't figure out how to reserve bytes, in the middle of .text
    ;so I zeroed it out.
    times 56 db 0

    loader:
    call cls                ;clear the screen
    mov si, head1           ;setup page headers
    call printf 
    mov si, head2
    call printf
    jmp note                ;start note program

    cls:
    mov ah, 0x0F            ;get current video mode
    mov al, 0x00            ;reset register
    int 0x10                ;get video mode
    mov ah, 0x00            ;set video mode
    int 0x10                ;reset screen
    mov ah, 0x02            ;set cursor pos
    mov bh, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
    ret

    printf:
    .loop                   ;our function that loops
    mov al, [si]            ;load byte
    cmp al, 0               ;if null, end
    je .end
    mov ah, 0x0E            ;function 0E
    mov bh, 0x00            ;page 0x00
    mov bl, 0x0F            ;white text on black background
    int 0x10                ;print
    inc si                  ;increment source index
    jmp .loop               ;repeat
    .end
    ret                     ;return

    ;*******************
    ; Note 'Program'
    ;*******************

    note:
    mov ah, 0x00            ;function 00
    int 0x16                ;get character
    cmp al, '`'             ;go up line?
    je setcur
    cmp al, 0x0D            ;enter?
    je setent
    cmp al, '+'             ;plus?
    je setplu
    cmp al, '-'             ;minus?
    je setminu
    cmp al, '\'             ;reset?
    je loader
    cmp al, 0x08            ;backspace?
    je setback
    mov ah, 0x0E            ;function 0E
    mov bh, 0x00            ;page 00
    mov bl, 0x0F            ;white on black
    int 0x10                ;print
    jmp note                ;repeat

    setcur:
    mov ah, 0x03            ;get cur pos
    mov bh, 0x00            ;page 00
    int 0x10                ;get pos
    cmp dh, 0x00            ;are we at top of page?
    je .begin               ;just reset cursor if so
    sub dh, 0x01            ;go up one line
    .begin
    mov dl, 0x00            ;set to beginning of line
    mov ah, 0x02            ;set cursor function
    mov bh, 0x00            ;page 00
    int 0x10                ;set position
    jmp note                ;read next character

    setent:
    mov ah, 0x0E            ;write character
    mov al, 0x0A            ;begin line
    mov bh, 0x00            ;page 00
    mov bl, 0x0F            ;white on black
    int 0x10                ;print

    setplu:
    mov ah, 0x03            ;get cursor pos
    mov bh, 0x00            ;page 0x00
    int 0x10                ;get pos
    mov ah, 0x02            ;set cursor pos
    add dl, 0x01            ;add one to column
    int 0x10                ;set new pos
    jmp note                ;get next char

    setminu:
    mov ah, 0x03            ;get cursor pos
    mov bh, 0x00            ;page 00
    int 0x10                ;get pos
    mov ah, 0x02            ;set cursor pos
    sub dl, 0x01            ;sub one to column
    int 0x10                ;set new pos
    jmp note                ;get next char

    setback:
    mov ah, 0x03            ;get cursor pos
    mov bh, 0x00            ;page 00
    int 0x10                ;get pos
    mov ah, 0x02            ;set cursor pos
    sub dl, 0x01            ;sub one column
    int 0x10                ;set pos
    mov ah, 0x0E            ;write char
    mov al, ' '             ;write space
    mov bh, 0x00            ;page 00
    mov bl, 0x0F            ;white on black
    int 0x10
    mov ah, 0x02            ;reset cur pos
    int 0x10                ;reset
    jmp note

    ;******************
    ; Our Page Headers
    ;******************
    head1: db '- Note OS Version 1.2-', 0x0A, 0x0D, 0
    head2: db '=======================', 0x0A, 0x0D, 0x0A, 0x0D, 0

    times 510 - ($ - $$) db 0
    dw 0xAA55

For Reference (Things I referenced):

Anscii Table : http://www.asciitable.com/

El-Torito Info : http://wiki.osdev.org/El-Torito

EDIT: Here are the keys I programmed and what they do:

enter - works normally now backspace - works normally now plus - moves cursor right minus - moves cursor left ` - moves cursor to beginning of previous row \ - "soft reboots" jumps almost to beginning of loader

Ganef answered 12/3, 2012 at 0:22 Comment(1)
It would be better if you could minimize that example.Liddy
I
2

The problem is here:

[org 0x7C00]
...
start:
jmp loader                           ;jump to the actual start of bootloader
...
loader:
call cls                ;clear the screen
mov si, head1           ;setup page headers
call printf 
...
printf:
.loop                   ;our function that loops
mov al, [si]            ;load byte

You expect CS=DS=0 when your code starts. DS is not guaranteed to be 0. So, when it's nonzero, mov al, [si] reads bytes from some segment other than segment 0 and there could be some garbage and not a copy of your greeting message.

Also, some BIOSes jump to your code using the address of 0:0x7C00 while others use 0x7C0:0, meaning that even CS isn't guaranteed to have a fixed value.

What I'd do instead is this:

[org 0x7C00]
[bits 16]
start:
jmp loader                           ;jump to the actual start of bootloader
...
loader:
jmp 0:loader2 ; this far jump guarantees CS=0

loader2:
push cs
pop ds ; this guarantees DS=0

; the rest of the code goes here
Itacolumite answered 12/3, 2012 at 6:19 Comment(3)
+1 for initing segment registers. I would also set ES and reset the stack pointer (SS, SP) to a known value.Antipyretic
Thanks that makes alot of sense.Ganef
@adelphus, I'll keep the ss & sp in mind when I get to initalizing the stack, but I'm not gonna worry about it until then. As far as es goes, I'll give it a try.Ganef
G
2

Wowsers; now that's a heavy question!

In reality, it's too generic of a programming question to really work here on Stack Overflow, but just to chuck some things at you, in a hope of being helpful!

If you're getting to a point where it's even moving your cursor at all, albeit randomly then I guess your bootloader is ok; but to be clear - does it even display 'header' on the I5 ?

What I'd be looking at here is the Interrupt vectors/Address lines/etc that you use to make the cursor move around at all. Are you sure the int10 operations are completely generic ?

Grayback answered 12/3, 2012 at 0:30 Comment(4)
Sorry, no it doesn't display the 'header' on the I5.Ganef
Question : if the problem is with int10, how would I find out how to move the cursor on my specific system?Ganef
That's a great question - those op's should be generic, but it would pay to do some googling and see if there are any exceptions or specifics that you need to consider. It might feel like cheating but you could look at the linux source and see how it does it ? Regarding not displaying header, just out of interest what happens if you don't call CLS first ? I'd also look into how to do this with a USB flash drive instead of burning a CD, it'll be a lot simpler!Grayback
I did some googling, and it turns out that the get cur pos isn't actually generic for ALL BIOS's, this may be part of the problem. I'm gonna try to get rid of the CLS and get back to you.Ganef
I
2

The problem is here:

[org 0x7C00]
...
start:
jmp loader                           ;jump to the actual start of bootloader
...
loader:
call cls                ;clear the screen
mov si, head1           ;setup page headers
call printf 
...
printf:
.loop                   ;our function that loops
mov al, [si]            ;load byte

You expect CS=DS=0 when your code starts. DS is not guaranteed to be 0. So, when it's nonzero, mov al, [si] reads bytes from some segment other than segment 0 and there could be some garbage and not a copy of your greeting message.

Also, some BIOSes jump to your code using the address of 0:0x7C00 while others use 0x7C0:0, meaning that even CS isn't guaranteed to have a fixed value.

What I'd do instead is this:

[org 0x7C00]
[bits 16]
start:
jmp loader                           ;jump to the actual start of bootloader
...
loader:
jmp 0:loader2 ; this far jump guarantees CS=0

loader2:
push cs
pop ds ; this guarantees DS=0

; the rest of the code goes here
Itacolumite answered 12/3, 2012 at 6:19 Comment(3)
+1 for initing segment registers. I would also set ES and reset the stack pointer (SS, SP) to a known value.Antipyretic
Thanks that makes alot of sense.Ganef
@adelphus, I'll keep the ss & sp in mind when I get to initalizing the stack, but I'm not gonna worry about it until then. As far as es goes, I'll give it a try.Ganef

© 2022 - 2024 — McMap. All rights reserved.