0

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
1
  • 3
    You may like to read stackoverflow.com/a/41205267/634919, since I think one of the underlying issues here may be a confusion about how labels work, and how they are different from defining functions in a high-level language. Commented Jun 6 at 6:25

1 Answer 1

3

%includeputs 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 called.

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...

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.