Page 1 of 1

helloworld problem

Posted: Fri May 28, 2010 7:53 pm
by windtracekimo
I am referring to a simple bootloader program (printing hello world) as the following
http://www.digitalthreat.net/2009/09/a- ... ootloader/ (the code written in NASM is also attached).
I can run it without a problem when using Virtualbox

But, my question is:
If I move the "HelloString db 'Hello World', 0" right after the HLT instruction, then the output contains some junk ascii code after the original string. Why is that? Moving the HelloString somewhere can mess up with the printing?

Code: Select all

[BITS 16]		; Tell NASM we're in 16-bit mode
[ORG 0x7C00]		; Tell NASM that this code will be loaded at 0x7C00
			; to ensure any absolute jumps are calculated correctly

;---------------- BOOTLOADER CODE ----------------;

MOV SI, HelloString	; Store pointer to hello world string in SI
CALL PrintString	; Print the string
HLT			; Stop the processor

;---------------- SCREEN FUNCTIONS ---------------;

PrintString:		; Print a string to screen
			; Assume pointer to string to print is in SI
next_character:
MOV AL, [SI]		; Grab the next character
OR AL, AL		; Check if character is zero
JZ exit_function	; If it is, then return
CALL PrintCharacter	; Else, print the character
INC SI			; Increment pointer for next character
JMP next_character	; Loop
exit_function:
RET

PrintCharacter:		; Print a single character to screen
			; Assume character to print is in AL
MOV AH, 0x0E		; Teletype Mode
MOV BH, 0x00		; Page zero
MOV BL, 0x07		; Light Gray
INT 0x10		; Print Character
RET

;------------------ DATA BLOCK ------------------;

HelloString db 'Hello World', 0

;-------------- PADDING / SIGNATURE -------------;

; $ is current line, $$ is first line, db 0 is a 00000000 byte
; So, pad the code with 0s until you reach 510 bytes
TIMES 510 - ($ - $$) DB 0

; Fill last two bytes (a word) with the MBR signature 0xAA55
DW 0xAA55

Re: helloworld problem

Posted: Fri May 28, 2010 11:28 pm
by xvedejas
Are interrupts enabled? If so then "hlt" will stop after you get an interrupt. try "cli" right before "hlt".

Re: helloworld problem

Posted: Sat May 29, 2010 1:54 am
by Combuster
Better even to put HLT in an infinite loop, it allows you to reboot the machine with ctrl+alt+del (and let the bios do all other sorts of power management).

Re: helloworld problem

Posted: Sat May 29, 2010 5:07 am
by Love4Boobies
Not only that, but CLI will only mask out IRQs, not NMIs, IPIs and SPIs. Thus, here's the correct code:

Code: Select all

cli ; If you want it -- CTRL + ALT + DEL will only work on old machines, where it is implemented as a NMI
hang:
hlt
jmp hang
I was a bit lazy in reading the code but I did notice that you're not initializing your segment registers - SI is not enough to point to HelloString.

Re: helloworld problem

Posted: Sat May 29, 2010 7:02 am
by windtracekimo
changing to the following actually works

Code: Select all

cli
hang:
hlt
jmp hang
However I still got some questions out of curiosity
(1) I am not pressing any key while the program is running, why does cli matter?
(2) If I don't put a loop on the hlt, it seems the program is running twice (helloworld is output twice), and I don't see why??

As for initializing the segment registers, I think you are right, so I did the following.

Code: Select all

   mov   ax, cs      ; Get the current segment
   mov   ds, ax      ; The data is in this segment
   cli         ; disable interrupts while changing stack
   mov   ss, ax      ; We'll use this segment for the stack too
   mov   sp, 0xfffe   ;  Start the stack at the top of the segment
   sti         ; Reenable interrupts
Without this initialization, if I put the "HelloString db 'Hello World', 0" to the beginning of the code, then it output nothing. (I also wander what segment register is the root cause for this??)

Thanks for the reply

Re: helloworld problem

Posted: Sat May 29, 2010 8:13 am
by gerryg400
(1) I am not pressing any key while the program is running, why does cli matter?
(2) If I don't put a loop on the hlt, it seems the program is running twice (helloworld is output twice), and I don't see why??
1. There are other interrupt sources besides kbd. Even some timer, unexpected spurious interrupt or nmi may occur. They will wake the processor from hlt
2. If you don't have the loop, and the processor wakes from halt it will execute whatever follows HLT. Eventually it may wrap around the segment or somehow find its way back to the code that CALLs PrintString again.

You must assume that the processor can wake from HLT. You must have the loop. CLI is not essential. In fact CLI does not prevent NMI.