@section text //---BEGIN string_print_num_16--- //TODO append to string instead of doing putch .string_print_num_16 //in 0 is the 16-bit number to print //in 1-2 is the address of a string buffer to append it to ::__subvar re+rh 0 rl rh,rl(i) a rh,rl b ::string_print_num_res re+rh+rl a rh,rl(i) b rh,rl //reset buffer index ::string_print_num_buf_idx_upper re+rh+rl :::string_print_num_buf_idx_start rh,rl ::string_print_num_buf_idx re+rh+rl ::string_print_num_buf_idx_start rh,rl(i) :string_print_num_buf_idx_start rh,rl .string_print_num_16_main_loop //copy res to divbuf_b ::string_print_num_res re+rh+rl rh,rl(i) a rh,rl b ::string_print_num_divbuf_b re+rh+rl a rh,rl(i) b rh,rl //zero out divbuf_t ::string_print_num_divbuf_t re+rh+rl 0 rh,rl(i) 0 rh,rl //reset shift count ::string_print_num_shift_count re+rh+rl 0 rh,rl .string_print_num_16_div_loop //shift until divbuf_t >= 10 or shift_count == 16 .string_print_num_16_shift_loop //the actual shift -- divbuf ::string_print_num_divbuf_b re+rh+rl rh,rl a a b 0 flags add rh,rl rh,rl(i) a a b add rh,rl(i) ::string_print_num_divbuf_t re+rh rh,:string_print_num_divbuf_t a a b add rh,:string_print_num_divbuf_t //the actual shift -- res ::string_print_num_res re+rh+rl rh,rl a a b 0 flags add rh,rl rh,rl(i) a a b add rh,rl(i) //increment shift count ::string_print_num_shift_count re+rh rh,:string_print_num_shift_count a 1 b 0 flags add rh,:string_print_num_shift_count //check if divbuf_t >= 10 (note that it will never exceed 15) ::string_print_num_divbuf_t re+rh rh,:string_print_num_divbuf_t a 9 b branch :string_print_num_16_shift_loop_do_subtract a>b //check if shift_count >= 16 ::string_print_num_shift_count re+rh rh,:string_print_num_shift_count a 15 b branch :string_print_num_16_div_loop_end a>b //otherwise loop branch :string_print_num_16_shift_loop 1 .string_print_num_16_shift_loop_do_subtract //subtract 10 from divbuf_t and set the low bit of res ::string_print_num_divbuf_t re+rh rh,:string_print_num_divbuf_t a 0b11110110 b 0 flags add rh,:string_print_num_divbuf_t ::string_print_num_res re+rh rh,:string_print_num_res a 1 b or rh,:string_print_num_res //check if shift_count >= 16 ::string_print_num_shift_count re+rh rh,:string_print_num_shift_count a 15 b branch :string_print_num_16_div_loop_end a>b //otherwise loop branch :string_print_num_16_shift_loop 1 .string_print_num_16_div_loop_end //buffer the remainder (divbuf_t) ::string_print_num_divbuf_t re+rh rh,:string_print_num_divbuf_t a '0' b 0 flags add a ::string_print_num_buf_idx_upper re+rh rh,:string_print_num_buf_idx_upper c ::string_print_num_buf_idx re+rh+rl rh,rl(i) b rh,rl rl b rh c re a rh,rl //decrement print_num_buf_idx ::string_print_num_buf_idx re+rh+rl rh,rl a 255 b 0 flags add rh,rl rh,rl(i) a add rh,rl(i) ::string_print_num_buf_idx_upper re+rh rh,:string_print_num_buf_idx_upper a add rh,:string_print_num_buf_idx_upper //loop if result is nonzero ::string_print_num_res re+rh+rl rh,rl a 0 b branch :string_print_num_16_main_loop a>b rh,rl(i) a branch :string_print_num_16_main_loop a>b //otherwise done //print the buffered values .string_print_num_16_print_loop //increment print_num_buf_idx ::string_print_num_buf_idx re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_print_num_buf_idx_upper re+rh rh,:string_print_num_buf_idx_upper a add rh,:string_print_num_buf_idx_upper //print ::string_print_num_buf_idx_upper re+rh rh,:string_print_num_buf_idx_upper c ::string_print_num_buf_idx re+rh+rl rh,rl(i) a rh,rl rl a rh c re rh,rl a ::__subvar re+rh a rh,0 call :tty_putch ::string_print_num_buf_idx_upper re+rh rh,:string_print_num_buf_idx_upper a :::string_print_num_buf_idx_start b a=b a 255 b branch :string_print_num_16_print_loop xor ::string_print_num_buf_idx re+rh+rl rh,rl(i) a ::string_print_num_buf_idx_start b a=b a 255 b branch :string_print_num_16_print_loop xor rh,rl a :string_print_num_buf_idx_start b a=b a 255 b branch :string_print_num_16_print_loop xor ret //---END string_print_num_16--- @section bss .string_print_num_res dl 0 .string_print_num_divbuf_b dl 0 .string_print_num_divbuf_t dl 0 .string_print_num_shift_count dw 0 .string_print_num_buf_idx_upper dw 0 .string_print_num_buf_idx dl 0 .string_print_num_buf dw 0 dw 0 dw 0 dw 0 .string_print_num_buf_idx_start dw 0 @section text //---BEGIN string_copy--- //note that ordinary strings only use the low byte of each memory address //therefore, string_copy will not touch the high byte //code adapted from mem_copy .string_copy //out 1-2 is destination buffer //in 3-4 is source null-terminated string //in 5-6 is max # of bytes to copy; the destination string will be // terminated if a terminator is not copied //source address -> string_copy_source_counter ::__subvar re+rh rh,3 a ::string_copy_source_counter_upper re+rh a rh,:string_copy_source_counter_upper ::__subvar re+rh 4 rl rh,rl(i) a rh,rl b ::string_copy_source_counter re+rh+rl a rh,rl(i) b rh,rl //dest address -> string_copy_dest_counter ::__subvar re+rh rh,1 a ::string_copy_dest_counter_upper re+rh a rh,:string_copy_dest_counter_upper ::__subvar re+rh 2 rl rh,rl(i) a rh,rl b ::string_copy_dest_counter re+rh+rl a rh,rl(i) b rh,rl //string_copy_source_counter + words to copy -> string_copy_source_counter_target ::string_copy_source_counter re+rh rh,:string_copy_source_counter a ::__subvar re+rh rh,6 b 0 flags ::string_copy_source_counter_target re+rh add rh,:string_copy_source_counter_target ::string_copy_source_counter re+rh+rl rh,rl(i) a ::__subvar re+rh 6 rl rh,rl(i) b ::string_copy_source_counter_target re+rh+rl add rh,rl(i) ::string_copy_source_counter_upper re+rh rh,:string_copy_source_counter_upper a ::__subvar re+rh rh,5 b ::string_copy_source_counter_target_upper re+rh add rh,:string_copy_source_counter_target_upper .string_copy_loop //check to see if target has been reached ::string_copy_source_counter re+rh rh,:string_copy_source_counter a ::string_copy_source_counter_target re+rh rh,:string_copy_source_counter_target b a=b a 255 b branch :string_copy_loop_continue xor :string_copy_source_counter_target rl rh,rl(i) b ::string_copy_source_counter re+rh+rl rh,rl(i) a a=b a 255 b branch :string_copy_loop_continue xor ::string_copy_source_counter_upper re+rh rh,:string_copy_source_counter_upper a ::string_copy_source_counter_target_upper re+rh rh,:string_copy_source_counter_target_upper b a=b a 255 b branch :string_copy_loop_continue xor branch :string_copy_loop_end_do_terminate 1 .string_copy_loop_continue //don't copy upper byte //copy lower byte ::string_copy_source_counter_upper re+rh rh,:string_copy_source_counter_upper c ::string_copy_source_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a ::string_copy_dest_counter_upper re+rh rh,:string_copy_dest_counter_upper c ::string_copy_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re a rh,rl //if byte is 0, end immediately 0 b branch :string_copy_loop_end a=b //increment source counter ::string_copy_source_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_copy_source_counter_upper re+rh rh,:string_copy_source_counter_upper a add rh,:string_copy_source_counter_upper //increment dest counter ::string_copy_dest_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_copy_dest_counter_upper re+rh rh,:string_copy_dest_counter_upper a add rh,:string_copy_dest_counter_upper branch :string_copy_loop 1 .string_copy_loop_end ret .string_copy_loop_end_do_terminate //we've reached the limit of bytes to copy; terminate the dest string ::string_copy_dest_counter_upper re+rh rh,:string_copy_dest_counter_upper c ::string_copy_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re 0 rh,rl ret //---END string_copy--- @section bss .string_copy_source_counter_upper dw 0 .string_copy_source_counter dl 0 .string_copy_dest_counter_upper dw 0 .string_copy_dest_counter dl 0 .string_copy_source_counter_target_upper dw 0 .string_copy_source_counter_target dl 0 @section text //---BEGIN string_len--- .string_len //in 1-2 is address of null-terminated string //out 5-6 is length of string (excl. null terminator) //string address -> string_len_counter ::__subvar re+rh rh,1 a ::string_len_counter_upper re+rh a rh,:string_len_counter_upper ::__subvar re+rh 2 rl rh,rl(i) a rh,rl b ::string_len_counter re+rh+rl a rh,rl(i) b rh,rl //0 to length ::__subvar re+rh 5 rl 0 rh,rl(i) 0 rh,rl 6 rl 0 rh,rl(i) 0 rh,rl .string_len_loop //read lower byte ::string_len_counter_upper re+rh rh,:string_len_counter_upper c ::string_len_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a //if byte is 0, end immediately 0 b branch :string_len_loop_end a=b //increment counter ::string_len_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_len_counter_upper re+rh rh,:string_len_counter_upper a add rh,:string_len_counter_upper //increment len ::__subvar re+rh 6 rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) rh,5 a add rh,5 branch :string_len_loop 1 .string_len_loop_end ret //---END string_len--- @section bss .string_len_counter_upper dw 0 .string_len_counter dl 0 @section text //---BEGIN string_cmp_prefix--- //compare two strings, ending the comparison when one ends //if the first string is a prefix of the second, the result is true //if the second is a prefix of the first (and the strings differ in length), it is false //code adapted from string_copy .string_cmp_prefix //out 0 is 1 for match, 0 for no match //in 1-2 is a null-terminated string //in 3-4 is another null-terminated string //source address -> string_cmp_prefix_source_counter ::__subvar re+rh rh,1 a ::string_cmp_prefix_source_counter_upper re+rh a rh,:string_cmp_prefix_source_counter_upper ::__subvar re+rh 2 rl rh,rl(i) a rh,rl b ::string_cmp_prefix_source_counter re+rh+rl a rh,rl(i) b rh,rl //dest address -> string_cmp_prefix_dest_counter ::__subvar re+rh rh,3 a ::string_cmp_prefix_dest_counter_upper re+rh a rh,:string_cmp_prefix_dest_counter_upper ::__subvar re+rh 4 rl rh,rl(i) a rh,rl b ::string_cmp_prefix_dest_counter re+rh+rl a rh,rl(i) b rh,rl .string_cmp_prefix_loop //don't copy upper byte //fetch 1st string byte ::string_cmp_prefix_source_counter_upper re+rh rh,:string_cmp_prefix_source_counter_upper c ::string_cmp_prefix_source_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a ::string_cmp_prefix_s1 re+rh a rh,:string_cmp_prefix_s1 //if 1st string byte is 0, return true (see above for why) 0 b branch :string_cmp_prefix_rtrue a=b //fetch 2nd string byte ::string_cmp_prefix_dest_counter_upper re+rh rh,:string_cmp_prefix_dest_counter_upper c ::string_cmp_prefix_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a ::string_cmp_prefix_s2 re+rh a rh,:string_cmp_prefix_s2 //if 2nd string byte is 0, return false (see above for why) 0 b branch :string_cmp_prefix_rfalse a=b //if bytes differ, return false ::string_cmp_prefix_s1 re+rh rh,:string_cmp_prefix_s1 b a=b a 255 b branch :string_cmp_prefix_rfalse xor //increment source counter ::string_cmp_prefix_source_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_cmp_prefix_source_counter_upper re+rh rh,:string_cmp_prefix_source_counter_upper a add rh,:string_cmp_prefix_source_counter_upper //increment dest counter ::string_cmp_prefix_dest_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_cmp_prefix_dest_counter_upper re+rh rh,:string_cmp_prefix_dest_counter_upper a add rh,:string_cmp_prefix_dest_counter_upper branch :string_cmp_prefix_loop 1 .string_cmp_prefix_rfalse ::__subvar re+rh 0 rl 0 rh,rl(i) 0 rh,rl ret .string_cmp_prefix_rtrue ::__subvar re+rh 0 rl 0 rh,rl(i) 1 rh,rl ret //---END string_cmp_prefix--- @section bss .string_cmp_prefix_source_counter_upper dw 0 .string_cmp_prefix_source_counter dl 0 .string_cmp_prefix_dest_counter_upper dw 0 .string_cmp_prefix_dest_counter dl 0 .string_cmp_prefix_s1 dw 0 .string_cmp_prefix_s2 dw 0 @section text //---BEGIN string_pack--- //ordinary strings only use the low byte of each memory address //this routine packs them to use both (i, d, i, d, ...) //and pads to the length of a full word with zero bytes //code adapted from string_copy .string_pack //out 1-2 is destination buffer //in 3-4 is source null-terminated string //in 5-6 is max no. of bytes to copy; the resultant string will be // terminated if a terminator is not copied //source address -> string_pack_source_counter ::__subvar re+rh rh,3 a ::string_pack_source_counter_upper re+rh a rh,:string_pack_source_counter_upper ::__subvar re+rh 4 rl rh,rl(i) a rh,rl b ::string_pack_source_counter re+rh+rl a rh,rl(i) b rh,rl //dest address -> string_pack_dest_counter ::__subvar re+rh rh,1 a ::string_pack_dest_counter_upper re+rh a rh,:string_pack_dest_counter_upper ::__subvar re+rh 2 rl rh,rl(i) a rh,rl b ::string_pack_dest_counter re+rh+rl a rh,rl(i) b rh,rl //string_pack_source_counter + words to copy -> string_pack_source_counter_target ::string_pack_source_counter re+rh rh,:string_pack_source_counter a ::__subvar re+rh rh,6 b 0 flags ::string_pack_source_counter_target re+rh add rh,:string_pack_source_counter_target ::string_pack_source_counter re+rh+rl rh,rl(i) a ::__subvar re+rh 6 rl rh,rl(i) b ::string_pack_source_counter_target re+rh+rl add rh,rl(i) ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper a ::__subvar re+rh rh,5 b ::string_pack_source_counter_target_upper re+rh add rh,:string_pack_source_counter_target_upper .string_pack_loop //check to see if target has been reached ::string_pack_source_counter re+rh rh,:string_pack_source_counter a ::string_pack_source_counter_target re+rh rh,:string_pack_source_counter_target b a=b a 255 b branch :string_pack_loop_continue xor :string_pack_source_counter_target rl rh,rl(i) b ::string_pack_source_counter re+rh+rl rh,rl(i) a a=b a 255 b branch :string_pack_loop_continue xor ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper a ::string_pack_source_counter_target_upper re+rh rh,:string_pack_source_counter_target_upper b a=b a 255 b branch :string_pack_loop_continue xor branch :string_pack_loop_end 1 .string_pack_loop_continue //copy lower byte of source to upper byte of dest ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper c ::string_pack_source_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a ::string_pack_dest_counter_upper re+rh rh,:string_pack_dest_counter_upper c ::string_pack_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re a rh,rl(i) //clear lower byte of dest (in case the string has ended and padding is needed) 0 rh,rl //if byte is 0, end immediately 0 b branch :string_pack_loop_end a=b //increment source counter ::string_pack_source_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper a add rh,:string_pack_source_counter_upper //check to see if target has been reached ::string_pack_source_counter re+rh rh,:string_pack_source_counter a ::string_pack_source_counter_target re+rh rh,:string_pack_source_counter_target b a=b a 255 b branch :string_pack_loop_continue2 xor :string_pack_source_counter_target rl rh,rl(i) b ::string_pack_source_counter re+rh+rl rh,rl(i) a a=b a 255 b branch :string_pack_loop_continue2 xor ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper a ::string_pack_source_counter_target_upper re+rh rh,:string_pack_source_counter_target_upper b a=b a 255 b branch :string_pack_loop_continue2 xor branch :string_pack_loop_end_do_terminate 1 .string_pack_loop_continue2 //copy lower byte of source to lower byte of dest ::string_pack_source_counter_upper re+rh rh,:string_pack_source_counter_upper c ::string_pack_source_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re rh,rl a ::string_pack_dest_counter_upper re+rh rh,:string_pack_dest_counter_upper c ::string_pack_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re a rh,rl //if byte is 0, end immediately 0 b branch :string_pack_loop_end a=b //increment dest counter ::string_pack_dest_counter re+rh+rl rh,rl a 1 b 0 flags add rh,rl rh,rl(i) a 0 b add rh,rl(i) ::string_pack_dest_counter_upper re+rh rh,:string_pack_dest_counter_upper a add rh,:string_pack_dest_counter_upper branch :string_pack_loop 1 .string_pack_loop_end ret .string_pack_loop_end_do_terminate //we've hit the max # of bytes to copy; terminate the destination string ::string_pack_dest_counter_upper re+rh rh,:string_pack_dest_counter_upper c ::string_pack_dest_counter re+rh+rl rh,rl(i) b rh,rl rl b rh c re 0 rh,rl(i) 0 rh,rl ret //---END string_pack--- @section bss .string_pack_source_counter_upper dw 0 .string_pack_source_counter dl 0 .string_pack_dest_counter_upper dw 0 .string_pack_dest_counter dl 0 .string_pack_source_counter_target_upper dw 0 .string_pack_source_counter_target dl 0