I am learning to write a 16-bit bootloader using NASM with BIOS interrupts to print strings to the screen. I’ve created a simple print subroutine in an external file (printer.asm
), and I'm using %include
to bring it into my main bootloader file.
Here’s where it gets weird: depending on where I place the %include
directive, I get completely different outputs.
Here's the code and all the placements of the include with the different outputs it gives:
org 0x7C00
bits 16
%include "printer.asm" ; placing include here prints "S" (probably garbage)
mov bx, GREETING
call print
%include "printer.asm" ; placing include here prints the GREETING message twice (Hello WorldHello World)
loop:
jmp loop
%include "printer.asm" ; placing include here prints the GREETING message as expected (Hello World)
GREETING:
db "Hello World", 0
times 510-($-$$) db 0
dw 0xAA55
I understand that NASM uses a flat binary format and memory layout matters, but I thought %include
is just a textual paste. Why is it behaving this way?
Is the string or code being overlapped? Is NASM putting instructions and data in conflicting places? What’s the correct way to organize includes and data to prevent this?
This is the printer.asm
file (included file):
; prints contents stored at BX
print:
pusha
mov ah, 0x0E ; TTY mode
start:
mov al, [bx]
cmp al, 0
je done
int 0x10
add bx, 1
jmp start
done:
popa
ret
%include
puts the external file exactly where the command was used. The procedure from the external file thus appears on that spot in the bootloader program. Because this kind of program always gets executed from the top, you couldn't have the subroutine before anything else because then you would not have the opportunity to call
it!
The second emplacement allows the normal execution to fall-through in the subroutine, again violating the requirement that a subroutine should be call
ed.
Only the third emplacement is fine, since it stays out of the direct execution path.
Ask yourself the question about where you would write that subroutine if it was not to come from an external file. Then only the 3rd emplacement would be a good choice. Possibly even writing the subroutine below the 'Hello' message...