I have the following x86 program:
mov ah, 0x0e ; Set up call to BIOS routine to print character
mov al, [character] ; Stick the byte at label "character"
int 0x10 ; Display character in al
jmp $ ; Loop forever
character:
db 0x41 ; Put the byte "A" at this position
times 510-($-$$) db 0 ; Pad with zeros and end with the magic number for a bootloader
db 0x55
db 0xaa
I'm running it in two different ways:
- In qemu
- Writing it to a USB stick with
dd
and booting it on an old 64 bit laptop
I use the following commands to run this code:
$ nasm -f bin -o boot.bin main.s
$ qemu-system-x86_64 boot.bin # to test
$ dd if=boot.bin of=/dev/sda # to put it on a USB stick
The code as written above doesn't work in either case. On the hardware it displays a blinking cursur, and on qemu it prints a Cyrillic letter, rather than "A". So I change the second (non-empty) line to
mov al, [0x7c00 + character]
adding the offset 0x7c00
to the label, since according to some sources x86 puts your bootloader at 0x7c00
in memory. This works as expected in qemu, but continues to give me a blinking cursor on the hardware. Note that this has the same effect as putting [org 0x7c00]
at the top, by which I mean the binaries produced by using the above line or by adding an org
directive are identical (I compared their md5s).
To make sure my hardware doesn't have some weird character set where 0x41
isn't an "A", I tried
mov al, 0x41
and that works on both qemu and the hardware.
How can I properly reference the data stored at "character" so that my laptop will find the value that's supposed to be there? Note that because this is a bootloader the CPU is (if I understand correctly) in 16-bit real mode.