I am trying to write my own bootloader. Although it works great on QEMU, Bochs, and VirtualBox, I can't get it to work on my laptop.
On my laptop, the bootloader behaves differently to all emulators hanging from a seemingly random place, refusing to print, even skipping some instructions jmp $.
While I have a lot of problems with "real equipment", I think there is one reason for them.
The following code is a short bootloader that should print a “TEST” message 3 times, then hang, jumping to the same place:
[BITS 16]
[ORG 0x7C00]
jmp 0x0000:start_16 ; In case bootloader is at 0x07C0:0x0000
start_16:
xor ax, ax
mov ds, ax
mov es, ax
cli ; Disable interrupts
mov ss, ax
mov sp, 0x7C00
sti ; Enable interrupts
cld ; Clear Direction Flag
; Store the drive number
mov [drive_number], dl
; Print message(s)
mov si, msg
call print_string
mov si, msg
call print_string
mov si, msg
call print_string
jmp $ ; HALT
; print_string
; si = string
print_string:
pusha
mov ah, 0x0E
.repeat:
lodsb
cmp al, 0x00
je .done
int 0x10
jmp short .repeat
.done:
popa
ret
; Variables
drive_number db 0x00
msg db 'TEST', 0x0D, 0x0A, 0x00
times 510-($-$$) db 0x00
db 0x55
db 0xAA
Compile and emulate code with
$ nasm -f bin bootloader.asm
$ qemu-system-x86_64 bootloader
On emulators, it prints "TEST" three times and freezes. On my laptop it prints "TEST" followed by 3 strange characters:

Most bootloader code from http://wiki.osdev.org does not work either. For example, none of the code snippets from http://wiki.osdev.org/Babystep2 work on my laptop.
What is wrong with my code? How can i fix this?
Additional Information
If I delete 2 unnecessary mov si, msg, the message "TEST" will be printed twice .
A laptop:
- Asus Vivobook S200,
- Processor: Intel i3-3217U
- BIOS: American Megatrends, version 210.
- The computer works just fine with any other bootloader, such as Grub.
Build and Burn:
$ nasm -f bin bootloader.asm
$ qemu-system-x86_64 bootloader
$ sudo dd if=/dev/zero of=/dev/sdd bs=1M count=1
$ sudo dd if=bootloader of=/dev/sdd conv=fsync
$ qemu-system-x86_64 /dev/sdd
Change 1
Ross Ridge noted in the comments that the Ω♣|first 3 bytes of the bootloader.2
:
print_string:
pusha
.repeat:
mov ah, 0x0E
xor bx, bx
cld ; Clear Direction Flag
lodsb
cmp al, 0x00
je .done
int 0x10
jmp short .repeat
.done:
popa
ret
msg db 'TEST', 0x00
TEST. .
3
, dumpregs . int 0x10 .
dumpregs drive_number jmp $ . 1 . :

:
https://gist.github.com/anonymous/0ddc146f73ff3a13dd35
4
:
$ ndisasm -b16 bootload2 -o 0x7c00
https://gist.github.com/anonymous/c9384fbec25513e3b815