Page 1 of 2

simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 11:59 am
by pompon
Hi, I'm trying to write a bootsector which will print "Hello world!!!" on the screen:

Code: Select all

org 0h

main:
	mov		ax, 0x07c0
	cli
	mov		ds, ax
	mov		es, ax
	mov		ss, ax
	mov		sp, 03feh
	sti
.loop:
	mov		si, hello_text
	call	put_string
	mov 	ah, 0
	int 	0x16
	jmp		.loop

put_string:
	lodsb
	cmp		al, 0
	je		.return
	mov		ah, 0x0E
	int		0x10
	jmp		put_string
.return:
	ret

hello_text db 'Hello world!!!',13,10,0

times 510-($-$$) db 0
dw	0xaa55
I assemble the code to flat binary with NASM, copy with dd on the pendrive. My cpu is Intel Core 2 Duo T5550.
While emulating with qemu everything is ok, but when I boot it from pendrive "hello world" does not appear. I've read many tutorials yet but nothing helped. Could anyone tell me what I'm doing wrong?

Re: simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 12:18 pm
by sebihepp
Hello,

although something doesn't provide best performance, I find no mistake.
The only thing is, that Function 0x0E of Interrupt 0x10 needs the color in the BL register.
Just try to set BL to 0x0F for white on black for example. Then make sure you really boot from
"pendrive". (What is a pendrive??? :shock: )

If this doesn't help, just set the video mode. This is done by Function 0x00 of Interrupt 0x10.
So AH is set to 0x00, AL contains the video mode (0x03 for 25x80 text-mode with 16 colors)
and then fire interrupt 0x10.

Hope that helps. I will meditate about other resolutions... [-o< :D

Greetings
Sebihepp

Re: simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 12:43 pm
by pompon
Thanks! It still doesn't work properly, but there occured an improvement. After setting video mode "Hello world" has been printed, nevertheless it hadn't stopped on 0 byte but followed printing random characters. Code now looks like that:

Code: Select all

org 0h

main:
	mov		ax, 0x07c0
	cli
	mov		ds, ax
	mov		es, ax
	mov		ss, ax
	mov		sp, 03feh
	sti
	;set video mode
	mov		ah, 0x00
	mov		al, 0x03
	int		0x10
.loop:
	mov		si, hello_text
	call	put_string
	mov 	ah, 0
	int 	0x16
	jmp		.loop

put_string:
	lodsb
	cmp		al, 0
	je		.return
	mov		ah, 0x0E
	mov		bl, 0x0F
	int		0x10
	jmp		put_string
.return:
	ret

hello_text db 'Hello world!!!',13,10,0

times 510-($-$$) db 0
dw	0xaa55
I've also added "mov bl, 0x0F", but it didn't change anything. Do you have any further suggestions?
[pendrive is other name for flash disk]

Re: simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 2:01 pm
by Firestryke31
bh should be 0 unless you specifically change the text page (or whatever it's called), in which case it should be whichever page you changed it to. There are a few space-saving things I saw at a glance, but they're not too important. Also note that you never set CS to 0x07C0, but with the code you have so far it doesn't matter (it's small enough that jumps and calls can be relative instead of absolute).

Re: simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 2:24 pm
by sebihepp
Try

Code: Select all

test al, al
jz .return
instead of

Code: Select all

cmp al, 0
je .return
Edit:
I don't know why, but it seems that a cmp to zero doesn't result in the equal flag set.
Instead the zero flag is set.

Re: simple bootsector beginner's problem

Posted: Fri Mar 13, 2009 3:28 pm
by JohnnyTheDon
Uh, je == jz. Its just another name for the same instruction. There is no 'equal flag'.

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 4:29 am
by sebihepp
Okay, but I have had the same problem.
test + jz works, cmp + je doesn't work.

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 4:42 am
by JohnnyTheDon
There isn't any reason that I can think of that it shouldn't. The only thing I can think of is that your file is missing a BITS 16 directive.

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 6:00 am
by AJ
Hi,

As Firestryke indicates above, you assume that your code is running at 0x07C0:0x0000. Could you start off with a jmp to ensure that this is the case? (The BIOS could have run your code at 0x0000:0x7C00 or any other valid CS:IP combination). I know this is unlikely to be the cause of the problem as jumps are within short range, but it could cause issues later.

Cheers,
Adam

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 8:12 am
by Firestryke31
In all of my putStr implementations I use this:

Code: Select all

	or al, al
	jz return
which is 4 bytes. I haven't tried some of the others I've seen here, but the reason I use this is a hangover from when I did z80 ASM (where that was smaller than similar instructions).

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 9:50 am
by pompon
I've added "bits 16" and "jmp 0x07c0:main" and tested it on my notebook ASUS F3Sseries (Intel Core 2 Duo T5550) and I obtained pure black screen. Next I've tried also on ASUS PC (Pentium D) and it printed "Hello world" properly. Unfortunately it wasn't reacting on key pressing, which should cause next line printing. Adding "mov bh,0" in put_string and replacing "cmp al,0; je .return" with "test al,al; jz .return" made no differenece. Any ideas? Could it be the cpu matter?

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 10:12 am
by Troy Martin
Theoretically, no, there should be no difference.

[offtopic]The box I'm posting on has the same processor as your ASUS laptop. Sadly it has no floppy drive :( [/offtopic]

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 10:23 am
by pompon
Troy Martin wrote: [offtopic]The box I'm posting on has the same processor as your ASUS laptop. Sadly it has no floppy drive :( [/offtopic]
Neither mine. I wrote in the first post that I boot it from flash disk.

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 10:32 am
by Dex
I would like to help, but first i need a problem, i tested your 2nd code on 8 differant PC's and it works on all of them.

Re: simple bootsector beginner's problem

Posted: Sat Mar 14, 2009 11:14 am
by JohnnyTheDon
Did you use a long jump to make sure segments are set properly (as was suggested)? That would explain why it works on one computer but not another (bioses can load segments with whatever they want).