Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
nakst authored Jul 12, 2020
1 parent 19fd5ef commit 875e325
Show file tree
Hide file tree
Showing 7 changed files with 5,783 additions and 0 deletions.
270 changes: 270 additions & 0 deletions boot.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
[bits 16]
[org 0x7C00]
[cpu 386]

; Memory map:
; 0x500-0x700: filesystem header
; 0x700-0x900: sector table buffer
; 0x900-0xB00: file sector buffer
; 0x7000-0x7C00: stack
; 0x7C00-0x7E00: this code
; 0x10000-0x20000: loaded program

start:
; Setup segment registers and the stack.
cli
xor ax,ax
mov ds,ax
mov ss,ax
mov sp,0x7C00 ; Put stack below the code.
sti
cld
jmp 0x0000:.set_cs
.set_cs:

; Save the BIOS drive number.
mov [drive_number],dl

; Print a loading message.
mov si,loading_message
call print_string

; Get drive parameters.
mov ah,0x08
mov dl,[drive_number]
xor di,di
int 0x13
mov si,error_read
jc error
and cx,31
mov [max_sectors],cx
inc dh
shr dx,8
mov [max_heads],dx

; Load the filesystem header.
xor ax,ax
mov es,ax
mov di,1
mov bx,0x500
call load_sector

; Check for correct signature and version.
mov si,error_disk
mov ax,[0x500]
cmp ax,0x706C
jne error
mov ax,[0x502]
cmp ax,1
jne error

; Load the root directory.
mov ax,[0x51C]
mov [file_remaining_size],ax
mov ax,[0x520]
mov [current_sector],ax
mov di,ax
xor ax,ax
mov es,ax
mov bx,0x900
call load_sector

; Scan the root directory.
xor bx,bx
.scan_root_directory:
cmp bx,0x200
jne .loaded_sector
call next_file_sector
xor bx,bx
.loaded_sector:

; Compare file name.
xor ax,ax
mov es,ax
mov cx,7
mov si,program_name
mov di,0x900
add di,bx
rep cmpsb
jne .next_entry

; Save the startup program's first sector, size and checksum.
mov al,[0x917 + bx]
mov [checksum],al
mov ax,[0x910 + bx]
mov [file_remaining_size],ax
mov di,[0x914 + bx]
mov [current_sector],di
jmp .load_startup_program

; Go to the next entry.
.next_entry:
add bx,0x20
sub word [file_remaining_size],0x20
cmp word [file_remaining_size],0
jne .scan_root_directory
mov si,error_disk
jmp error

; Load the startup program.
.load_startup_program:
xor bx,bx
mov es,bx
mov bx,0x900
call load_sector

; Copy the sector to the destination.
.copy_sector:
mov bx,0x1000
mov es,bx
mov di,[file_destination]
mov si,0x900
mov cx,0x200
rep movsb

; Calculate checksum.
mov bl,[checksum]
mov si,0x900
mov cx,0x200
.checksum_loop:
lodsb
xor bl,al
loop .checksum_loop
mov [checksum],bl

; Load the next sector of the startup program.
add word [file_destination],0x200
mov ax,[file_remaining_size]
cmp ax,0x200
jbe .launch

sub word [file_remaining_size],0x200
call next_file_sector
jmp .copy_sector

; Launch the startup program.
.launch:
mov si,error_disk
cmp byte [checksum],0
jne error
mov dl,[drive_number]
jmp 0x1000:0x0000

next_file_sector:
; Do we need to switch the sector table buffer?
mov ax,[current_sector]
shr ax,8 ; 256 sector table entries per sector
cmp al,[current_sector_table]
je .skip_switch
mov [current_sector_table],al

; Load the new sector table buffer.
add ax,2
mov di,ax
xor bx,bx
mov es,bx
mov bx,0x700
call load_sector
.skip_switch:

; Get the next sector.
mov bx,[current_sector]
and bx,0xFF
shl bx,1
mov di,[0x700 + bx]
mov [current_sector],di

; Load the next sector.
xor bx,bx
mov es,bx
mov bx,0x900
jmp load_sector

; di - LBA.
; es:bx - buffer
load_sector:
mov byte [read_attempts],5

.try_again:

mov si,error_read
mov al,[read_attempts]
or al,al
jz error
dec byte [read_attempts]

