I am using this code for a Hello world bootloader. Instead of printing out “Hello world\n” it just prints out a ‘H’ and hangs. I have used loadsb print out the message successfully but I can’t understand why this approach won’t work as it seems equivalent.
[ORG 0x7c00]
[BITS 16]
xor ax, ax ;make it zero
mov ds, ax
mov ecx, msg
bios_print:
mov al, [ecx]
add ecx,1
cmp al, 0 ;zero=end of str
je hang ;get out
cmp al,100
jge hang
mov ah, 0x0E
int 0x10
jmp bios_print
hang:
jmp hang
msg db 'Hello World', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
Edit:
I changed the [BITS 64] to [BITS 16]
Your program is working exactly in a way you’ve coded it. The lower-case
ein ASCII is represented as65h, which equals 101 in decimal. Therefore, executingcmp al, 100 / jge hangife(101) is inalresults in a jump to the labelhang. Everything’s alright. 🙂A solution to your problem would be simply deleting that line, since I don’t really see any purpose for it – seeing how you’ve got your string terminated by a
\0, the loop will end when it reaches the end.Four extra tips, though :
cmpafter anadd, especially if the only condition of the jump can be represented by one of the flags. In this case,add ecx, 1 / cmp al, 0 / je hangcan be replaced by a very simpleadd ecx, 1 / jz hang. This saves you two bytes, so valuable in those bootsector conditions.pushadoes just that. It’s generally a rule of thumb to preserve all the runtime information when calling any piece of code you haven’t written yourself (though this may sound extreme in more “civilized” environments – but BIOS and general real mode code isn’t one).mov ecx, msgis simply redundant – the offset part of the address will never be longer than 16 bits. Same goes foradd ecx, 1. Just replaceecxwithcxin both those cases.hltinstruction. It makes your CPU’s blood pressure much lower, and there’s really no use in stressing it all over the place. Simply addhltafter thehanglabel and before the jump.