Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; --------------------------------------------
- ; Title: cli
- ; Version:
- ; --------------------------------------------
- ; CLI
- ; the command line interface is the default method for user to interact with OS
- ; etc stuff blahblahblah
- #segment text
- :cli_name
- dat "Command Prompt", 0
- #segment data
- :cmd_start
- dat 0x0
- :cmd_buffer
- dat 0x0
- #segment code
- ; prints the prompt
- :cli_prompt
- set push, a
- set a, cliprompt_data
- jsr print
- set a, pop
- set pc, pop
- :cli
- ; set up command buffer
- set a, 128 ; 64 word buffer
- jsr malloc
- set [cmd_buffer], c ; store that
- jsr clearscreen
- ;set a, clistart
- ;jsr print
- ;jsr newline
- jsr cli_prompt ; print prompt
- set [cmd_start], [vram_pointer]
- :cli_input_loop
- set j, [vram_pointer]
- jsr getc
- ife c, 0
- set pc, cli_input_loop
- ifl c, 0x20
- set pc, cli_handle_lowspec ; handle low special character
- ifg c, 0x7f
- set pc, cli_handle_hispec ; handle high special character
- :standard_char
- bor c, [defaultcolor]
- set [j], c
- add j, 1
- set [vram_pointer], j
- set pc, cli_input_loop
- ; handle 0x10-0x19
- :cli_handle_lowspec
- ife c, 0x10 ; backspace
- jsr backspace
- ife c, 0x11 ; return
- jsr cli_handle_input ; deal with the input
- ife c, 0x12 ; insert
- add pc, 0 ; placeholder
- ife c, 0x13 ; delete
- add pc, 0 ; placeholder
- set pc, cli_input_loop
- ; handle 0x80+
- :cli_handle_hispec
- set pc, cli_input_loop
- ; handle an inputted command
- :cli_handle_input
- jsr newline ; go to a new line
- set push, a
- set push, b
- set push, c
- set push, z
- set push, i
- set push, j
- set y, 0
- set i, 0 ; argc
- set z, 0 ; *argv
- set a, 32 ; stores the arguments
- jsr malloc
- set z, c
- set [argv_buffer_pointer], z
- set a, [cmd_start] ; start of command
- set b, [cmd_buffer] ; copy into buffer
- set c, [vram_pointer]
- sub c, [cmd_start] ; length of command
- jsr memcpy ; do copy
- set a, b ; set a to buffer
- set push, a ; store a
- set push, b
- set b, a
- add b, 128
- :buf_other_loop
- and [a], 0x7f
- add a, 1
- ifl a, b
- set pc, buf_other_loop
- set b, pop
- set a, pop
- set push, a
- set push, b
- set push, z
- set b, a
- add b, 128
- :buf_clean_loop ; clean out any text effects
- ifn [a], 0x20 ; space
- set pc, buf_clean_loop_skip
- ; deal with space stuff
- set [a], 0 ; clear for nts delimiter
- add i, 1 ; increment argc
- set push, b
- set push, c
- add a, 1
- set [z], a
- add z, 1
- sub a, 1
- set c, pop
- set b, pop
- :buf_clean_loop_skip
- add a, 1
- ifl a, b
- set pc, buf_clean_loop
- set z, pop
- set b, pop
- set a, pop
- ; handle buffer:
- jsr cmd_process ; process the actual command
- jsr cli_prompt ; reprint new prompt
- set b, 128 ; clear 64 words
- set a, [cmd_buffer]
- jsr memclear ; clear buffer
- set c, pop
- set b, pop
- set a, pop
- set j, pop
- set i, pop
- set z, pop
- set [cmd_start], [vram_pointer] ; update cmd_start
- set pc, cli_input_loop
- ; process the given command
- :cmd_process
- ; just check for default commands
- set push, a
- set push, b
- set push, c
- set push, x
- set push, y
- set a, [cmd_buffer] ; first string is buffer
- set push, cmd_process_end ; pseudo-jsr
- set x, [cmd_buffer]
- ifn [x], 0x26 ; not ampersand
- set pc, cmd_process_l2 ; skip that stuff
- ; set new thread stuff
- set y, 1 ; flag new process
- add a, 1 ; skip ampersand
- :cmd_process_l2
- set x, 0
- set b, proclist_cmd
- jsr strcmp ; compare
- ife c, 1 ; match
- set x, proclist ; do that
- set b, disp_time_cmd
- jsr strcmp
- ife c, 1
- set x, disp_time
- set b, testproc_cmd
- jsr strcmp
- ife c, 1
- set x, testproc2
- set b, devicelist_cmd
- jsr strcmp
- ife c, 1
- set x, devicelist
- set b, cli_kill_cmd
- jsr strcmp
- ife c, 1
- set x, cli_kill
- set b, ls_cmd
- jsr strcmp
- ife c, 1
- set x, ls
- set b, test_cmd
- jsr strcmp
- ife c, 1
- set x, testing
- ifn x, 0 ; we are going to do something
- set pc, cmd_execute_base ; execute command
- ; command not understood
- set a, cmd_unrecog
- jsr print
- add sp, 1
- jsr newline
- :cmd_process_end
- set y, pop
- set x, pop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- :cmd_execute_base
- ife y, 1 ; gotta spawn new process
- jsr cmd_execute_new ; new process
- ife y, 0
- jsr cmd_execute_current ; just do it within current process
- set pc, pop
- :cmd_execute_current
- set a, i
- set b, z
- set z, 0
- set i, 0
- set j, 0
- set push, x
- set x, 0
- jsr pop
- set pc, pop
- :cmd_execute_new
- set push, a
- set push, b
- set a, x
- jsr newproc
- set b, cmd_new_proc_name
- jsr setprocname
- jsr startproc
- set b, pop
- set a, pop
- set pc, pop
- ; CLI DATA
- #segment data
- :argv_buffer_pointer
- dat 0x0
- #segment text
- :clistart
- dat "", 0
- :cliprompt_data
- dat "%>", 0
- :cmd_unrecog
- dat "Command not recognized.", 0
- :cmd_new_proc_name
- dat "Console spawned", 0; --------------------------------------------
- ; Title: file
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- ; Sector Header Format: 32 words
- ;----------------------------------
- ; Word | What it is
- ;----------------------------------
- ; 0: Sector data type:
- ; 0: nothing
- ; 1: file
- ; 2: directory
- ;
- ; 1: Flags
- ;
- ; 2: Previous sector (0xFFFF if none)
- ;
- ; 3: Next sector (0xFFFF if none)
- ;
- ; 4:
- #segment data
- ; pointer to sector buffer
- :sector_buffer
- dat 0x0
- ; sector of hard_drive that we are currently at
- :cur_sector
- dat 0x0
- ; pointer to path string that we're currently at
- :cur_path
- dat 0x0
- #segment text
- :root_path
- dat "/", 0
- #segment code
- ; initialize file system stuff
- :fs_init
- set push, a
- set [hd_hwnum], i
- set a, 512 ; sector buffer
- jsr malloc ; allocate it
- set [sector_buffer], c ; store that
- set a, 128
- jsr malloc
- set [cur_path], c
- jsr fs_format
- set [cur_path], root_path ; default path
- set a, pop
- set pc, pop
- ; format the hard drive
- :fs_format
- set push, a
- set push, b
- set push, c
- set push, x
- set push, i
- set i, [hd_hwnum]
- ; check there is media
- set a, 0
- hwi i
- ife b, 0 ; no media
- set pc, fsf_end ; return
- set c, 1438 ; sector for root directory
- set a, fs_format_data ; data to write
- jsr sector_write ; write that data to that sector
- :fsf_end
- set i, pop
- set x, pop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- #segment data
- :fs_format_data
- dat 0x0002, 0x0000, 0xFFFF, 0x059f, 0x0000, 0x0000, 0x0000, 0x0000
- dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- dat 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
- #segment code
- ; write *A to sector C on disk I
- :sector_write
- set push, a
- set push, b
- set push, c
- set push, x
- set b, c
- set x, a
- set c, 1
- set a, 0x11 ; interrupt code
- hwi i ; do the interrupt
- set x, pop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- ; Go to specified relative/absolute path
- :cd
- #segment text
- :ls_cmd
- dat "ls", 0
- #segment code
- ; List contents of current directory
- :ls
- ; first, print current path to screen
- set push, a
- set a, [cur_path]
- jsr print ; print current path string
- jsr newline ; newline of course
- ; now, print out contents of current directory
- set a, pop
- set pc, pop; --------------------------------------------
- ; Title: graphics
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- ; LEM1802 Driver
- ; Monitor display driver
- #segment data
- ; default print color
- :defaultcolor
- dat 0xf000
- #segment code
- ; print_hex
- ; prints the hex value in A, digit by digit, to screen
- :print_hex
- set push, a
- set push, b
- set push, c
- set b, a
- and b, 0xf000 ; highest digit
- shr b, 12
- jsr print_hex_sub
- set b, a
- and b, 0x0f00
- shr b, 8
- jsr print_hex_sub
- set b, a
- and b, 0x00f0
- shr b, 4
- jsr print_hex_sub
- set b, a
- and b, 0x000f
- jsr print_hex_sub
- set c, pop
- set b, pop
- set a, pop
- set pc, pop ; return
- :print_hex_sub
- ifg b, 0x9 ; alphabetical digit
- add b, 0x37 ; bring to ascii
- ifl b, 0xa ; numerical digit
- add b, 0x30 ; bring to ascii
- bor b, [defaultcolor]
- set c, [vram_pointer]
- set [c], b
- add c, 1
- set [vram_pointer], c
- ifg [vram_pointer], [vram_end]
- jsr shiftlines
- set pc, pop
- ; print
- ; This function prints nt string pointed by A to the monitor
- :print
- set push, a
- set push, b
- set push, c
- set push, x
- :print_loop
- set x, [a] ; character to print
- jsr putc
- :print_loop_end
- add a, 1
- ifn [a], 0 ; not at end!
- set pc, print_loop ; keep going
- :print_end
- set x, pop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop ; return
- ; handle a carriage return
- :carriage_ret
- and [vram_pointer], 0xffe0
- set pc, pop
- ; prints ascii character in a
- :putc
- ; check for overflow
- set b, [vram_pointer]
- ifl b, [vram_end]
- set pc, putc_cont ; good to go
- jsr shiftlines
- :putc_cont
- ife x, 10 ; newline
- set pc, newline
- ife x, 8 ; backspace - this probably shouldn't show up but you never know
- set pc, backspace
- ife x, 13
- set pc, carriage_ret
- bor x, [defaultcolor] ; add in color
- set b, [vram_pointer] ; get vram pointer
- set [b], x ; print
- add b, 1 ; increment
- set [vram_pointer], b
- set pc, pop
- ; print something out asynchronously from command line
- :async_print
- jsr newline ; force newline
- jsr print ; print the thing
- jsr newline
- set pc, pop
- ; inserts a space
- :space
- add [vram_pointer], 1
- set pc, pop
- ; shift the lines of everything down
- :shiftlines
- set push, i
- set push, j
- set push, z
- set z, 0
- set i, [vram_loc] ; i is beginning of vram
- set j, [vram_end]
- sub j, 32 ; j is end of 11th line (because 12th will be empty)
- :sl_loop
- set [i], [i+32] ; set everything to the respective value a line below
- add i, 1 ; increment
- ifl i, j ; if not to end
- set pc, sl_loop ; go again
- add j, 32 ; bring j to end
- :sl_loop2
- set [i], z ; clear i
- add i, 1 ; increment
- ifl i, j ; not at end...
- set pc, sl_loop2 ; ...keep going
- set [vram_pointer], 0x1360
- set z, pop
- set j, pop
- set i, pop
- set pc, pop ; return
- :addcolor
- set push, a
- set push, b
- set push, c
- jsr strlen
- set b, [defaultcolor]
- add c, a
- :addcolor_loop
- bor [a], b ; add in the color to this word
- add a, 1
- ifl a, c
- set pc, addcolor_loop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- :clearscreen
- set push, a
- set push, b
- set push, c
- set a, [vram_loc]
- set b, [vram_end]
- :csloop
- set [a], 0
- add a, 1
- ifl a, b
- set pc, csloop
- ; reset vram pointer
- set [vram_pointer], [vram_loc]
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- :newline
- set push, x
- set x, [vram_pointer]
- sub x, [vram_loc]
- and x, 0xffe0
- add x, 32
- add x, [vram_loc]
- set [vram_pointer], x
- ; check for overflow
- ifg [vram_pointer], [vram_end]
- jsr shiftlines ; if so shift lines up
- set x, pop
- set pc, pop ; return
- :backspace
- set push, i
- set i, [vram_pointer]
- ifg i, [vram_loc] ; not out of vram
- ifg i, [cmd_start] ; nor out of current command
- sub i, 1 ; go back one
- set [i], 0 ; clear old
- set [vram_pointer], i ; re-store
- set i, pop
- set pc, pop ; return; --------------------------------------------
- ; Title: hardware
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- ; HARDWARE FUNCTIONS
- ; Functions designed to allow the OS to interact with hardware
- ; hardware_init
- ; looks through all connected hardware devices, attempts to recognize each one,
- ; and initializes it as appropriate
- :hardware_init
- set push, a
- set push, b
- set push, c
- set push, x
- set push, y
- set push, z
- set push, i
- hwn z ; find number of hardware devices
- ; get ready for loop
- set i, 0 ; counter
- ; loop for hardware init
- :hi_loop
- hwq i ; get info on i
- ; find lem1802
- ife b, 0x7349
- ife a, 0xf615
- jsr lem1802_init ; initialize found monitor
- ; find clock
- ife b, 0x12d0
- ife a, 0xb402
- jsr clock_init ; initialize found clock
- ; find keyboard
- ife b, 0x30cf
- ife a, 0x7406
- jsr keyboard_init ; initialize found keyboard
- ife b, 0x4cae
- ife a, 0x74fa
- jsr fs_init
- add i, 1
- ; if we haven't found every hardware device, keep going
- ifl i, z ; still less than z (total num)
- set pc, hi_loop
- ; end of hi_loop
- set i, pop ; start restoring registers
- set z, pop
- set y, pop
- set x, pop
- set c, pop
- set b, pop
- set a, pop
- set pc, pop ; return to calling function
- ; lem1802_init
- ; This function initializes hardware device I as a lem1802 monitor.
- :lem1802_init
- ifn [lem_hwnum], 0 ; monitor already initializes
- set pc, pop ; go back, only one monitor (currently)
- set [lem_hwnum], i ; store the hwnum of the monitor
- set push, a
- set push, b
- set push, c
- set a, 0x0 ; interrupt num for vram-set
- set b, [vram_loc] ; location of VRAM
- hwi i ; send vram-set interrupt
- ; if desired, add additional configuration interrupts for monitor here
- ; calculate vram end
- set b, [vram_loc]
- add b, 384
- set [vram_end], b
- set [vram_pointer], [vram_loc]
- set c, pop
- set b, pop
- set a, pop
- set pc, pop ; return to calling function
- ; clock_init
- ; This function initializes a clock at hwnum I
- :clock_init
- set push, a
- set push, b
- set push, c
- set [clock_hwnum], i
- set a, 0 ; set clock freq interrupt num
- set b, [clock_freq] ; frequency of clock data
- hwi i ; do the interrupt
- set a, 2 ; set interrupt code interupt num
- set b, 0x01 ; code of clock
- hwi i ; do the interrupt again
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- ; keyboard_init
- ; Initializes keyboard at hwnum i
- :keyboard_init
- set push, a
- set push, b
- set push, c
- set [kb_hwnum], i
- ; do that interrupt
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- ; disp_time
- ; This function prints the current system time to the screen
- :disp_time
- set push, a
- set a, disp_time_data
- jsr print
- set a, [sys_time+1]
- jsr print_hex
- set a, [sys_time]
- jsr print_hex
- jsr newline
- set a, pop
- set pc, pop
- #segment text
- :disp_time_data
- dat "Current system time: ", 0
- :disp_time_cmd
- dat "time", 0
- #segment code
- ; list all devices and print formatted list
- :devicelist
- hwn i
- sub i, 1
- :dl_loop
- hwq i
- set x, device_unrecog
- ; find lem1802
- ife b, 0x7349
- ife a, 0xf615
- set x, monitor_text
- ; find clock
- ife b, 0x12d0
- ife a, 0xb402
- set x, clock_text
- ; find keyboard
- ife b, 0x30cf
- ife a, 0x7406
- set x, kb_text
- set a, x
- jsr print ; print text
- jsr newline ; advance line
- sub i, 1
- ifn i, 0xffff
- set pc, dl_loop
- set pc, pop
- #segment text
- :monitor_text
- dat "LEM1802 Monitor", 0
- :clock_text
- dat "Generic Clock", 0
- :kb_text
- dat "Generic Keyboard", 0
- :device_unrecog
- dat "Unrecognized Device", 0
- :devicelist_cmd
- dat "devicelist", 0; --------------------------------------------
- ; Title: kernel
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- ; Operating system for DCPU16
- #segment boot
- ; Go to beginning of OS:
- set pc, boot
- ; OS DATA
- #segment data
- ; location of kernel's stack
- :kernel_sp
- dat 0x1200 ; provides 512-word stack for kernel
- ; clock interrupt frequency
- :clock_freq
- dat 1 ; 10 hertz
- ; system time
- :sys_time
- dat 0, 0 ; 32-bit time value, represents clock ticks since startup
- ; hwnum of the monitor the OS is using
- :lem_hwnum
- dat 0x0
- ; hwnum of the active keyboard
- :kb_hwnum
- dat 0x0
- ; hwnum of active clock
- :clock_hwnum
- dat 0x0
- :hd_hwnum
- dat 0x0
- ; process data
- ; pid of the current process
- :cur_proc
- dat 0x0
- :proc_list_start
- dat 0x1b00 ; start of data of process pointer list
- :proc_maxnum
- dat 0x10 ; max number of processes (16)
- ; malloc data
- :malloc_reg
- dat 0x1400
- :malloc_reg_end
- dat 0x0 ; calculated
- :malloc_start
- dat 0x2000
- :malloc_length
- dat 0xe000
- :malloc_end
- dat 0x0 ; calculated
- :malloc_reg_pointer
- dat 0x0
- ; video data
- :vram_loc
- dat 0x1200
- :vram_pointer
- dat 0x0 ; calculated
- :vram_end
- dat 0x0 ; calculated
- ; AUTO CLOCKSPEED FLAG
- :autoclockflag
- dat 0x0 ; 1 for yes, 0 for no
- ; Kernel Boot Functions
- #segment code
- ; This is what happens when the dcpu is turned on originally.
- :boot
- set sp, [kernel_sp] ; move sp to the proper place
- set [cur_proc], 0x1 ; this is the "pid" assigned to the launch process (for pid-dependent function purposes)
- jsr malloc_init ; initialize dynamically allocated memory
- ; start test process for testing
- ;jsr testproc2_start
- jsr hardware_init ; recognize and initialize hardware
- jsr fs_init
- jsr bootscreen
- set a, [autoclockflag]
- ife a, 1
- jsr autoclock
- ife a, 0
- jsr standardclock
- ; Now, we need to set up the CLI process to get it all rolling
- set a, cli ; starter PC of newproc
- jsr newproc ; get the process for it going
- set b, cli_name ; name of process
- jsr setprocname ; set that
- set b, 3 ; desired priority
- jsr setprocpriority ; set that too
- jsr startproc ; get process schedulable
- ; start up our processcleaner
- jsr processcleaner
- ; start up interrupt handler, which will get actual OS running and end boot process
- ias inthand
- ; after the boot process, idle until scheduler takes over
- :idle
- iaq 0 ; make sure interrupts are on (for scheduler to resume control)
- :idleloop
- set pc, idleloop ; endless loop
- ; OS has crashed for some reason
- :crash
- ias 0 ; no interrupts
- sub pc, 1 ; hang
- ; autosset clock settings
- :autoclock
- ; test cpu clock speed to set scheduling speed
- set b, 1
- set i, [clock_hwnum]
- set a, 0
- hwi i
- set i, 0
- :speed_test_loop
- add i, 1
- ifl i, 0xffff
- set pc, speed_test_loop
- set i, [clock_hwnum]
- set a, 1
- hwi i
- div c, 40
- add c, 1
- set b, c
- set a, 0
- hwi i
- set pc, pop
- #segment text
- :autoclock_cmd
- dat "autoclock", 0
- #segment code
- :standardclock
- set i, [clock_hwnum]
- set a, 0
- set b, 6
- hwi i
- set pc, pop
- ; TEST FUNCTIONS
- :testproc2_start
- set push, a
- set a, testproc2
- jsr newproc
- set b, testprocname
- jsr setprocname
- jsr startproc
- set a, pop
- set pc, pop
- :testproc2
- set a, 0
- set b, 0
- set c, 0
- :loopy
- add a, 1
- add b, ex
- add c, ex
- set pc, loopy
- #segment text
- :testprocname
- dat "Test process", 0
- :testproc_cmd
- dat "testproc", 0
- ; OS API FUNCTIONS
- ; Designed to be used by other programs and the OS alike
- #segment code
- ; STANDARD FUNCTIONS
- ; memcpy
- ; copies C words from A to B
- :memcpy
- set push, i
- set push, j
- set push, c
- set i, a
- set j, b
- add c, i
- :memcpy_loop
- sti [j], [i]
- ifl i, c
- set pc, memcpy_loop
- set c, pop
- set j, pop
- set i, pop
- set pc, pop ; return
- ; memclear
- ; clears b words of memory starting at A
- :memclear
- set push, i
- set push, j
- set i, a ; beginning
- set j, a
- add j, b ; end
- :memclear_loop
- set [i], 0 ; clear
- add i, 1 ; increment
- ifl i, j ; not at end
- set pc, memclear_loop ; keep going
- set j, pop
- set i, pop
- set pc, pop
- #segment code
- ; INTERRUPT HANDLER
- ; This is the OS interrupt handler. It handles all interrupts that can be caused.
- ; Interrupt Codes
- ; 0x01 - clock interrupt
- ; 0x02 - non-clock scheduling interrupt
- ; 0x03 - keyboard interrupt
- ; 0x20 - malloc
- ; Interrupt Handler data
- :inthand
- iaq 1 ; queue interrupts
- set [extempstore], ex ; quickly store this
- ; handle the interrupts
- set push, intreturn ; pseudo-jsr
- ife a, 0x01 ; clock interrupt
- set pc, clock_interrupt
- ife a, 0x02
- set pc, ci_cont ; schedule without incrementing clock
- ife a, 0x20 ; malloc interrupt
- set pc, malloc_interrupt
- :intreturn
- ; end interrupt handler for non-process-switching interrupts and go back to proper code
- rfi 1
- ; specific interrupt handlers
- :keyboard_interrupt
- set pc, pop ; return
- :clock_interrupt
- ; increase system time
- add [sys_time], 1 ; 32 bit increment
- add [sys_time+1], ex
- :ci_cont
- ; get all the things as they should be
- add sp, 1 ; undo inthand's push
- set pc, schedule ; go schedule next process
- :malloc_interrupt
- ; do a malloc
- set a, pop ; get a off stack
- iaq 0 ; unqueue interrupts
- set pc, malloc ; go do that
- ; PROCESS FUNCTIONS
- ; functions to handle the OS processes stuff
- ; process stati:
- ; 1 - run as normal
- ; 2 - in creation
- ; 3 - sleeping
- ; 4 - being killed
- ; 5 - indefinitely suspended
- #segment data
- ; schedule
- ; Decide what process to run next, then set up and give that process control of dcpu
- :stempstore
- dat 0
- :extempstore
- dat 0
- #segment code
- :schedule
- ; first things first: store data of currently running process
- set [stempstore], b
- set a, [cur_proc]
- ifl a, 2 ; not legit process
- set pc, sched_start2
- add a, [proc_list_start]
- set b, [a] ; data of current process
- set [b+7], pop ; pop A from stack
- set [b+4], pop ; pop PC from stack
- set [b+8], [stempstore] ; get b from temp
- set [b+9], c ; store the rest of registers
- set [b+10], x
- set [b+11], y
- set [b+12], z
- set [b+13], i
- set [b+14], j
- set [b+5], sp ; store sp
- :sched_start2
- set [cur_proc], 0x1 ; kernel process
- set sp, [kernel_sp]
- set i, [proc_list_start]
- add i, 2 ; bring i to start of processes
- set z, [proc_list_start]
- add z, [proc_maxnum]
- set a, 0 ; maxval
- set b, 0 ; maxpid
- :sched_loop
- set c, [i] ; proc data for i
- set x, [c] ; shortcut
- ife c, 0 ; nothing to do here...
- set pc, sched_loop_end
- ife x, 3 ; process sleeping
- set pc, sched_sleep_handle ; handle that stuff
- ifn x, 1 ; process not supposed to be running
- set pc, sched_loop_end
- set x, [sys_time]
- set y, [sys_time+1]
- sub x, [c+2] ; lower 16 bit difference
- add y, ex ; factor in overflow
- sub y, [c+3] ; upper 16 bit difference
- add x, [c+1] ; increase time based on priority
- add y, ex ; overflow
- ifg y, 0 ; something present in y
- set x, 0xffff ; set x to max possible
- ifl x, a ; didn't set new max
- set pc, sched_loop_end
- ; did set new max
- set a, x ; change vals
- set b, i
- :sched_loop_end
- add i, 1 ; increment
- ifl i, z ; not at end
- set pc, sched_loop
- ; now we know what process to launch, we have to launch it
- set a, b ; move b to a
- ife a, 0 ; no process wants to be fun
- set pc, idle ; idle and wait
- set b, [a]
- set [b+2], [sys_time]
- set [b+3], [sys_time+1]
- sub a, [proc_list_start] ; a is pid of process to launch
- ; automatically continue to launch...
- iaq 0 ; unqueue
- :launch ; can also be started not from scheduler
- ifl a, 2 ; not valid process
- set pc, idle ; go idle and wait
- iaq 1 ; queue interrupts
- set [cur_proc], a ; set up current process
- add a, [proc_list_start] ; bring a to entry in list
- set a, [a] ; bring a to proc data
- set b, [a+8] ; start setting registers
- set c, [a+9]
- set x, [a+10]
- set y, [a+11]
- set z, [a+12]
- set i, [a+13]
- set j, [a+14]
- set ex, [a+6]
- set sp, [a+5]
- set push, [a+4] ; push pc
- set a, [a+7]
- iaq 0 ; unqueue interrupts
- set pc, pop ; process launched
- ; handle sleeping process
- :sched_sleep_handle
- set x, [sys_time]
- set y, [sys_time+1]
- ifl y, [c+16] ; upper 16 bits less
- set pc, sched_loop_end
- ifl x, [c+15] ; lower 16 bits less
- set pc, sched_loop_end
- ; stop sleeping!
- set [c], 1 ; set status 1 - run normally
- set pc, sched_loop_end ; go back into scheduling loop
- :cli_kill
- ifl a, 1 ; missing argument
- set pc, cli_kill_fail
- set a, [b]
- set i, [a]
- sub i, 0x30 ; ascii number to
- add a, 1
- set j, [a]
- ife j, 0 ; single number given in arguments
- set pc, cli_kill_1d
- ; 2 digit
- sub j, 0x30
- mul i, 10
- add j, i ; j is pid
- set a, j
- jsr killproc
- set pc, pop
- :cli_kill_1d
- set a, i
- jsr killproc
- set pc, pop
- :cli_kill_fail
- set pc, pop
- #segment text
- :cli_kill_cmd
- dat "kill", 0
- ; processcleaner
- ; This process goes and cleans up after dead processes.
- #segment text
- :procclean_name
- dat "Process Cleaner", 0
- #segment code
- :processcleaner
- ; start up processcleaner process
- set push, a
- set a, processcleaner_outer
- jsr newproc
- set b, procclean_name
- jsr setprocname
- jsr startproc
- set a, pop
- set pc, pop ; return
- :processcleaner_outer ; outer loops
- set i, [proc_list_start]
- set j, i
- add i, 1
- add j, [proc_maxnum]
- :pcloop
- add i, 1
- set b, [i]
- ife [b], 4
- set pc, pc_clean
- :pcloop_return
- ifl i, j ; not and end
- set pc, pcloop
- :pc_break
- set a, 10 ; 10 cycle sleep
- jsr sleepproc ; go sleep
- set pc, processcleaner_outer
- :pc_clean
- set [i], 0 ; remove process listing
- set a, i
- sub a, [proc_list_start] ; get pid
- jsr free_pid ; remove memory
- set pc, pcloop_return
- ; Lists data on all active processes
- :proclist
- set push, a
- set push, c
- set push, x
- set push, y
- set push, i
- set push, j
- set a, proclist_header
- jsr print
- jsr newline
- set a, 32
- jsr malloc ; allocate some stuff
- set i, [proc_list_start]
- set j, i
- add i, 2
- add j, [proc_maxnum] ; j to end
- :proclist_loop
- set a, [i]
- ife a, 0 ; no process in this slot
- set pc, proclist_loop_end
- ife [a], 4 ; process to be killed
- set pc, proclist_loop_end
- ; there is a process here
- set x, i
- sub x, [proc_list_start] ; x is pid
- set y, x ; y too
- div x, 10 ; upper digit base 10
- mod y, 10 ; lower digit base 10
- add x, 48 ; bring to ascii
- add y, 48
- set [c], x ; put into string in malloc'ed area
- set [c+1], y
- set push, a
- set a, c
- jsr print
- set a, pop
- jsr space
- jsr space
- set a, [a+18] ; pointer to process name
- jsr print ; print name
- jsr newline ; get newline
- :proclist_loop_end
- add i, 1
- ifl i, j
- set pc, proclist_loop
- set a, 32
- jsr free ; free what we malloced
- set j, pop
- set i, pop
- set y, pop
- set x, pop
- set c, pop
- set a, pop
- set pc, pop
- #segment text
- :proclist_header
- dat "PID Process Name", 0
- :proclist_cmd
- dat "proclist", 0
- #segment code
- :getc
- set push, a
- set push, b
- set push, j
- set j, [kb_hwnum]
- set a, 1
- :getc_loop
- hwi j
- ife c, 0 ; nothing yet
- set pc, getc_loop
- set j, pop
- set b, pop
- set a, pop
- set pc, pop
- #segment text
- ; Screen for OS to display while booting
- :bootsdat
- dat " Booting up OS!", 10
- dat " Please wait...", 0
- #segment code
- :bootscreen
- set push, a
- jsr newline
- jsr newline
- jsr newline
- set a, bootsdat
- jsr print
- set a, pop
- set pc, pop; --------------------------------------------
- ; Title: malloc
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- ; MALLOC
- ; allocates A words of RAM, returning in C the address of the RAM
- :malloc
- set push, a
- set push, b
- set push, i
- set push, j
- ife [cur_proc], 0
- set [cur_proc], 0xffff
- ; find in registry enough spaces for what we want
- ; convert A from words to blocks
- jsr calc_block_num
- set i, [malloc_reg]
- ;set i, [malloc_reg_pointer]
- :malloc_find_loop
- set j, 0 ; number of found blocks
- :malloc_inner_loop
- ifn [i], 0 ; current block unused
- set pc, mil_fail ; found a used block, restart looking
- add j, 1 ; increment found blocks count
- add i, 1 ; increment search counter
- ife j, a ; we've found enough blocks
- set pc, malloc_success ; finished alloc
- ife i, malloc_reg_end ; finished search, malloc failed
- set pc, malloc_fail
- set pc, malloc_inner_loop
- :malloc_success
- sub i, j ; set i to beginning of found area in registry
- ; indicate allocation
- set push, i
- set j, i
- add j, a
- :m_allocate_loop
- set [i], [cur_proc]
- add i, 1
- ifl i, j
- set pc, m_allocate_loop
- set [malloc_reg_pointer], i
- set i, pop
- sub i, [malloc_reg] ; set i to number of blocks after start
- mul i, 32 ; set i to offset of data start
- add i, [malloc_start] ; set i to actual location
- set c, i ; move that into c
- :malloc_break
- set j, pop
- set i, pop
- set b, pop
- set a, pop
- set pc, pop
- ; failure of malloc inner loop, just increment and restart
- :mil_fail
- set j, 0 ; reset found blocks
- add i, 1 ; go to next block for search
- set pc, malloc_inner_loop
- :malloc_fail
- ; this is bad - not enough memory for what we want
- ; have to terminate current process
- set pc, crash
- ; FREE
- ; frees A words starting at address given in C
- :free
- set push, a
- set push, b
- set push, c
- jsr calc_block_num ; switch a from words to blocks
- sub c, [malloc_start]
- div c, 32
- add c, [malloc_reg] ; c is place in malloc reg
- set b, c
- add b, a
- :free_loop
- set [c], 0 ; clear
- add c, 1 ; increment
- ifl c, b ; not at end
- set pc, free_loop ; continue
- set c, pop
- set b, pop
- set a, pop
- set pc, pop
- ; free_pid
- ; frees all blocks for a certain pid
- :free_pid
- set push, i
- set push, j
- set i, [malloc_reg]
- set j, [malloc_reg_end]
- :freepid_loop
- ife [i], a ; remove this allocation.
- set [i], 0 ; do that
- add i, 1 ; increment
- ifl i, j ; not at end yet
- set pc, freepid_loop ; keep going
- set j, pop
- set i, pop
- set pc, pop ; return
- :calc_block_num
- set push, x
- set x, a
- mod x, 32
- div a, 32
- ifn x, 0
- add a, 1
- set x, pop
- set pc, pop ; return
- ; malloc_init
- ; Initializes dynamic memory stuff
- :malloc_init
- set push, a
- set push, b
- set push, c
- set a, [malloc_reg]
- set b, [malloc_length]
- div b, 32
- add b, a
- set [malloc_reg_end], b
- set a, [malloc_start]
- add a, [malloc_length]
- set [malloc_end], a
- set [malloc_reg_pointer], [malloc_reg]
- set c, pop
- set b, pop
- set a, pop
- set pc, pop ; return
- ; --------------------------------------------
- ; Title: proc
- ; Date: 7/13/2012
- ; Version:
- ; --------------------------------------------
- #segment code
- ; newproc
- ; Creates a process skeleton and returns a pointer in A
- ; Skeleton does not contain most critical data required to start it
- :newproc
- iaq 1 ; queue interrupts during this
- set push, a
- set push, b
- set push, c
- set push, [cur_proc]
- set [cur_proc], 0x1 ; proc data stored under kernel pid
- jsr newpid ; get a new pid in a
- set push, a ; push pid
- set a, 32 ; length of proc data
- jsr malloc ; allocate proc data
- set a, pop
- set [a], c ; set pointer to new process data location
- set [c], 2 ; status of 2 - in creation
- set [c+1], 1 ; priority - 1 (standard)
- set b, c
- add b, 32 ; b is end
- set push, c
- :newprocloop
- add c, 1 ; increment
- set [c], 0 ; clear a
- ifl c, b ; not at end
- set pc, newprocloop ; keep going
- set [cur_proc], a ; new process's pid
- sub [cur_proc], [proc_list_start]
- set push, a
- set a, 1024 ; size of new process's stack
- jsr malloc ; allocate its stack
- set b, c ; temp
- set a, pop
- add b, 1023 ; bring to start of stack - 1
- set c, pop ; restore
- set [c+5], b ; set SP
- set [b], kill_me ; last address on stack, if it set pc, pops one time too many
- set [c+2], [sys_time] ; time of creation
- set [c+3], [sys_time + 1] ; cont
- set a, [cur_proc]
- set [cur_proc], pop
- set c, pop
- set b, pop
- set push, a
- add a, [proc_list_start]
- set a, [a]
- set [a+4], pick 1 ; pc
- set a, pop
- add sp, 1
- iaq 0 ; unqueue interrupts
- set pc, pop ; return
- ; newpid
- ; Finds a new, empty process id and returns it.
- :newpid
- set push, i
- set push, j
- set i, [proc_list_start]
- add i, 2
- set j, i
- add j, [proc_maxnum]
- sub j, 2
- :np_loop
- ife [i], 0
- set pc, np_found
- add i, 1
- ife i, j
- set pc, np_fail
- set pc, np_loop
- :np_fail
- :np_found
- set a, i
- set j, pop
- set i, pop
- set pc, pop ; return
- ; startproc
- ; This process takes a pid of a process "in creation," and sets it to
- ; actually start, aka eligiblizes it for scheduling
- :startproc
- set push, a
- ifl a, 2
- ifg a, 16
- set pc, pop ; invalid pid
- add a, [proc_list_start] ; get to proc list entry
- set a, [a] ; get pointer to proc data
- ifn [a], 2 ; process NOT in creation
- set pc, pop ; return without doing anything
- set [a], 1 ; set status 1: run normally
- set a, pop
- set pc, pop ; return
- ; killproc
- ; "kills" the process with pid A
- ; This doesn't actually kill it, but rather mark it for death,
- ; to be cleaned up later.
- :killproc
- set push, a
- add a, [proc_list_start]
- ifl a, 2
- ifg a, 16
- set pc, pop ; invalid pid
- set a, [a]
- set [a], 4 ; set status 4: kill process
- set a, pop
- set pc, pop ; return
- ; kill_me
- ; This function causes the process that calls it to die.
- :kill_me
- set a, [cur_proc]
- jsr killproc ; flag process to die
- int 0x02 ; auto-reschedule
- set pc, idle
- ; set the name of a pid A to *B
- :setprocname
- ifl a, 2
- ifg a, 0x10
- set pc, pop ; do nothing
- set push, a
- add a, [proc_list_start]
- set a, [a]
- set [a+18], b ; set that pointer there
- set a, pop
- set pc, pop
- :setprocpriority
- ifl a, 2
- ifg a, 0x10
- set pc, pop ; do nothing
- set push, a
- add a, [proc_list_start]
- set a, [a]
- set [a+1], b ; set that pointer there
- set a, pop
- set pc, pop
- #segment code
- ; sleepproc
- ; causes caller to sleep for A cycles
- :sleepproc
- set push, z
- set push, y
- set push, x
- set push, a
- set a, [cur_proc] ; get current process
- add a, [proc_list_start]
- set a, [a]
- set y, [sys_time+1]
- set x, [sys_time]
- set z, a
- set a, pop
- add x, a
- add y, ex
- set a, z
- set [a+15], x
- set [a+16], y
- set [a], 3 ; set status 3 - sleeping
- set x, pop
- set y, pop
- set z, pop
- int 0x02 ; reschedule
- set pc, pop ; wait
- ; --------------------------------------------
- ; Title: string
- ; Date: 9/23/2012
- ; Version:
- ; --------------------------------------------
- ; strcpy
- ; copies null-terminated string from A to B
- :strcpy
- set push, c
- jsr strlen ; get length in C
- jsr memcpy ; do the copy
- set c, pop
- set pc, pop ; return
- ; strlen
- ; gets the length of a null-terminated string at A into C
- :strlen
- set push, i
- set i, a
- :strlen_loop
- ife [i], 0 ; found end
- set pc, strlen_end ; break loop
- add i, 1 ; increment
- set pc, strlen_loop ; restart loop
- :strlen_end
- sub i, a ; set i to length
- set c, i ; set c to length
- set i, pop
- set pc, pop ; return
- ; Compares string *a and *b, c = 0 for mismatch, c = 1 for match
- :strcmp
- set push, a
- set push, i
- set push, j
- set i, a
- set j, b
- :strcmp_inner_loop
- set a, [i]
- set b, [j]
- ifn a, b ; difference found!
- set pc, strcmp_fail ; go fail
- ife a, 0 ; done
- set pc, strcmp_succeed ; yay!
- add i, 1 ; increment
- add j, 1
- set pc, strcmp_inner_loop ; keep going
- :strcmp_end
- set j, pop
- set i, pop
- set a, pop
- set pc, pop ; return
- :strcmp_fail
- set c, 0 ; for fail
- set pc, strcmp_end ; end function
- :strcmp_succeed ; for success
- set c, 1 ; for succeed
- set pc, strcmp_end ; end function; --------------------------------------------
- ; Title: tests
- ; Date: 9/28/2012
- ; Version:
- ; --------------------------------------------
- ; a test process for the operating system
- #segment text
- :test_text
- dat "testing1234567899", 8, "0", 10, 0
- :test_cmd
- dat "test", 0
- #segment code
- :testing
- ; test printing
- set i, 0
- set a, test_text
- :test_text_loop
- jsr print
- add i, 1
- ifl i, 20
- set pc, test_text_loop
- ; test printing hexes
- set a, 0x1000
- :test_hex_loop
- jsr print_hex
- jsr newline
- add a, 0x20
- ifl a, 0x2000
- set pc, test_hex_loop
- ; test process creation
- set i, 0
- set x, testproc2
- :test_proc_loop
- jsr cmd_execute_new ; spawn the new process
- add i, 1
- ifl i, 10
- set pc, test_proc_loop
- ; proclist
- jsr newline
- jsr proclist
- ; wait a little bit
- set a, 100
- jsr sleepproc
- ; kill all the processes
- set a, 4
- :test_kill_loop
- jsr killproc
- add a, 1
- ifl a, 14
- set pc, test_kill_loop
- jsr newline
- jsr proclist
- ; done!
- set pc, pop
Advertisement
Add Comment
Please, Sign In to add comment