; Calculate cylinder and head.
mov ax,di
xor dx,dx
div word [max_sectors]
xor dx,dx
div word [max_heads]
push dx ; remainder - head
mov ch,al ; quotient - cylinder
shl ah,6
mov cl,ah

; Calculate sector.
mov ax,di
xor dx,dx
div word [max_sectors]
inc dx
or cl,dl

; Load the sector.
pop dx
mov dh,dl
mov dl,[drive_number]
mov ax,0x0201
int 0x13
jc .try_again

ret

; ds:si - zero-terminated string.
error:
call print_string
jmp $

; ds:si - zero-terminated string.
print_string:
lodsb
or al,al
jz .done
mov ah,0xE
int 0x10
jmp print_string
.done: ret

file_destination:
dw 0
current_sector_table:
db 0xFF

error_read:
db "Cannot read boot disk.",0
error_disk:
db "Corrupt boot disk.",0
program_name:
db "system",0 ; don't forget to change name length in comparison!
loading_message:
db 'Loading... ',0

times (0x1FE - $ + $$) nop
dw 0xAA55

; Uninitialised variables outside the boot image.
drive_number:
db 0
read_attempts:
db 0
max_sectors:
dw 0
max_heads:
dw 0
current_sector:
dw 0
file_remaining_size:
dw 0
checksum:
db 0
29 changes: 29 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mkdir -p bin bin/dest
set -e

# Create a blank floppy image.
dd if=/dev/zero of=bin/drive.img bs=512 count=2880 status=none

# Assemble and copy the bootloader.
nasm boot.s -f bin -o bin/boot
dd if=bin/boot of=bin/drive.img bs=512 count=1 conv=notrunc status=none

# Assemble the system.
nasm system.s -f bin -o bin/dest/system

# Check the system fits in 32KB.
# The bootloader can't load files greater than a 64KB segment,
# and the system uses the upper 32KB of its segment for buffers.
if [ $(wc -c <bin/dest/system) -ge 32768 ]; then
echo "System too large (more than 32KB)."
exit 1
fi

# Copy the system and other files to the floppy.
gcc -o bin/mkfs mkfs.c
cp *.lisp bin/dest
bin/mkfs bin/drive.img 2880 bin/dest

# Launch the emulator.
qemu-system-x86_64 -drive file=bin/drive.img,index=0,if=floppy,format=raw -boot a
# bochs -f bochs_config.txt -q
40 changes: 40 additions & 0 deletions mandelbrot.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[set-graphics 1]

; Constants.
[let WIDTH 320]
[let HEIGHT 200]
[let MAXIT 15]
[let FIXED 500]

; Fixed-point arithmetic.
[let mf [fun [x] [* x FIXED]]]
[let *f [fun [x y] [muldiv x y FIXED]]]

; Complex numbers.
[let re [fun [z] [car z]]]
[let im [fun [z] [cdr z]]]
[let +c [fun [a b] [cons [+ [re a] [re b]] [+ [im a] [im b]]]]]
[let square-c [fun [z] [cons
[- [*f [re z] [re z]] [*f [im z] [im z]]]
[* 2 [*f [re z] [im z]]]]]]
[let length-squared [fun [z] [+ [*f [re z] [re z]] [*f [im z] [im z]]]]]

; Viewport.
[let getx [fun [x] [- [muldiv x [mf 3] WIDTH] [mf 2]]]]
[let gety [fun [y] [- [muldiv y [mf 2] HEIGHT] [mf 1]]]]

; Image generation.
[let iterate [fun [z c] [+c c [square-c z]]]]
[let do_pixel [fun [X Y c] [let i 0] [let z c]
[while [and [< i MAXIT] [<= [length-squared z] [mf 4]]]
[do [= z [iterate z c]] [inc i]]]
[poke 10 [+ X [* 320 Y]] [+ 64 i]]]]
[let do_row [fun [Y y] [let col 0] [while [< col WIDTH]
[do [do_pixel col Y [cons [getx col] y]] [inc col]]]]]
[let image [fun [] [let row 0] [while [< row HEIGHT]
[do [do_row row [gety row]] [inc row]]]]]

; Show the image and wait for user input.
[image]
[wait-key]
[set-graphics nil]
Loading

0 comments on commit 875e325

Please sign in to comment.