;*************************************************************** ;Program: TinyOS 1.0 TinyTim ;Author: Tim Wylie ;Compile date: ;commands as of now are four or less characters. each ; parameter can be no more than 10 characters. folders should ; be only four chars long. end of os is * ;*************************************************************** main: lda load jsb printc lda endl jsb printc ;while loading need to look for additional programs installed ;as well as all folders and processes in kernel ;then branch to start shell b kernel_load load_return: b start_shell ;******************KERNEL************************************** kernel: ;*******************function strcmp**************************** ;function: strcmp ;description: this function takes two char strings and compares them. ; if equal it returns a zero, neg number if string1string2. ;*************************************************************** strcmp: ;int strcmp(char string1[], char string2[]) pop st strcmp_retaddr pop st strcmp_&string1 pop st strcmp_&string2 ld strcmp_retaddr push strcmp_for_1: ;for(int i=0;string1[i]==string2[i] &&string1[i]!='\0'&&string2[2]!='\0';i++){ ld #0 st strcmp_i strcmp_for_test_1: ld strcmp_&string1 add strcmp_i st strcmp_index_1 ld strcmp_&string2 add strcmp_i st strcmp_index_2 ldi strcmp_index_2 st strcmp_temp ldi strcmp_index_1 sub strcmp_temp bn strcmp_end_for_1 bp strcmp_end_for_1 ldi strcmp_index_1 bz strcmp_end_for_1 ldi strcmp_index_2 bz strcmp_end_for_1 ld strcmp_i add #1 st strcmp_i b strcmp_for_test_1 strcmp_end_for_1: ;end=string1[i]-string2[i] ldi strcmp_index_2 st strcmp_temp ldi strcmp_index_1 sub strcmp_temp st strcmp_end ld strcmp_end rsb ;} ;strcmp constants ;strcmp variables strcmp_end: ds 1 strcmp_&string1: ds 1 strcmp_&string2: ds 1 strcmp_index_1: ds 1 strcmp_index_2: ds 1 strcmp_i: db 0 strcmp_retaddr: ds 1 strcmp_temp: ds 1 ;**********************end strcmp function***************************************** ;*****************************strcpy*********************************** ;function:strcpy ;description: function that takes two strings and copies string2 into string1 ;************************************************************************* strcpy: ;void strcpy(char string1[], char string2[]) pop st strcpy_retaddr pop st strcpy_&string1 pop st strcpy_&string2 ld strcpy_retaddr push strcpy_for_1: ld #0 st strcpy_i strcpy_for_test_1: ld strcpy_&string1 add strcpy_i st strcpy_index_1 ld strcpy_&string2 add strcpy_i st strcpy_index_2 ldi strcpy_index_2 bz strcpy_end_for_1 ldi strcpy_index_2 sti strcpy_index_1 ld strcpy_i add #1 st strcpy_i b strcpy_for_test_1 strcpy_end_for_1: ;} ld #0 ;string1[i]='\0' sti strcpy_index_1 ld strcpy_&string1 ;maybe not needed rsb ;} ;strcpy constants ;strcpy variables strcpy_retaddr: ds 1 strcpy_i: db 0 strcpy_index_1: ds 1 strcpy_index_2: ds 1 strcpy_&string1: ds 1 strcpy_&string2: ds 1 ;******************************end strcpy********************************* ;******************************find*********************************** ;function: find ;description: this function takes a memory location and then finds the ; next 0 and returns that address in the ACC. ;****************************************************************** find: pop st find_retaddr pop st find_start ld find_retaddr push find_for_1: ;for(counter=0;file[counter]!=0;counter++) ld #0 st find_counter find_for_test_1: ld find_start add find_counter st find_index ldi find_index ;sub #0 ;!!!taken sub #0 out for space bz find_end_for_1 ld find_counter add #1 st find_counter b find_for_test_1 find_end_for_1: ld find_index rsb ;find variables find_retaddr: ds 1 find_start: ds 1 find_counter: db 0 find_index: ds 1 ;*****************************end find******************************** ;*****************kernel_load***************************** ;inline function: kernel_load ;description: this searches for files and folders in the diretories ; and sets the numbers and pointers ;********************************************************* kernel_load: lda home st location_ptr ;store starting point ;go one spot past enddir* ld kernel_load_#7 ;there are 5 slots and then* st kernel_load_counter ld #1 st kernel_load_ptr_spot kernel_load_for_1: ;for(counter=0;slot!='\n';counter++){ ; leave counter as is ;reset counter kernel_load_for_test_1: ;must test >20000 lda home_num add kernel_load_counter st kernel_load_index ldi kernel_load_index ;!!!took out sub #0 for space ;sub #0 bz kernel_load_end_for_1 ldi kernel_load_index sub #20000 bp kernel_load_end_for_1 kernel_load_if_1: ;if(*index==0) ldi kernel_load_index ;!!!!took out sub #0 for space ;sub #0 bz kernel_load_then_1 ldi kernel_load_index sub #20000 bp kernel_load_then_1 b kernel_load_else_1 kernel_load_then_1: ld home_num ;does nothing ;add #0 ;!!!took out add #0 for space st home_num b kernel_load_end_if_1 kernel_load_else_1: kernel_load_if_2: ;if(*index=='$' || *index=='/') ldi kernel_load_index sub dollar bz kernel_load_then_2 ldi kernel_load_index sub slash bz kernel_load_then_2 b kernel_load_else_2 kernel_load_then_2: ;now at beginning of file $ or / ld home_num add #1 st home_num lda home_num add kernel_load_ptr_spot st kernel_load_ptr_addr ld kernel_load_ptr_spot ;ptr_spot++ add #1 st kernel_load_ptr_spot ld kernel_load_index ;i think this is right sti kernel_load_ptr_addr kernel_load_for_3: ;for(counter;file[counter]!='*';counter++) ;leave counter as is kernel_load_for_test_3: lda home_num add kernel_load_counter st kernel_load_index ldi kernel_load_index sub star bz kernel_load_end_for_3 ld kernel_load_counter add #1 st kernel_load_counter b kernel_load_for_test_3 kernel_load_end_for_3: kernel_load_else_2: kernel_load_if_3: ;extra if not used yet kernel_load__then_3: kernel_load_end_if_3: kernel_load_end_if_2: kernel_load_end_if_1: ld kernel_load_counter add #1 st kernel_load_counter b kernel_load_for_test_1 kernel_load_end_for_1: b load_return ;kernel_load constants kernel_load_#2: db 2 kernel_load_#7: db 7 ;kernel_load variables kernel_load_counter: ds 1 kernel_load_index: db 0 kernel_load_ptr_spot: db 1 kernel_load_ptr_addr: db 0 ;********************end kernel_load************************* ;********************decipher_input**************************** ;inline function: decipher_input ;Description: This function will take the command and check to ; see if it is a real command like a big switch statement ; and then if needed it will check the parameter, and then ; it calls the function to carry it out. ;******************************************************************* decipher_input: decipher_input_if_1: ;if(command=='help'){ lda command push lda chelp push jsb strcmp bz decipher_input_then_1 b decipher_input_else_1 decipher_input_then_1: b help decipher_input_else_1: ;else{ decipher_input_if_2: ;if(command=='run') lda command push lda crun push jsb strcmp bz decipher_input_then_2 b decipher_input_else_2 decipher_input_then_2: b run decipher_input_else_2: ;else{ decipher_input_if_3: ;if(command=='list'){ lda command push lda clist push jsb strcmp bz decipher_input_then_3 b decipher_input_else_3 decipher_input_then_3: b list decipher_input_else_3: ;else{ decipher_input_if_4: ;if(command=='cd'){ lda command push lda ccd push jsb strcmp bz decipher_input_then_4 b decipher_input_else_4 decipher_input_then_4: b cd decipher_input_else_4: ;else{ decipher_input_if_5: ;if(command=='mdir'){ lda command push lda cmdir push jsb strcmp bz decipher_input_then_5 b decipher_input_else_5 decipher_input_then_5: b mdir decipher_input_else_5: ;else{ decipher_input_if_6: ;if(command=='quit'){ lda command push lda cquit push jsb strcmp bz decipher_input_then_6 b decipher_input_else_6 decipher_input_then_6: b quit decipher_input_else_6: decipher_input_if_7: ;if(command=='open'){ lda command push lda copen push jsb strcmp bz decipher_input_then_7 b decipher_input_else_7 decipher_input_then_7: b open decipher_input_else_7: decipher_input_if_8: ;if(command=='new'){ lda command push lda cnew push jsb strcmp bz decipher_input_then_8 b decipher_input_else_8 decipher_input_then_8: b new decipher_input_else_8: ;else decipher_input_if_9: ;if(command=='move'){ ;lda command ;push ;lda cmove ;push ;jsb strcmp ;bz decipher_input_then_9 ;b decipher_input_else_9 decipher_input_then_9: ;b move decipher_input_else_9: decipher_input_if_10: ;if(command=='del'){ ;lda command ;push ;lda cdel ;push ;jsb strcmp ;bz decipher_input_then_10 ;b decipher_input_else_10 decipher_input_then_10: ;b del decipher_input_else_10: lda error jsb printc decipher_input_end_if_10: decipher_input_end_if_9: decipher_input_end_if_8: decipher_input_end_if_7: decipher_input_end_if_6: decipher_input_end_if_5: decipher_input_end_if_4: decipher_input_end_if_3: decipher_input_end_if_2: decipher_input_end_if_1: b return_shell ;decipher_input variables ;decipher_input constants command_list: chelp: dc 'help' db 0 crun: dc 'run' db 0 clist: dc 'list' db 0 ccd: dc 'cd' db 0 cmdir: dc 'mdir' db 0 cquit: dc 'quit' db 0 copen: dc 'open' db 0 cnew: dc 'new' db 0 ;cmove: dc 'move' ;move and del are commented out for space ;db 0 ;cdel: dc 'del' ;db 0 ;need a save command to type db 42 ;'*' signifies end of commands for help command loop ;************************end decipher_input********************** ;*********************help*********************************** ;command: help ;description: this function just prints out a list of all the possible ; commands for the user to type ;************************************************************ help: ;need to put in a for loop help_for_1: ;for(counter=0;index[counter]!='*';counter++) ld #0 st help_counter help_for_test_1: lda command_list add help_counter st help_index ldi help_index sub star bz help_end_for_1 ld help_index jsb printc lda endl jsb printc ;for(counter;index[counter]!=0;counter++) in find function ld help_index st help_index_temp ;store in a temp variable push jsb find st help_index ;store where 0 is in help_index sub help_index_temp ;find difference between indexes add help_counter ;find where counter should be st help_counter ;update counter ld help_counter add #1 st help_counter b help_for_test_1 help_end_for_1: b return_shell ;help variables help_index: ds 1 help_counter: db 0 help_index_temp: db 0 ;help constants ;***********************************end help********************** ;**************************run******************************** ;command: run ;description: this will run the program given in the parameter ; this assumes a program. if it is not. it will crash ; the beginning of this could be encapsulated into a function ; and passed the location_ptr and the parameter(both of which ; are global so that's not really needed. this same functionality ; is used in run, cd, move, open(included in run), ;************************************************************* run: ld location_ptr ;set at loading and when cd st run_index ld location_ptr ;for(counter=0;file[counter]!=0;counter++) push jsb find st run_index ;used find function for 0 ld run_index ;move to num_ptrs add #1 st run_index ldi run_index ;get num_ptrs st run_num_ptrs ld run_index ;go to ptrs add #1 st run_index run_for_2: ;for(spot=0;num_pointers>0;num_pointers--, spot++) ld #0 st run_ptr_spot run_for_test_2: ld run_num_ptrs ;sub #0 ;!!!took out sub #0 for space bz run_end_for_2 ld run_index add run_ptr_spot st run_ptr_addr ldi run_ptr_addr st run_address ld run_address ;must NOT type in $ or / add #1 st run_address run_if_1: ld run_address ;strcmp call push lda parameter ;must pass address push jsb strcmp ;if equal will return 0 bz run_then_1 b run_end_if_1 run_then_1: ;starts program run_open_if_1: ;if(command=run);this sees if text open or program run should happen ld crun sub command bz run_open_then_1 b run_open_else_1 run_open_then_1: ;use find function for for loop ;for(counter=0;file[counter]!=0;counter++) ld run_address push jsb find st run_index ld run_index add #1 st run_index ; branch and start. must add 12000 to get branch opcode ld run_index add run_#12000 st run_index b run_index ;bi run_index run_open_else_1: ;else{ run_open_cd_if_1: ld copen ;if(command==open) sub command bz run_open_cd_then_1 b run_open_cd_else_1 run_open_cd_then_1: run_open_for_1: ;for(counter=0;file[counter]!='*';count++) ld #0 st run_counter run_open_for_test_1: ld run_address add run_counter st run_index ldi run_index sub star bz run_open_end_for_1 ld run_index jsb printc lda endl jsb printc run_open_for_2: ;for(counter;file[counter]!=0;count++) ;leave counter run_open_for_test_2: ld run_address add run_counter st run_index ldi run_index ;sub #0 ;!!!took out sub #0 for space bz run_open_end_for_2 ld run_counter add #1 st run_counter b run_open_for_test_2 run_open_end_for_2: ld run_counter add #1 st run_counter b run_open_for_test_1 run_open_end_for_1: b return_shell run_open_cd_else_1: ld run_address ;want the '/' in the prompt sub #1 st run_address ld location_ptr ;set prev pointer st location_prev ld run_address ;tell os you're in other folder st location_ptr b return_shell run_open_cd_end_if_1: run_open_end_if_1: run_end_if_1: ld run_ptr_spot ;ptr_spot++; add #1 st run_ptr_spot ld run_num_ptrs ;num_ptrs--; sub #1 st run_num_ptrs b run_for_test_2 run_end_for_2: run_cd_if_1: ld command sub ccd bz run_cd_then_1 b run_cd_else_1 run_cd_then_1: lda run_cd_error jsb printc b run_cd_end_if_1 run_cd_else_1: lda run_error jsb printc run_cd_end_if_1: b return_shell ;run constants run_#12000: db 12000 ;for BI indirectly branch run_error: dc 'No prog' db 0 run_cd_error: dc 'No dir' db 0 ;run variables run_index: db 0 run_counter: db 0 run_num_ptrs: db 0 run_ptr_spot: db 0 run_address: db 0 run_ptr_addr: db 0 ;************************end run*********************************** ;************************************************************* ;command: list ;description: shows contents of a folder ;************************************************************ list: ld location_ptr ;cout<0;num_ptrs--, index++) ;leave num_ptrs the same ld list_index add #1 st list_index list_test_for_2: ld list_num_ptrs ;sub #0 ;!!!took out sub #0 for space bz list_end_for_2 ldi list_index ;cout<=5) no room ld mdir_num_ptrs ; need to impliment more than five files later sub mdir_#5 bn mdir_else_1 b mdir_then_1 mdir_then_1: lda mdir_error jsb printc b mdir_end_if_1 mdir_else_1: ldi mdir_index ;num_ptrs++ add #1 sti mdir_index ld mdir_num_ptrs ;mdir_num_ptrs++; add #1 st mdir_num_ptrs ld mdir_index ;move to free slot add mdir_num_ptrs st mdir_insert_spot mdir_for_2: ;for(index++;*index!=0&& *index<20000;counter++) ;leave counter where it is ld mdir_counter add #1 st mdir_counter mdir_for_test_2: ld location_ptr add mdir_counter st mdir_index ldi mdir_index ;doing it this way acts as an || rather than &&, need an if ;sub #0 ;!!!! sub #0 taken out for space bz mdir_end_for_2 ldi mdir_index sub #20000 bp mdir_end_for_2 mdir_for_3: ;for(index;index!=* ;counter++) ;leave counter where it is mdir_for_test_3: ld location_ptr add mdir_counter st mdir_index ldi mdir_index sub star bz mdir_end_for_3 ld mdir_counter add #1 st mdir_counter b mdir_for_test_3 mdir_end_for_3: ld mdir_counter add #1 st mdir_counter b mdir_for_test_2 mdir_end_for_2: mdir_room_if_1: ;check to see if there is at least 13 spots of memory open ld #880 ;this tries to prevent you from crashing the os by allocating too much sub mdir_index bp mdir_room_then_1 b mdir_room_else_1 mdir_room_then_1: ld mdir_index ;put ptr to folder in parent folder sti mdir_insert_spot ld slash ;store slash sti mdir_index ld mdir_index st new_index ;store spot for new command. doing it this way, is faster ;than an if statement and doesn't waste space add #1 st mdir_index lda parameter push ld mdir_index push jsb strcpy mdir_make: ;this makes the dir ld mdir_index ;go to 0 push jsb find st mdir_index ;ld mdir_index ;not necessary add #1 ;go to num_ptrs st mdir_index ld #0 sti mdir_index ld mdir_index ;go 5 spaces past ptrs and then to last one for star add #6 st mdir_index ld star sti mdir_index mdir_end_make: mdir_end_if_1: mdir_new_if_1: ld command sub cnew bz return_new b return_shell mdir_new_end_if_1: mdir_room_else_1: ld mdir_insert_spot ;num_ptrs--; sub mdir_num_ptrs st mdir_index ldi mdir_index sub #1 sti mdir_index lda mdir_error jsb printc b return_shell mdir_room_end_if_1: ;mdir variables mdir_index: db 0 mdir_counter: db 0 mdir_num_ptrs: db 0 mdir_insert_spot: db 0 ;mdir constants #880: db 880 mdir_error: dc 'NR' db 0 mdir_#5: db 5 ;****************************end mdir***************************** ;***********************open******************************* ;command:open ;description: open will open a text document and read it ; it actually opens in the run function because they a lot of ; the same functionality ;************************************************************ open: b run ;***************************end open*************************** ;**********************move********************************* ;command:move ;description: move will move a file or program to another folder. ; not implemented so commented out. ;************************************************************ ;move: ;b return_shell ;**********************end move****************************** ;***********************************new********************** ;command:new ;description: new will create a new text document. It actually ; uses the mdir command and then changes the folder format to ; a text format. This saves a lot of redundant code. ;note:will also be used to make a new program based on the .t or ; .p but not enough space to test for it and format. ; you cannot edit files after creating them yet. ;*********************************************************** new: b mdir return_new: ld dollar sti new_index ;set in mdir to have the address of the file ld new_index push jsb find ;returns address of null add #1 ;go to next spot st new_index jsb inputc ;input from user. needs to be in a loop. maybe? ld new_index ;find null terminator push jsb find add #1 ;go to next spot st new_index ld star ;store eof char '*' sti new_index b return_shell ;return ;new variables new_index: ds 1 ;**********************end new************************************* ;**********************del************************************* ;command: del ;description: deletes files or folders. not implemented so it ; is commented out. ;************************************************************* ;del: ;b return_shell ;************************end del************************************ ;******************************quit**************************** ;command:quit ;description: this function shuts down the os. it will not save ; any information due to the fact that all information is in ; memory, and not on a hard disk of some sort. ;************************************************************** quit: shut_down: ;lda endl ;took out for space. not needed ;jsb printc lda shutd jsb printc stop ;**************************end quit************************** ;kernel variables ;kernel constants end_kernel: ;********************end kernel******************************* ;*************************shell**************************** start_shell: lda strmsg jsb printc shell: ;do{ lda endl jsb printc ld location_ptr ;prompt jsb printc lda colon jsb printc lda input_buffer ;get input jsb inputc ;************************format_input************************* ;inline function:format_input ;description: This function takes the input and checks to see ; if it is correctly formatted and of the correct length ; and then places the command in the command string ; and it puts the paramater in its string. If it is ; incorrectly typed then it displays an error message ;************************************************************** format_input: ;initialize variables ld #0 st format_input_exit ld #0 st format_input_error ld #0 st format_input_num_spaces format_input_for_1: ;for(counter=0;exit=false;counter++) ld #0 st format_input_counter format_input_for_test_1: ld format_input_exit sub #1 bz format_input_end_for_1 format_input_if_1: ;if(counter>maxinput){ ld format_input_counter sub format_input_MAXINPUT bp format_input_then_1 b format_input_else_1 format_input_then_1: ;error=true;exit=true;} ld #1 st format_input_exit ld #1 st format_input_error b format_input_end_if_1 format_input_else_1: ;else{ format_input_if_2: ;if(input[counter]==' '){ lda input_buffer add format_input_counter st format_input_index ldi format_input_index sub format_input_space bz format_input_then_2 b format_input_else_2 format_input_then_2: ;spaces++; ld format_input_num_spaces add #1 st format_input_num_spaces format_input_if_3: ;if(num_spaces>1){ ld format_input_num_spaces sub #1 bp format_input_then_3 b format_input_end_if_3 ;do i need to bn with bp format_input_then_3: ;error=true;exit=true} ld #1 st format_input_error ld #1 st format_input_exit format_input_end_if_3: format_input_else_2: ;else{ format_input_if_4: ;if(input[counter]='\n'){ ldi format_input_index ;sub #0 ;took out sub #0 for space bz format_input_then_4 b format_input_end_if_4 format_input_then_4: ;error=false;exit=true;} ld #0 ;redundant st format_input_error ld #1 st format_input_exit format_input_end_if_4: format_input_end_if_2: format_input_end_if_1: ld format_input_counter add #1 st format_input_counter b format_input_for_test_1 format_input_end_for_1: format_input_if_5: ;if(!error){ ld format_input_error ;sub #0 ;!!!took out sub #0 for space bz format_input_then_5 b format_input_else_5 format_input_then_5: format_input_for_2: ;for(counter=0;input[counter]!= ' ' && input[counter]!='\n';counter++){ ld #0 st format_input_counter format_input_for_test_2: lda input_buffer ;set index add format_input_counter st format_input_index lda command add format_input_counter st format_input_index2 ldi format_input_index sub format_input_space bz format_input_end_for_2 ldi format_input_index ;sub #0 ;!!!took out sub #0 for space bz format_input_end_for_2 ldi format_input_index sti format_input_index2 ld format_input_counter add #1 st format_input_counter b format_input_for_test_2 format_input_end_for_2: ;command[index]='\n'; lda command add format_input_counter st format_input_index2 ld #0 sti format_input_index2 format_input_if_6: ;if(input[counter]!='n'){ ldi format_input_index ;sub #0 ;!!!took out sub #0 for space bz format_input_end_if_6 format_input_then_6: ld format_input_index add #1 st format_input_index ld format_input_index ;for(counter,counter2=0 ;input[counter]='\n';counter++){ push lda parameter push jsb strcpy format_input_end_if_6: b format_input_end_if_5 format_input_else_5: ;else{cout<<"Bad Command!"<