Video Teletype (int 0x10 / ah=0xE) mistakenly repeated by Qemu

Viewed 194

I'm trying to reproduce the qemu hello-word example from the post. The code doesn't seem to have much room for bugs:

# boot.asm
.code16 
.global init       # makes our label "init" available to the outside 
init:              # this is the beginning of our binary later. 
  mov $0x0e41, %ax # sets AH to 0xe (function teletype) and al to 0x41 (ASCII "A") 
  int $0x10        # call the function in ah from interrupt 0x10 
  hlt              # stops executing 
.fill 510-(.-init), 1, 0 # add zeroes to make it 510 bytes long 
.word 0xaa55       # magic bytes that tell BIOS that this is bootable

But after compiling it and loading it with qemu:

as -o boot.o boot.asm
ld -o boot.bin --oformat binary -e init boot.o
qemu-system-x86_64 boot.bin

the character 'A' is printed multiple times: enter image description here

I've repeated the experiment multiple times. Mostly it behaves normally and only prints the character once. Sometimes it repeats the character 2 or 3 times. The screenshot shows a rare but existing behavior.

Does anyone have an idea how this could happen?

Thanks in advance.

1 Answers

Let me summarize fuz's and Brendan's comments.

The code was wrong because hlt halt the cpu only until the next interrupt. When the next interrupt arrives, the cpu resumes and continues running garbage codes (here: 0x00 0x00 ... 0x00 0x55 0xaa 0xrandom-garbage), in which the machine code for int might appear and get executed, thereby repeat the printing of 'A'.

The correct way of halting the cpu, as suggested by Brendan, is to put the hlt instruction into an infinite loop:

.die
hlt
jmp .die
Related