org 0x7C00
bits 16
%define ENDL 0x0D, 0x0A
;
; FAT12 header
;
jmp short start
nop
bdb_oem: db 'MSWIN4.1' ; 8 bytes
bdb_bytes_per_sector: dw 512
bdb_sectors_per_cluster: db 1
bdb_reserved_sectors: dw 1
bdb_fat_count: db 2
bdb_dir_entries_count: dw 0x0e0
bdb_total_sectors: dw 2880 ; 2880 * 512 = 1.44MB
bdb_media_descriptor_type: db 0F0h ; F0 = 3.5" floppy disk
bdb_sectors_per_fat: dw 9 ; 9 sectors/fat
bdb_sectors_per_track: dw 18
bdb_heads: dw 2
bdb_hidden_sectors: dd 0
bdb_large_sector_count: dd 0
; extended boot record
ebr_drive_number: db 0 ; 0x00 floppy, 0x80 hdd, useless
db 0 ; reserved
ebr_signature: db 29h
ebr_volume_id: db 12h, 34h, 56h, 78h ; serial number, value doesn't matter
ebr_volume_label: db 'GARB OS' ; 11 bytes, padded with spaces
ebr_system_id: db 'FAT12 ' ; 8 bytes
start:
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
push es
push word .after
retf
.after:
mov [ebr_drive_number], dl
; shows messages
mov si, msg_loading
call puts
mov si, welcome
call puts
push es
mov ah, 0x08
int 0x13
jc floppy_error
pop es
mov cl, 0x3F
xor ch, ch
mov [bdb_sectors_per_track], cx
inc dh
mov [bdb_heads], dh
mov ax, [bdb_sectors_per_track]
mov bl, [bdb_sectors_per_track]
xor bh, bh
mul bx
add ax, [bdb_reserved_sectors]
push ax
mov ax, [bdb_sectors_per_fat]
shl ax, 5
xor dx, dx
div word [bdb_bytes_per_sector]
test dx, dx
jz .root_dir_after
inc ax
.root_dir_after:
mov cl, al
pop ax
mov dl, [ebr_drive_number]
mov bx, buffer
call disk_read
; look for kernel.bin
xor bx, bx
mov di, buffer
.search_kernel:
mov si, file_kernel_bin
mov cx, 11
push di
repe cmpsb
pop di
je .found_kernel
add di, 32
inc bx
cmp bx, [bdb_dir_entries_count]
jl .search_kernel
jmp kernel_not_found_error
.found_kernel:
mov ax, [di + 26]
mov [kernel_cluster], ax
mov ax, [bdb_reserved_sectors]
mov bx, buffer
mov cl, [bdb_sectors_per_fat]
mov dl, [ebr_drive_number]
call disk_read
mov bx, KERNEL_LOAD_SEGMENT
mov es, bx
mov bx, KERNEL_LOAD_OFFSET
.load_kernel_loop:
mov ax, [kernel_cluster]
mov ax, 31
mov cl, 1
mov dl, [ebr_drive_number]
call disk_read
add bx, [bdb_bytes_per_sector]
mov ax, [kernel_cluster]
mov cx, 3
mul cx
mov cx, 2
div cx
mov si, buffer
add si, ax
mov ax, [ds:si]
or dx, dx
jz .even
.odd:
shr ax, 4
jmp .next_cluster_after
.even:
and ax, 0x0FFF
.next_cluster_after:
cmp ax, 0x0FF8 ; end of chain
jae .read_finish
mov [kernel_cluster], ax
jmp .load_kernel_loop
jmp wait_key_and_reboot
.read_finish:
mov dl, [ebr_drive_number] ; boot device in dl
mov ax, KERNEL_LOAD_SEGMENT ; set segment registers
mov ds, ax
mov es, ax
jmp KERNEL_LOAD_SEGMENT:KERNEL_LOAD_OFFSET
jmp wait_key_and_reboot
cli
hlt
;
; error handling
;
floppy_error:
mov si, msg_read_failed
call puts
jmp wait_key_and_reboot
kernel_not_found_error:
mov si, msg_kernel_not_found
call puts
jmp wait_key_and_reboot
wait_key_and_reboot:
mov ah, 0
int 0x16
jmp 0FFFFh:0
.halt:
cli
hlt
;
; Prints a string to the screen
; Params:
; - ds:si points to string
;
puts:
; save registers we will modify
push si
push ax
push bx
.loop:
lodsb ; loads next character in al
or al, al ; verify if next character is null?
jz .done
mov ah, 0x0E ; call bios interrupt
mov bh, 0 ; set page number to 0
int 0x10
jmp .loop
.done:
pop bx
pop ax
pop si
ret
;
; Disk routines
;
; Converts an LBA address to a CHS address
; Parameters:
; - ax: LBA address
; Returns:
; - cx [bits 0-5]: sector number
; - cx [bits 6-15]: cylinder
; - dh: head
;
lba_to_chs:
push ax
push dx
xor dx, dx ; dx = 0
div word [bdb_sectors_per_track] ; ax = LBA / SectorsPerTrack
; dx = LBA % SectorsPerTrack
inc dx ; dx = (LBA % SectorsPerTrack + 1) = sector
mov cx, dx ; cx = sector
xor dx, dx ; dx = 0
div word [bdb_heads] ; ax = (LBA / SectorsPerTrack) / Heads = cylinder
; dx = (LBA / SectorsPerTrack) % Heads = head
mov dh, dl ; dh = head
mov ch, al ; ch = cylinder (lower 8 bits)
shl ah, 6
or cl, ah ; put upper 2 bits of cylinder in CL
pop ax
mov dl, al ; restore DL
pop ax
ret
disk_read:
push ax ; save registers we will modify
push bx
push cx
push dx
push di
push cx
call lba_to_chs
pop ax
mov ah, 0x02
mov di, 3
.retry:
pusha
stc
int 0x13
jnc .done
popa
call disk_reset
dec di
test di, di
jnz .retry
.fail:
jmp floppy_error
.done:
popa
pop di
pop dx
pop cx
pop bx
pop ax ; restore registers modified
ret
disk_reset:
pusha
mov ah, 0
stc
int 13h
jc floppy_error
popa
ret
msg_loading:db "Loading.....", ENDL, 0
welcome: db "Welcome to GARB OS", ENDL, 0
msg_read_failed: db "Read from disk failed", ENDL, 0
file_kernel_bin: db "KERNEL BIN"
msg_kernel_not_found: db "NO KERNEL WAS FOUND", ENDL, 0
kernel_cluster: dw 0
KERNEL_LOAD_SEGMENT equ 0x2000
KERNEL_LOAD_OFFSET equ 0
times 510-($-$$) db 0
dw 0xAA55
buffer:
How do I solve the 'src/bootloader/boot.asm:324: error: TIMES value -17 is negative' error? I am building an OS and I don't know how to solve this error as I am new assembly.
I am following a tutorial and the code is the exact same. I thought times 510 - ($ - $$) db 0
was the standard as it fills 512 bytes with 0s.
The guy in the tutorial is not having any problems and no one is talking about it in the comments. I am using this Makefile to compile the code:
ASM=nasm
CC=gcc
TOOLS_DIR=tools
SRC_DIR=src
BUILD_DIR=build
.PHONY: all floppy_image kernel bootloader clean always tools_fat
all: floppy_image tools_fat
#
# Floppy image
#
floppy_image: $(BUILD_DIR)/main_floppy.img
$(BUILD_DIR)/main_floppy.img: bootloader kernel
dd if=/dev/zero of=$(BUILD_DIR)/main_floppy.img bs=512 count=2880
mkfs.fat -F 12 -n "GBOS" $(BUILD_DIR)/main_floppy.img
dd if=$(BUILD_DIR)/bootloader.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc
#mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin"
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin"
mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::test.txt"
#
# Bootloader
#
bootloader: $(BUILD_DIR)/bootloader.bin
$(BUILD_DIR)/bootloader.bin: always
$(ASM) $(SRC_DIR)/bootloader/boot.asm -f bin -o $(BUILD_DIR)/bootloader.bin
#
# Kernel
#
kernel: $(BUILD_DIR)/kernel.bin
$(BUILD_DIR)/kernel.bin: always
$(ASM) $(SRC_DIR)/kernel/main.asm -f bin -o $(BUILD_DIR)/kernel.bin
#
# Tools
#
tools_fat: $(BUILD_DIR)/tools/fat
$(BUILD_DIR)/tools/fat: always $(TOOLS_DIR)/fat/fat.c
mkdir -p $(BUILD_DIR)/tools
$(CC) -g -o $(BUILD_DIR)/tools/fat $(TOOLS_DIR)/fat/fat.c
#
# Always
#
always:
mkdir -p $(BUILD_DIR)
#
# Clean
#
clean:
rm -rf $(BUILD_DIR)/*
Any help would be appreciated!