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
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
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 ?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With