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