diff --git a/stage4/bootasm2.S b/stage4/bootasm2.S index 6d15cf7..ebd077c 100644 --- a/stage4/bootasm2.S +++ b/stage4/bootasm2.S @@ -275,14 +275,14 @@ cons_filled_rect_check_x_dir: cmpw $0, %ax jge cons_filled_rect_check_y_dir add %ax, rectx(%bp) - neg rectwidth(%bp) + negw rectwidth(%bp) cons_filled_rect_check_y_dir: movw rectheight(%bp), %ax # Check if the user has entered a negative height value and swap the direction to a pos cmpw $0, %ax jge cons_filled_rect_check_x_zero add %ax, recty(%bp) - neg rectheight(%bp) + negw rectheight(%bp) cons_filled_rect_check_x_zero: movw rectx(%bp), %ax # Check if the x value is a negative value, set it to 0 and figure out the offset so we @@ -344,8 +344,7 @@ cons_filled_rect_setup: movw (screen_width), %ax # Set ax to 320 so that we can multiply this by y mul %dx # does the (y * 320) part of our math add rectx(%bp), %ax # Add the value of x to register ax - movw %ax, %si - lea %es:(%si), %bx # Load the memory address into the bx register + movw %ax, %bx # Load the memory offset address into the bx register movw rectheight(%bp), %si # Set the counter to our height which should be the number of lines to draw to diff --git a/stage4/bootasm2.o b/stage4/bootasm2.o index 6c43a64..3410ea9 100644 Binary files a/stage4/bootasm2.o and b/stage4/bootasm2.o differ diff --git a/stage4/bootblock2 b/stage4/bootblock2 index dda25ec..8f6d29a 100644 Binary files a/stage4/bootblock2 and b/stage4/bootblock2 differ diff --git a/stage4/bootblock2.o b/stage4/bootblock2.o index ad38871..13fe6b5 100644 Binary files a/stage4/bootblock2.o and b/stage4/bootblock2.o differ diff --git a/stage4/xv6.img b/stage4/xv6.img index 6ffd19d..1b593b8 100644 --- a/stage4/xv6.img +++ b/stage4/xv6.img @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91937ee0ce0a78815628538f19ff3ee6cf003e740e7815fb11539871c39e068e +oid sha256:465ada267f22651cb6209e385990be1d287f9831c9b4c7c1db2efd0a005e1d6a size 5120000 diff --git a/stage5/.vscode/tasks.json b/stage5/.vscode/tasks.json new file mode 100644 index 0000000..c567be5 --- /dev/null +++ b/stage5/.vscode/tasks.json @@ -0,0 +1,19 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build and QEMU", + "type": "shell", + "command": "make qemu", + "problemMatcher": [] + }, + { + "label": "Build and QEMU (debug)", + "type": "shell", + "command": "make qemu-gdb", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/stage5/Makefile b/stage5/Makefile new file mode 100644 index 0000000..e409242 --- /dev/null +++ b/stage5/Makefile @@ -0,0 +1,102 @@ +# Try to infer the correct TOOLPREFIX if not set +ifndef TOOLPREFIX +TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \ + then echo 'i386-jos-elf-'; \ + elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \ + echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \ + echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \ + echo "*** environment variable to that prefix and run 'make' again." 1>&2; \ + echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +# If the makefile can't find QEMU, specify its path here +# QEMU = qemu-system-i386 + +# Try to infer the correct QEMU +ifndef QEMU +QEMU = $(shell if which qemu > /dev/null; \ + then echo qemu; exit; \ + elif which qemu-system-i386 > /dev/null; \ + then echo qemu-system-i386; exit; \ + elif which qemu-system-x86_64 > /dev/null; \ + then echo qemu-system-x86_64; exit; \ + else \ + qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \ + if test -x $$qemu; then echo $$qemu; exit; fi; fi; \ + echo "***" 1>&2; \ + echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \ + echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \ + echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \ + echo "***" 1>&2; exit 1) +endif + +CC = $(TOOLPREFIX)gcc +AS = $(TOOLPREFIX)gas +LD = $(TOOLPREFIX)ld +OBJCOPY = $(TOOLPREFIX)objcopy +OBJDUMP = $(TOOLPREFIX)objdump +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer +CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) +ASFLAGS = -m32 -gdwarf-2 -Wa,-divide +# FreeBSD ld wants ``elf_i386_fbsd'' +LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1) + +# Disable PIE when possible (for Ubuntu 16.10 toolchain) +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) +CFLAGS += -fno-pie -no-pie +endif +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),) +CFLAGS += -fno-pie -nopie +endif + +xv6.img: bootblock bootblock2 + dd if=/dev/zero of=xv6.img count=10000 + dd if=bootblock of=xv6.img conv=notrunc + dd if=bootblock2 of=xv6.img seek=1 conv=notrunc + +bootblock: bootasm.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o + $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock + ./sign.pl bootblock + +bootblock2: bootasm2.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm2.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x9000 -o bootblock2.o bootasm2.o + $(OBJCOPY) -S -O binary -j .text bootblock2.o bootblock2 + + +.PRECIOUS: %.o + +clean: + rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ + *.o *.d *.asm *.sym vectors.S bootblock bootblock2 entryother \ + initcode initcode.out kernel xv6.img fs.img kernelmemfs \ + xv6memfs.img mkfs \ + syscall.h syscalltable.h usys.S + +# run in emulators + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) +ifndef CPUS +CPUS := 1 +endif +QEMUOPTS = -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) + +qemu: xv6.img + $(QEMU) -vga std -serial mon:stdio $(QEMUOPTS) + +qemu-gdb: xv6.img + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -vga std -serial mon:stdio $(QEMUOPTS) -S -gdb tcp::1234 + diff --git a/stage5/bootasm.S b/stage5/bootasm.S new file mode 100644 index 0000000..ebfa7da --- /dev/null +++ b/stage5/bootasm.S @@ -0,0 +1,101 @@ +# When the PC starts, the processor is essentially emulating an 8086 processor, i.e. +# a 16-bit processor. So our initial boot loader code is 16-bit code that will +# eventually switch the processor into 32-bit mode. + +# This code is linked to assume a starting address of 0x7C00 which is where the BIOS +# will load a boot segment. + +.code16 # Assemble for 16-bit mode +.globl start +start: + jmp real_start + +# Write to the console using BIOS. +# +# Input: SI contains the address of the null-terminated string to be displayed + +cons_write: + movb $0x0e, %ah # 0x0e is the INT 10h BIOS call to output the value contained in AL to screen + +cons_write_rpt: + movb (%si), %al # Load the byte at the location contained in the SI register into AL + inc %si # Add 1 to the value in SI + cmp $0, %al # Compare the value in AL with 0 + jz cons_write_done # If it is zero, then we are done + int $0x10 # Output the character in AL to the screen + jmp cons_write_rpt # and continue + +cons_write_done: # Something that is called will never return + ret # until a 'ret' instruction is encountered. Labels do + # not give a program any structure. They just give a + # memory location a name that we can use in our code. + +cons_write_crlf: + movb $0x0e, %ah # Output CR + movb $0x0d, %al + int $0x10 + movb $0x0a, %al # Output LF + int $0x10 + ret + +cons_writeline: + call cons_write + call cons_write_crlf + ret + +real_start: + cli # BIOS enabled interrupts; disable + + # Zero data segment registers DS, ES, and SS. + xorw %ax, %ax # Set %ax to zero + movw %ax, %ds # -> Data Segment + movw %ax, %es # -> Extra Segment + movw %ax, %ss # -> Stack Segment + movw $0, %sp # Set the stack to the top of the segment + + movb %dl, (boot_device) # Boot device number is passed in DL from BIOS. Save it hear since DL might get trashed + + movw $boot_message, %si # Display our boot message + call cons_writeline + + movb $2, %ah # BIOS function 13h, sub-function 2 is read sectors + movb $7, %al # Number of sectors to read = 7 + movw $0x9000, %bx # The 7 sectors will be loaded into memory at ES:BX (0000:9000h) + movb $0, %ch # Use cylinder 0 + movb $0, %dh # Use head 0 + movb (boot_device), %dl # Retrieve the ID of our boot device + movb $2, %cl # Start reading at sector 2 (i.e. one after the boot sector) + int $0x13 + cmpb $7, %al # AL returns the number of sectors read. If this is not 7, report an error + jne read_failed + + movb (0x9000), %al # Check that what we loaded is not empty + cmpb $0, %al + je read_failed + + movb (boot_device), %dl # Pass boot device ID to second stage + movw $0x9000, %ax # Jump to stage 2 + jmp *%ax + +read_failed: # Display error messages + movw $read_failed_msg, %si + call cons_writeline + + mov $cannot_continue, %si + call cons_writeline + +endless_loop: # Loop forever more + jmp endless_loop + +# Program data + +boot_device: + .byte 0 + +boot_message: + .string "Boot Loader V1.0" +read_failed_msg: + .string "Unable to read stage 2 of the boot process" +cannot_continue: + .string "Cannot continue boot process" + diff --git a/stage5/bootasm.d b/stage5/bootasm.d new file mode 100644 index 0000000..59e6ae8 --- /dev/null +++ b/stage5/bootasm.d @@ -0,0 +1 @@ +bootasm.o: bootasm.S diff --git a/stage5/bootasm.o b/stage5/bootasm.o new file mode 100644 index 0000000..67f80b7 Binary files /dev/null and b/stage5/bootasm.o differ diff --git a/stage5/bootasm2.S b/stage5/bootasm2.S new file mode 100644 index 0000000..d1c216d --- /dev/null +++ b/stage5/bootasm2.S @@ -0,0 +1,1138 @@ +# Second stage of the boot loader + +.code16 # Assemble for 16-bit mode +.globl start +start: + jmp real_start + +# Write to the console using BIOS. +# +# Input: SI contains the address of the null-terminated string to be displayed + +cons_write: + movb $0x0e, %ah # 0x0e is the INT 10h BIOS call to output the value contained in AL to screen + +cons_write_rpt: + movb (%si), %al # Load the byte at the location contained in the SI register into AL + inc %si # Add 1 to the value in SI + cmp $0, %al # Compare the value in AL with 0 + jz cons_write_done # If it is zero, then we are done + int $0x10 # Output the character in AL to the screen + jmp cons_write_rpt # and continue + +cons_write_done: # Something that is called will never return + ret # until a 'ret' instruction is encountered. Labels do + # not give a program any structure. They just give a + # memory location a name that we can use in our code. + +cons_write_crlf: + movb $0x0e, %ah # Output CR + movb $0x0d, %al + int $0x10 + movb $0x0a, %al # Output LF + int $0x10 + ret + +cons_writeline: + call cons_write + call cons_write_crlf + ret + +# Added Write Hex and Int functions to help with debugging +HexChars: .ascii "0123456789ABCDEF" + +cons_write_hex: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + + movw $4, %cx + movb $0x0E, %ah + +hexloop: + rol $4, %bx + movw %bx, %si + and $0x000F, %si + movb HexChars(%si), %al + int $0x10 + loop hexloop + + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret + +cons_write_int: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + + movw $IntBuffer + 4, %si + movw %bx, %ax + + cmpw $0, %ax + jge getdigit + + xor %ax, %ax # Added to handle signed numbers, it adds the minus and then neg's the number + movb $0x0E, %ah + movb $0x2D, %al + int $0x10 + + movw %bx, %ax + negw %ax + +getdigit: + xor %dx, %dx + movw $10, %cx + idiv %cx + addb $48, %dl + movb %dl, (%si) + dec %si + cmp $0, %ax + jne getdigit + inc %si + call cons_write + + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret + +IntBuffer: .string " " + +# Draw Line function DrawLine(x0 (4), y0 (6), x1 (8), y1 (10), color (12)) +# Define parameter address positions in stack +#define color 12 +#define y1 10 +#define x1 8 +#define y0 6 +#define x0 4 + +# Define local variable positions in stack +#define deltax -2 +#define deltay -4 +#define sx -6 +#define sy -8 +#define err -10 +#define e2 -12 + +cons_draw_line: + pushw %bp + movw %sp, %bp + subw $12, %sp # Make room for our local variables in the stack + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + + movw $0, err(%bp) # Make sure that err starts at 0 + movw x1(%bp), %cx # Load x1 and y1 into the registers + movw y1(%bp), %dx + sub x0(%bp), %cx # Remove x/y0 from x/y1 to get the delta values + sub y0(%bp), %dx + movw %cx, deltax(%bp) # Store the delta values + movw %dx, deltay(%bp) + +cons_line_check_x: + movw x0(%bp), %cx # Load x0 into register cx so we can manipulate this value to plot each pixel + movw $1, sx(%bp) # Preload the x slope with 1 + cmp x1(%bp), %cx # Check if x0 is less than x1 and we can move to y + jl cons_line_check_y + negw sx(%bp) # If x1 is greater than we need to flip the slope and the x delta values + negw deltax(%bp) # Flipping the deltax here saves us from having to have an abs function because if + # x0 was greater than x1 we know we have a negative delta value and we flip it to pos + +cons_line_check_y: + movw y0(%bp), %dx # Load y0 into register dx so we can manipulate this value to plot each pixel + movw $1, sy(%bp) # Preload the y slope with 1 + cmpw y1(%bp), %dx # Check if y0 is less than y1 and we can start our plotting + jl cons_line_prep_loop + negw sy(%bp) # if y1 is greater than we need to flip the slope y and delta y values + negw deltay(%bp) + +cons_line_prep_loop: + movw deltax(%bp), %ax # Calculate the err variable by subtracting delta y from delta x + sub deltay(%bp), %ax + movw %ax, err(%bp) + +cons_line_loop_start: + pushw color(%bp) + pushw %dx + pushw %cx + call cons_plot_pixel + + cmpw x1(%bp), %cx # Check if x0 and x1 are equal, if not then we are still plotting + jne cons_line_loop_next_point + cmpw y1(%bp), %dx # Check if y0 and y1 are equal, if not then we are still plotting + jne cons_line_loop_next_point + jmp cons_line_loop_end # if both x's and y's are equal then we can end the function + +cons_line_loop_next_point: + movw err(%bp), %ax # Load err into ax so that we can change it + sal %ax # e2 is 2 * err, so we can arithmatic shift left + +cons_line_loop_move_y_point: + movw deltay(%bp), %bx + negw %bx # We need negative deltay to compare + cmpw %bx, %ax # Check if we need to apply the slope value to y + jle cons_line_loop_move_x_point + negw %bx # Change deltay back to normal + subw %bx, err(%bp) # Remove the deltay from the err check + addw sx(%bp), %cx # Add the slope value to the current y value + +cons_line_loop_move_x_point: + movw deltax(%bp), %bx + cmpw %bx, %ax # Check if we need to apply the x slope value + jge cons_line_loop_start + addw %bx, err(%bp) # Add the deltax to the err value + addw sy(%bp), %dx # Add the slope value to the current x value + jmp cons_line_loop_start # Go back to the start of the loop + +cons_line_loop_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $10 # Finish the loop and return to the call address + # we also tell it to free the 10 bytes in the stack for the paramters + # 5 x Word (2 bytes) + +# Function PlotPixel(pixelx (4), pixely (6), pixelColor (8)) +#define pixelcolor 8 +#define pixely 6 +#define pixelx 4 + +# I split the pixel plotting off into its own function so that we can use it for any other function that plots pixels +# and any boundary checks will be applied with the same rules +cons_plot_pixel: + # Setup the stack + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + + xor %ax, %ax # Clear ax and bx for use with the draw function + xor %bx, %bx + movw pixelx(%bp), %cx # Move x and y into their registers + movw pixely(%bp), %dx + + cmpw (screen_width), %cx # Check if the x value has gone past the width of the screen + jg cons_plot_pixel_end # If so we ignore the pixel so that we dont draw into unrelated memory + cmpw $0, %cx # also check if x has gotten less than 0 + jl cons_plot_pixel_end + + cmpw (screen_height), %dx # Do the same checks for the y position, i chose to ignore the pixel rather than + jg cons_plot_pixel_end # end the entire draw because when we come to the circles and polygons we + cmpw $0, %dx # can still partially show the output that falls within the boundaries + jl cons_plot_pixel_end + + # Pixel point = 0xA0000 + (y * 320) + x + movw (screen_width), %ax # Set ax to 320 so that we can multiply this by y + mul %dx # does the (y * 320) part of our math + add %cx, %ax # Add the value of x to register ax + movw %ax, %si # Move the value of ax into the si counter + + movw pixelcolor(%bp), %bx # Load the color into a register + movb %bl, %es:(%si) # Load the lower half of the color (since they should only be from 0 to 255) + # and place it at the given byte in the segment + +cons_plot_pixel_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $6 # Finish the loop and return to the call address + +# Draw Line function DrawFilledRect(rectx (4), recty (6), rectWidth (8), rectHeight (10), rectColor (12)) +# Define parameter address positions in stack +#define rectcolor 12 +#define rectheight 10 +#define rectwidth 8 +#define recty 6 +#define rectx 4 + +cons_draw_filled_rect: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +cons_filled_rect_check_x_dir: + movw rectwidth(%bp), %ax # Check if the user has entered a negative width value and swap the direction to a positive + cmpw $0, %ax + jge cons_filled_rect_check_y_dir + add %ax, rectx(%bp) + negw rectwidth(%bp) + +cons_filled_rect_check_y_dir: + movw rectheight(%bp), %ax # Check if the user has entered a negative height value and swap the direction to a pos + cmpw $0, %ax + jge cons_filled_rect_check_x_zero + add %ax, recty(%bp) + negw rectheight(%bp) + +cons_filled_rect_check_x_zero: + movw rectx(%bp), %ax # Check if the x value is a negative value, set it to 0 and figure out the offset so we + movw $0, %bx # dont write to unwanted memory locations + cmpw %bx, %ax + jge cons_filled_rect_check_x_screenwidth + movw %bx, rectx(%bp) # Set to x 0 + sub %ax, %bx # get the distance from 0 to x + sub %bx, rectwidth(%bp) # take this away from the width + jmp cons_filled_rect_check_width_screenwidth + +cons_filled_rect_check_x_screenwidth: + movw (screen_width), %bx # Check if the x is outside of the view port, if so just end the call + cmpw %bx, %ax # since it will never draw anything + jg cons_filled_rect_loop_end + +cons_filled_rect_check_width_screenwidth: + add rectwidth(%bp), %ax + movw (screen_width), %bx # Check if the width ends up outside of the view port + cmpw %bx, %ax + jle cons_filled_rect_check_y_zero + sub %bx, %ax + sub %ax, rectwidth(%bp) # Remove the excess from the width value so we dont overflow memory + +cons_filled_rect_check_y_zero: + movw recty(%bp), %ax # Check if the y value is a negative value, set it to 0 and figure out the offset so we + movw $0, %bx # dont write to unwanted memory locations + cmpw %bx, %ax + jge cons_filled_rect_check_y_screenheight + movw %bx, recty(%bp) # Set to y 0 + sub %ax, %bx # get the distance from 0 to y + sub %bx, rectheight(%bp) # take this away from the height + jmp cons_filled_rect_check_height_screenheight + +cons_filled_rect_check_y_screenheight: + movw (screen_height), %bx # Check if the y is outside of the view port, if so just end the call + cmpw %bx, %ax # since it will never draw anything + jg cons_filled_rect_loop_end + +cons_filled_rect_check_height_screenheight: + add rectheight(%bp), %ax + movw (screen_height), %bx # Check if the width ends up outside of the view port + cmpw %bx, %ax + jle cons_filled_rect_setup + sub %bx, %ax + sub %ax, rectheight(%bp) # Remove the excess from the width value so we dont overflow memory + +cons_filled_rect_check_empty: + cmpw $0, rectwidth(%bp) # Check if the width or height is now zero, end the function if so + jle cons_filled_rect_loop_end + cmpw $0, rectheight(%bp) + jle cons_filled_rect_loop_end + +cons_filled_rect_setup: + movw recty(%bp), %dx + movw (screen_width), %ax # Set ax to 320 so that we can multiply this by y + mul %dx # does the (y * 320) part of our math + add rectx(%bp), %ax # Add the value of x to register ax + movw %ax, %bx # Load the memory offset address into the bx register + + movw rectheight(%bp), %si # Set the counter to our height which should be the number of lines to draw to + +cons_filled_rect_loop_start: + movw rectcolor(%bp), %ax # Set the color byte for our rep (it uses the AL register for the byte copy) + movw %bx, %di # move the memory location to the di counter + movw rectwidth(%bp), %cx # Set cx to our width so the rep knows when to end + cld # Clear the direction flag so our rep counter inc's + rep stosb # Run the stosb to copy bytes into the data segment til cx is 0 + + movw (screen_width), %cx + add %cx, %bx # Add 320 to our current y value for the next line + + dec %si # Dex the height counter til we hit 0 + jnz cons_filled_rect_loop_start + + +cons_filled_rect_loop_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $10 # Finish the loop and return to the call address + # we also tell it to free the 10 bytes in the stack for the paramters + # 5 x Word (2 bytes) + +# Draw Line function DrawCircle(circlex (4), circley (6), circleRadius (8), circleColor (10)) +# This follows the bresenham circle drawing algorithm so that we can stick to integer values +# Define parameter address positions in stack +#define circlecolor 10 +#define circleradius 8 +#define circley 6 +#define circlex 4 + +# Define local variable positions in stack +#define circled -4 # Decision variable +#define circlexcax -6 +#define circlexcsx -8 +#define circleycay -10 +#define circleycsy -12 +#define circlexcay -14 +#define circlexcsy -16 +#define circleycax -18 +#define circleycsx -20 + +cons_draw_circle: + pushw %bp + movw %sp, %bp + subw $20, %sp # Make room for our local variables in the stack + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +cons_draw_circle_setup: + movw $0, %cx # x starts at 0 + movw circleradius(%bp), %dx # y starts as the radius + movw circleradius(%bp), %bx # d = 3 - (2 * r), we load the radius into a register + sal %bx # and multiply it by 2 + movw $3, %ax # load a 3 into a register to subtract the above from + sub %bx, %ax + movw %ax, circled(%bp) # Move the d variable into the stack + +cons_circle_loop_start: + # We need to plot all 8 points for this step + xor %ax, %ax # Clear a and b registers for use below + xor %bx, %bx + + movw circlex(%bp), %ax # Points xc + x, yc + y + add %cx, %ax + movw circley(%bp), %bx + add %dx, %bx + movw %ax, circlexcax(%bp) + movw %bx, circleycay(%bp) + + movw circlex(%bp), %ax # Points xc - x, yc - y + sub %cx, %ax + movw circley(%bp), %bx + sub %dx, %bx + movw %ax, circlexcsx(%bp) + movw %bx, circleycsy(%bp) + + movw circlex(%bp), %ax # Points xc + y, yc + x + add %dx, %ax + movw circley(%bp), %bx + add %cx, %bx + movw %ax, circlexcay(%bp) + movw %bx, circleycax(%bp) + + movw circlex(%bp), %ax # Points xc - y, yc - x + sub %dx, %ax + movw circley(%bp), %bx + sub %cx, %bx + movw %ax, circlexcsy(%bp) + movw %bx, circleycsx(%bp) + + # Plot the 8 pixels for this turn of the circle + pushw circlecolor(%bp) + pushw circleycay(%bp) + pushw circlexcax(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycay(%bp) + pushw circlexcsx(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycsy(%bp) + pushw circlexcax(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycsy(%bp) + pushw circlexcsx(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycax(%bp) + pushw circlexcay(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycax(%bp) + pushw circlexcsy(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycsx(%bp) + pushw circlexcay(%bp) + call cons_plot_pixel + + pushw circlecolor(%bp) + pushw circleycsx(%bp) + pushw circlexcsy(%bp) + call cons_plot_pixel + + inc %cx # Inc the x value + cmpw $0, circled(%bp) # check if the decision variable is less than 0 + jle cons_circle_skip_y + + dec %dx # If not we decrement the Y value and calculate the new decision value + movw %cx, %ax # Move the x value into ax for mul + movw %dx, %bx # Move the y value into bx since mul destroys the value in dx + movw $4, %si # Move 4 into si because we are out of registers + sub %bx, %ax # d = d + 4 * (x - y) + 10 + imul %si + add $10, %ax + add %ax, circled(%bp) # Add the result to the current D value + movw %bx, %dx # Move y back into the dx register + jmp cons_circle_check_end # jump over the next section to the end check + +cons_circle_skip_y: + movw %cx, %ax # If the decision var was greater than 0 we use another formula for d + movw %dx, %bx # Store y in bx because we are using mul again + movw $4, %si # d = d + 4 * x + 6 + imul %si + add $6, %ax + add %ax, circled(%bp) + movw %bx, %dx # Restore y to the dx register + +cons_circle_check_end: + cmpw %cx, %dx # Check if y is greater than or equal to x + jge cons_circle_loop_start # If so we carry on the loop until it is no longer + +cons_circle_loop_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $8 # Finish the loop and return to the call address + # we also tell it to free the 10 bytes in the stack for the paramters + # 4 x Word (2 bytes) + +# Add Point to Array function AddPoint(int arrx (4), int arry (6)) +# The color comes first because i want the user to push pairs of x/y coordinates +# Define parameter address positions in stack +#define arry 8 +#define arrx 6 +#define arrptr 4 + +arr_add_point: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +arr_add_point_setup: + movw arrx(%bp), %cx # Load X and Y into cx and dx + movw arry(%bp), %dx + movw arrptr(%bp), %si # Load the address of the array into si + + cmpw $0x7fff, (%si) # Check if the user has pointed to an initialized array + jne arr_add_point_end # If not end the function + addw $2, %si # Otherwise move the array to the first data position + +arr_add_point_start: + cmpw $0x7f7f, (%si) # Check if the current + jne arr_add_point_move_addr + movw %cx, (%si) + movw %dx, 2(%si) + jmp arr_add_point_end + +arr_add_point_move_addr: + addw $4, %si + cmpw $0x7fff, (%si) + jne arr_add_point_start + +arr_add_point_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $6 # Finish the loop and return to the call address + # we also tell it to free the 10 bytes in the stack for the paramters + # 2 x Word (2 bytes) + +# Quick memory dump for debugging purposes +#define dumplen 8 +#define dumpstart 6 +#define dumpptr 4 +arr_dump: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +arr_dump_setup: + movw dumpptr(%bp), %si + addw dumpstart(%bp), %si + movw dumplen(%bp), %cx + +arr_dump_loop: + movw (%si), %bx + call cons_write_hex + call cons_write_crlf + add $2, %si + loop arr_dump_loop + +arr_dump_end: + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $6 + +# Clear/Init the Array function ArrayClear(ptr clearptr (4), short clearsize(6)) +# This function fills the array with FF bytes (FF being a value i can use in a loop to end it and not effect the x/y positions) +#define clearsize 6 +#define clearptr 4 +arr_clear: + pushw %bp + movw %sp, %bp + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +arr_clear_setup: + movb $0x7f, %al # Setup the byte to fill the array with + movw clearptr(%bp), %si + movw clearsize(%bp), %cx # Setup the cx counter for + sal $2, %cx # Multiply by 2 for x AND y values and again for the number of actual bytes + + movw $0x7fff, (%si) # Create a full byte at the start we can use in our array functions + addw $2, %si # to make sure a correct address was given + +arr_clear_loop_start: + movb %al, (%si) + inc %si + loop arr_clear_loop_start + +arr_clear_add_end_bytes: + movw $0x7fff, (%si) + +arr_clear_loop_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $4 + +# Draw Polygon function DrawPolygon(ptr polygonarray (2), short polygoncolor(4)...) +# Accepts the address for the array and a color for the lines +# Define parameter address positions in stack +#define polygoncolor 10 +#define polygonoffy 8 +#define polygonoffx 6 +#define polygonarray 4 + +cons_draw_polygon: + pushw %bp + movw %sp, %bp + #subw $20, %sp # Make room for our local variables in the stack + + # Store existing register values to the stack so we can restore later + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + +cons_draw_polygon_setup: + movw polygonarray(%bp), %si + cmpw $0x7fff, (%si) # Check if the user has pointed to an initialized array + jne cons_polygon_loop_end # If not end the function + addw $2, %si # Otherwise move the array to the first data position + +cons_draw_polygon_loop_next: + cmpw $0x7f7f, (%si) + je cons_polygon_loop_end + cmpw $0x7fff, (%si) + je cons_polygon_loop_end + +cons_polygon_loop_map_xy0: + movw (%si), %ax # Move x0 and y0 into ax and bx + movw 2(%si), %bx + cmpw $0x7f7f, 4(%si) + je cons_polygon_loop_map_end + cmpw $0x7fff, 4(%si) + je cons_polygon_loop_map_end + movw 4(%si), %cx + movw 6(%si), %dx + jmp cons_polygon_loop_draw_line + +cons_polygon_loop_map_end: + movw polygonarray(%bp), %di + movw 2(%di), %cx + movw 4(%di), %dx + +cons_polygon_loop_draw_line: + addw polygonoffx(%bp), %ax + addw polygonoffx(%bp), %cx + addw polygonoffy(%bp), %bx + addw polygonoffy(%bp), %dx + + pushw polygoncolor(%bp) + pushw %dx + pushw %cx + pushw %bx + pushw %ax + call cons_draw_line + + addw $4, %si + jmp cons_draw_polygon_loop_next + +cons_polygon_loop_end: + # Return all the original values to each register before we return back + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + movw %bp, %sp + popw %bp + ret $8 # Finish the loop and return to the call address + # we also tell it to free the 10 bytes in the stack for the paramters + # 4 x Word (2 bytes) + +real_start: + movw $0xA000, %bx # Set the start of the video memory location + movw %bx, %es # Move that address into the "extra segment" es register + + movw $boot_message, %si # Display our boot message + call cons_writeline + +draw_start: + # Set the Video mode to VGA 320 x 200 x 256 + movb $0, %ah + movb $0x13, %al + int $0x10 + xor %ax, %ax + +setup_polygon_arrays: + # Create the star polygon array using the static memory location + pushw $10 # Number of points + pushw $polygon_array # Address for array to be created + call arr_clear + + # Map points for the star polygon array + pushw $-6 + pushw $0 + pushw $polygon_array + call arr_add_point + pushw $0 + pushw $2 + pushw $polygon_array + call arr_add_point + pushw $0 + pushw $8 + pushw $polygon_array + call arr_add_point + pushw $4 + pushw $3 + pushw $polygon_array + call arr_add_point + pushw $9 + pushw $5 + pushw $polygon_array + call arr_add_point + pushw $6 + pushw $0 + pushw $polygon_array + call arr_add_point + pushw $9 + pushw $-7 + pushw $polygon_array + call arr_add_point + pushw $4 + pushw $-3 + pushw $polygon_array + call arr_add_point + pushw $0 + pushw $-8 + pushw $polygon_array + call arr_add_point + pushw $0 + pushw $-2 + pushw $polygon_array + call arr_add_point + + # Create the mountains polygon array using a dynamic memory location + pushw $9 # Number of Coord pairs + pushw $0x1000 # Address for array to be created + call arr_clear + + # Map points for the star polygon array + pushw (screen_height) + pushw $0 + pushw $0x1000 + call arr_add_point + pushw $140 + pushw $40 + pushw $0x1000 + call arr_add_point + pushw $160 + pushw $60 + pushw $0x1000 + call arr_add_point + pushw $120 + pushw $100 + pushw $0x1000 + call arr_add_point + pushw (screen_height) + pushw $150 + pushw $0x1000 + call arr_add_point + pushw $180 + pushw $180 + pushw $0x1000 + call arr_add_point + pushw (screen_height) + pushw $210 + pushw $0x1000 + call arr_add_point + pushw $90 + pushw $250 + pushw $0x1000 + call arr_add_point + pushw (screen_height) + pushw $300 + pushw $0x1000 + call arr_add_point + + # Create the mountains polygon array using a dynamic memory location + pushw $10 # Number of Coord pairs + pushw $0x1050 # Address for array to be created + call arr_clear + + # Array for the moon polygon + pushw $0 + pushw $0 + pushw $0x1050 + call arr_add_point + pushw $5 + pushw $8 + pushw $0x1050 + call arr_add_point + pushw $14 + pushw $11 + pushw $0x1050 + call arr_add_point + pushw $23 + pushw $8 + pushw $0x1050 + call arr_add_point + pushw $29 + pushw $0 + pushw $0x1050 + call arr_add_point + pushw $29 + pushw $9 + pushw $0x1050 + call arr_add_point + pushw $23 + pushw $16 + pushw $0x1050 + call arr_add_point + pushw $15 + pushw $19 + pushw $0x1050 + call arr_add_point + pushw $6 + pushw $17 + pushw $0x1050 + call arr_add_point + pushw $0 + pushw $9 + pushw $0x1050 + call arr_add_point + + # Draw the mountain polygon + pushw $6 # Color + pushw $0 # Y Offset + pushw $0 # X Offset + pushw $0x1000 # Address of the Array + call cons_draw_polygon + + # Draw the moon polygon + pushw $7 # Color + pushw $30 # Y Offset + pushw $280 # X Offset + pushw $0x1050 # Address of the Array + call cons_draw_polygon + +draw_stars: + # Draw the star polygons + pushw $14 + pushw $20 + pushw $20 + pushw $polygon_array + call cons_draw_polygon + + pushw $14 + pushw $20 + pushw $80 + pushw $polygon_array + call cons_draw_polygon + + pushw $14 + pushw $25 + pushw $130 + pushw $polygon_array + call cons_draw_polygon + + pushw $14 + pushw $10 + pushw $250 + pushw $polygon_array + call cons_draw_polygon + + pushw $14 + pushw $100 + pushw $200 + pushw $polygon_array + call cons_draw_polygon + + pushw $14 + pushw $60 + pushw $50 + pushw $polygon_array + call cons_draw_polygon + + # Setup the registers to loop through the flag stripes + movw $150, %ax # x Offset + movw $25, %bx # y Offset + movw $6, %cx # Sets of stripes (12 red/white) for the loop to decrement + +draw_flag_loop: + # Draw our filled rectangles for the flag stripes + add $5, %bx # add the height of stripe to the y offset + + pushw $12 # Color + pushw $5 # height + pushw $120 # width + pushw %bx # y + pushw %ax # x + call cons_draw_filled_rect + + add $5, %bx # add the height of stripe to the y offset + pushw $15 # Color + pushw $5 # height + pushw $120 # width + pushw %bx # y + pushw %ax # x + call cons_draw_filled_rect + loop draw_flag_loop + +draw_flag_loop_end: + # Draw the 13th stripe + add $5, %bx + pushw $12 # Color + pushw $5 # height + pushw $120 # width + pushw %bx # y + pushw %ax # x + call cons_draw_filled_rect + + # Draw the blue box that would hold the stars + pushw $1 # Color + pushw $35 # height + pushw $45 # width + pushw $30 # y + pushw $150 # x + call cons_draw_filled_rect + + pushw $6 # Color + pushw $180 # height + pushw $5 # width + pushw $30 # y + pushw $145 # x + call cons_draw_filled_rect + + # Draw some circles to show off that function + pushw $14 # Color + pushw $3 # radius + pushw $27 # y + pushw $147 # x + call cons_draw_circle + + pushw $2 # Color + pushw $25 # radius + pushw $90 # y + pushw $90 # x + call cons_draw_circle + + pushw $15 # Color + pushw $5 # radius + pushw $85 # y + pushw $80 # x + call cons_draw_circle + + pushw $15 # Color + pushw $5 # radius + pushw $85 # y + pushw $100 # x + call cons_draw_circle + + # Plot a line, we add the parameters to the stack in reverse order + pushw $15 # Color + pushw $100 # y1 + pushw $75 # x1 + pushw $105 # y0 + pushw $90 # x0 + call cons_draw_line + + pushw $15 # Color + pushw $100 # y1 + pushw $105 # x1 + pushw $105 # y0 + pushw $90 # x0 + call cons_draw_line + + # Draw the rest of the lines + pushw $2 # Color + pushw $210 # y1 + pushw $90 # x1 + pushw $115 # y0 + pushw $90 # x0 + call cons_draw_line + + pushw $2 # Color + pushw $110 # y1 + pushw $145 # x1 + pushw $130 # y0 + pushw $90 # x0 + call cons_draw_line + + # Line borders + pushw $9 # Color + pushw $10 # y1 + pushw $310 # x1 + pushw $10 # y0 + pushw $10 # x0 + call cons_draw_line + + pushw $10 # Color + pushw $190 # y1 + pushw $310 # x1 + pushw $10 # y0 + pushw $310 # x0 + call cons_draw_line + + pushw $13 # Color + pushw $190 # y1 + pushw $10 # x1 + pushw $190 # y0 + pushw $310 # x0 + call cons_draw_line + + pushw $15 # Color + pushw $10 # y1 + pushw $10 # x1 + pushw $190 # y0 + pushw $10 # x0 + call cons_draw_line + +endless_loop: # Loop forever more + jmp endless_loop + +# Program data +boot_message: + .string "Boot Loader Stage 2 loaded" + +screen_width: + .word 320 +screen_height: + .word 200 + +polygon_array: # Create some memory space for our polygon points array + .fill 40 # Fill array with data to the size of the array \ No newline at end of file diff --git a/stage5/bootasm2.d b/stage5/bootasm2.d new file mode 100644 index 0000000..74df401 --- /dev/null +++ b/stage5/bootasm2.d @@ -0,0 +1 @@ +bootasm2.o: bootasm2.S diff --git a/stage5/bootasm2.o b/stage5/bootasm2.o new file mode 100644 index 0000000..674eaa4 Binary files /dev/null and b/stage5/bootasm2.o differ diff --git a/stage5/bootblock b/stage5/bootblock new file mode 100644 index 0000000..95937cb Binary files /dev/null and b/stage5/bootblock differ diff --git a/stage5/bootblock.o b/stage5/bootblock.o new file mode 100644 index 0000000..9fb59f8 Binary files /dev/null and b/stage5/bootblock.o differ diff --git a/stage5/bootblock2 b/stage5/bootblock2 new file mode 100644 index 0000000..88f99f4 Binary files /dev/null and b/stage5/bootblock2 differ diff --git a/stage5/bootblock2.o b/stage5/bootblock2.o new file mode 100644 index 0000000..f233798 Binary files /dev/null and b/stage5/bootblock2.o differ diff --git a/stage5/sign.pl b/stage5/sign.pl new file mode 100644 index 0000000..d793035 --- /dev/null +++ b/stage5/sign.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/stage5/xv6.img b/stage5/xv6.img new file mode 100644 index 0000000..621fd09 --- /dev/null +++ b/stage5/xv6.img @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:288eb982d8be8d0bae83fd38df2c56107fba15cf66fd1beb675960fa8ab77132 +size 5120000