How to assemble / link two Assembly files that each reference the same function (for bootloader)

29 Views Asked by At

I have my first stage boot1.asm loaded at 7C00 which calls printString which resides in printString.asm My second stage, boot2.asm, which also calls printString - cannot call it as it cannot access external references.

I am currently using the following code to assemble my first stage:

nasm -f bin -I functions/ -o bin/boot1.bin boot1.asm

where functions contains printString.asm, a readDisk function, etc. I include them using the %include directive in boot1

I am using the following commands to make my floppy.img:

dd if=/dev/zero of=floppy.img bs=1024 count=1440
dd if=bin/boot1.bin of=floppy.img bs=512 count=1 conv=notrunc
dd if=bin/boot2.bin of=floppy.img bs=512 count=1 seek=1 conv=notrunc

then creating an iso with:

cp floppy.img iso/
  genisoimage -input-charset utf-8 -b floppy.img -o myos.iso iso/

emulating with:

qemu-system-i386 -cdrom myos.iso

I know the problem lies with how I am forming the floppy.img with the first and second boot.asm files. I am currently assembling the second stage into its own flat binary using nasm but that is obviously wrong as they don't support external references. But I also can't use include directives in this file as I have already included them in boot1.asm? Possibly I am going about this wrong, but I hope my problem is clear, want to maintain the modularity of separate files for functions and have separate files for boot stages.

Everything works fine, I get to the second stage and can print a message ONLY IF the print function resides within the boot2.asm file, - but i obviously want to reuse my printString function - how do I go about this and what am I misunderstanding?

Makefile

# MAKEFILE LAYOUT
#  - Programs and directories are in capitals e.g. src/ = SRC
#  - Files are not in capitals e.g. floppy.img = $(floppy)


# Programs
QEMU := qemu-system-i386
GENISOIMAGE := genisoimage
NASM := nasm
MKDIR := mkdir -p
RM := rm
CP := cp
DD := dd

# Top directories
SRC := src
BIN := bin

# Module directories
BOOT := $(SRC)/boot
FUNCTIONS := $(BOOT)/functions
ISO := iso

# Files
bootfiles := $(wildcard $(BOOT)/*.asm)
myos := myos
floppy := floppy.img
isofile := $(myos).iso

all: bootloader

# Emulate bootloader
bootloader: $(isofile)
    $(QEMU) -cdrom $<

# Create ISO
$(isofile): $(ISO) $(floppy)
    $(CP) $(floppy) $(ISO)/
    $(GENISOIMAGE) -A "SCC300" -input-charset utf-8 -b $(floppy) -o $@ $(ISO)/


# Floppy disk image
$(floppy): $(BIN)/boot1.bin $(BIN)/boot2.bin
    $(DD) if=/dev/zero of=$@ bs=1024 count=1440     # zero filled 1.44MB floppy disk image
    $(DD) if=$(BIN)/boot1.bin of=$@ bs=512 count=1 conv=notrunc
    $(DD) if=$(BIN)/boot2.bin  of=$@ bs=512 seek=1 count=1 conv=notrunc

# Assemble boot stages
$(BIN)/boot2.bin: $(BOOT)/boot2.asm     # assemble boot0
    $(NASM) -f bin -I '$(FUNCTIONS)/' -o $@ $<

$(BIN)/boot1.bin: $(BOOT)/boot1.asm     # assemble boot0
    $(NASM) -f bin -I '$(FUNCTIONS)/' -o $@ $<

# Directory Targets
$(ISO):
    $(MKDIR) $@

boot1.asm

[ORG 7C00h]         ; Loaded by BIOS at 0x7C00
[BITS 16]               ; 16 bit Real Mode
jmp 0000h:$_start   ; Enfore CS:IP

%include "printString.asm"
; %include "printHexString.asm"
%include "resetFloppyController.asm"
%include "readFromDisk.asm"

%define ENDL 0Dh, 0Ah

BOOT2_OFFSET:   equ 7E00h
HELLO_WORLD:        db "Hello World!", ENDL, 0

global _start

_start:
    ; Testing print functions
    mov bx, HELLO_WORLD
    call printString

    ;mov dx, 1FB6h
    ;call printHexString

    ; Init segments to 0
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Stack grows downwards below bootsector
    mov ss, ax
    mov sp, 7C00h

    ; Read second sector from disk
    sti
    call resetFloppyController

    mov ax, 07E0h
    mov es, ax
    mov bx, 00h
    call readFromDisk
    jmp 07E0h:0000h


times 510-($-$$) db 0   ; Fill the rest of the sector with 0'sector (assembler directive)
dw 0AA55h

boot2.asm Here, the printString2 function works because it is declared in the same file

[ORG 0000h] ; Ensure offset is same as IP after jump
[BITS 16]

extern printString

; Ensure DS matches up after jump
boot2:
    mov ax, cs
    mov ds, ax

    mov bx, buffer
    call printString
    jmp $

buffer: db 'Second Sector', 0

printString2:
    mov si, bx
    pusha

printChar2:
    lodsb
    or al, al       ; Set or clear ZF
    jz printStringDone2    ; Jump at null byte
    mov ah, 0Eh
    int 10h         ; Call video - teletype output interrupt
    jmp printChar2

printStringDone2:
    popa
    ret

; Setting up the GDT
; cli
times 512-($-$$) db 0 ; Fill rest of block
0

There are 0 best solutions below