0001 0000 ;RAM system monitor 0002 0000 ;Macro definitions for three levels of nested call and ret 0003 0000 #define call0(address) \return: .set $+15\ ldm return\ stm return_jump0+1\ ldm return+1\ stm return_jump0+2 0004 0000 #defcont \ jmp address\ .dw $+2 0005 0000 #define ret0 \ jmp return_jump0 0006 0000 #define call1(address) \return: .set $+15\ ldm return\ stm return_jump1+1\ ldm return+1\ stm return_jump1+2 0007 0000 #defcont \ jmp address\ .dw $+2 0008 0000 #define ret1 \ jmp return_jump1 0009 0000 #define call2(address) \return: .set $+15\ ldm return\ stm return_jump2+1\ ldm return+1\ stm return_jump2+2 0010 0000 #defcont \ jmp address\ .dw $+2 0011 0000 #define ret2 \ jmp return_jump2 0012 0000 ;Buffer location defined by these constant values 0013 0000 buff_low: .equ 0a0h ;low byte of buffer address 0014 0000 buff_high: .equ 0fh ;high byte of buffer address 0015 0000 buffer: .equ 0fa0h ;two-byte address constant 0016 0810 .org 0810h 0017 0810 1F return: .db 1fh ;placeholder for first definition of variable label -- NOP 0018 0811 13 14 08 sm_cold_start: jmp sm_lukewarm ;remove when used in ROM so can intialize port 0019 0814 ;Initialize port -- not needed if already initialized 0020 0814 ; LDI 4EH ;1 stop bit, no parity, 8-bit char, 16x baud 0021 0814 ; OUT 03H ;write to UART control port 0022 0814 ; LDI 37H ;enable receive and transmit 0023 0814 ; OUT 03H ;write to control port 0024 0814 ;Print greeting 0025 0814 11 9B 0E sm_lukewarm ldm sm_greeting 0026 0817 12 84 0F stm ws_inst+1 0027 081A 11 9C 0E ldm sm_greeting+1 0028 081D 12 85 0F stm ws_inst+2 0029 0820 call0(write_string) 0029 0820 0029 0820 11 2F 08 0029 0823 12 90 0F 0029 0826 11 30 08 0029 0829 12 91 0F 0029 082C 13 4C 0D 0029 082F 31 08 0030 0831 0031 0831 ;Warm start for system monitor, re-entry point after commands have finished 0032 0831 ;Prompt for routine number input 0033 0831 11 CD 0E sm_warm ldm sm_prompt 0034 0834 12 84 0F stm ws_inst+1 0035 0837 11 CE 0E ldm sm_prompt+1 0036 083A 12 85 0F stm ws_inst+2 0037 083D call0(write_string) 0037 083D 0037 083D 11 4C 08 0037 0840 12 90 0F 0037 0843 11 4D 08 0037 0846 12 91 0F 0037 0849 13 4C 0D 0037 084C 4E 08 0038 084E 0039 084E ;Get character and jump to monitor routine 0040 084E 17 03 sm_chk_loop: in 03h ;get status 0041 0850 0C 02 andim 02h ;check RxRDY 0042 0852 14 4E 08 jpz sm_chk_loop 0043 0855 17 02 in 02h ;get char from port and echo 0044 0857 12 61 0F stm choice 0045 085A ;sm_echo_loop in 03h 0046 085A ; andim 01h ;check TxRDY 0047 085A ; jpz sm_echo_loop 0048 085A ; ldm choice 0049 085A ; out 02h 0050 085A 0F 35 cmp '5' 0051 085C 16 7A 0A jpc sm_bload 0052 085F 0F 34 cmp '4' 0053 0861 16 96 09 jpc sm_load 0054 0864 0F 33 cmp '3' 0055 0866 16 84 09 jpc sm_run 0056 0869 0F 32 cmp '2' 0057 086B 16 71 08 jpc sm_dump 0058 086E 13 31 08 jmp sm_warm ;any number other than 2 to 5 results in warm restart 0059 0871 0060 0871 ;Memory dump routine 0061 0871 ;Get address from input string 0062 0871 13 47 0C sm_dump jmp get_address 0063 0874 11 5E 0F d_addr_back ldm address 0064 0877 12 72 0F stm d_indexed_ldm+1 0065 087A 11 5F 0F ldm address+1 0066 087D 12 73 0F stm d_indexed_ldm+2 0067 0880 0068 0880 ;Dump 16 lines of 16 characters each 0069 0880 ;Set up line counter 0070 0880 10 10 ldi 16 0071 0882 12 64 0F stm line_counter 0072 0885 ;Loop for putting a memory dump line in the buffer 0073 0885 ;Start with 4 characters of the starting address of the line, followed by space 0074 0885 11 73 0F d_line_loop ldm d_indexed_ldm+2 ;high byte of memory address 0075 0888 12 62 0F stm byte 0076 088B call0(byte_to_hex_pair) 0076 088B 0076 088B 11 9A 08 0076 088E 12 90 0F 0076 0891 11 9B 08 0076 0894 12 91 0F 0076 0897 13 19 0E 0076 089A 9C 08 0077 089C 11 5A 0F ldm char_pair 0078 089F 12 A0 0F stm buffer ;start of line 0079 08A2 11 5B 0F ldm char_pair+1 0080 08A5 12 A1 0F stm buffer+1 0081 08A8 11 72 0F ldm d_indexed_ldm+1 ;low byte of memory address 0082 08AB 12 62 0F stm byte 0083 08AE call0(byte_to_hex_pair) 0083 08AE 0083 08AE 11 BD 08 0083 08B1 12 90 0F 0083 08B4 11 BE 08 0083 08B7 12 91 0F 0083 08BA 13 19 0E 0083 08BD BF 08 0084 08BF 11 5A 0F ldm char_pair 0085 08C2 12 A2 0F stm buffer+2 0086 08C5 11 5B 0F ldm char_pair+1 0087 08C8 12 A3 0F stm buffer+3 0088 08CB 10 20 ldi 20h ;space character 0089 08CD 12 A4 0F stm buffer+4 0090 08D0 ;Set up for getting 16 memory bytes, converting to characters, and putting in string buffer 0091 08D0 10 A0 ldi buff_low 0092 08D2 08 05 addim 5 0093 08D4 12 78 0F stm d_indexed_stm+1 ;low byte of location of first character in output string 0094 08D7 10 0F ldi buff_high 0095 08D9 09 00 adcim 0 ;16-bit addition 0096 08DB 12 79 0F stm d_indexed_stm+2 ;high byte of location of first character in output string 0097 08DE 10 10 ldi 16 0098 08E0 12 66 0F stm byte_counter ;number of bytes to get, convert, and display in one line 0099 08E3 13 71 0F d_byte_loop: jmp d_indexed_ldm ;get byte from memory 0100 08E6 12 62 0F d_ldm_back: stm byte 0101 08E9 call0(byte_to_hex_pair) ;convert to hex pair 0101 08E9 0101 08E9 11 F8 08 0101 08EC 12 90 0F 0101 08EF 11 F9 08 0101 08F2 12 91 0F 0101 08F5 13 19 0E 0101 08F8 FA 08 0102 08FA 10 03 ldi 3 0103 08FC 12 67 0F stm nybble_counter 0104 08FF 11 5A 0F ldm char_pair 0105 0902 13 77 0F d_nybble_loop: jmp d_indexed_stm ;store char of byte in string buffer 0106 0905 11 78 0F d_stm_back: ldm d_indexed_stm+1 ;increment pointer by 16-bit incrementation 0107 0908 19 inc 0108 0909 12 78 0F stm d_indexed_stm+1 0109 090C 11 79 0F ldm d_indexed_stm+2 0110 090F 09 00 adcim 0 0111 0911 12 79 0F stm d_indexed_stm+2 ;pointing to next spot in buffer 0112 0914 11 67 0F ldm nybble_counter 0113 0917 1A dec ;all three characters stored (hex chars plus space)? 0114 0918 14 2E 09 jpz d_nybble_done ;yes, next byte 0115 091B 12 67 0F stm nybble_counter ;no, place next character or space 0116 091E 0A 01 subim 1 ;if nybble count = 1, put a space next 0117 0920 14 29 09 jpz d_put_space 0118 0923 11 5B 0F ldm char_pair+1 ;otherwise, get next char and store 0119 0926 13 02 09 jmp d_nybble_loop 0120 0929 10 20 d_put_space: ldi 20h ;space character 0121 092B 13 02 09 jmp d_nybble_loop 0122 092E 11 72 0F d_nybble_done: ldm d_indexed_ldm+1 ;increment memory pointer 0123 0931 19 inc 0124 0932 12 72 0F stm d_indexed_ldm+1 0125 0935 11 73 0F ldm d_indexed_ldm+2 0126 0938 09 00 adcim 0 0127 093A 12 73 0F stm d_indexed_ldm+2 0128 093D 11 66 0F ldm byte_counter 0129 0940 1A dec 0130 0941 14 4A 09 jpz d_line_done 0131 0944 12 66 0F stm byte_counter 0132 0947 13 E3 08 jmp d_byte_loop 0133 094A 10 0D d_line_done: ldi 0dh ;newline characters 0134 094C 12 D4 0F stm buffer+52 0135 094F 10 0A ldi 0ah 0136 0951 12 D5 0F stm buffer+53 0137 0954 10 00 ldi 0 0138 0956 12 D6 0F stm buffer+54 ;where the end of the line will be 0139 0959 ;Write string to screen 0140 0959 10 A0 ldi buff_low 0141 095B 12 84 0F stm ws_inst+1 0142 095E 10 0F ldi buff_high 0143 0960 12 85 0F stm ws_inst+2 0144 0963 call0(write_string) 0144 0963 0144 0963 11 72 09 0144 0966 12 90 0F 0144 0969 11 73 09 0144 096C 12 91 0F 0144 096F 13 4C 0D 0144 0972 74 09 0145 0974 0146 0974 ;Check if 16 lines done 0147 0974 11 64 0F ldm line_counter 0148 0977 1A dec 0149 0978 14 81 09 jpz d_done 0150 097B 12 64 0F stm line_counter 0151 097E 13 85 08 jmp d_line_loop 0152 0981 d_done: 0153 0981 13 31 08 error: jmp sm_warm 0154 0984 0155 0984 ;Monitor routine to jump and execute code 0156 0984 ;Gets target address from terminal 0157 0984 0158 0984 13 47 0C sm_run jmp get_address 0159 0987 11 5E 0F run_addr_back ldm address 0160 098A 12 69 0F stm run_jump+1 0161 098D 11 5F 0F ldm address+1 0162 0990 12 6A 0F stm run_jump+2 0163 0993 13 68 0F jmp run_jump 0164 0996 0165 0996 ;Routine to get hex char pairs from input and load bytes in RAM 0166 0996 ;Get address first 0167 0996 13 47 0C sm_load jmp get_address 0168 0999 11 5E 0F ld_addr_back ldm address 0169 099C 12 6C 0F stm ld_indexed_stm+1 0170 099F 11 5F 0F ldm address+1 0171 09A2 12 6D 0F stm ld_indexed_stm+2 0172 09A5 ;Get characters 0173 09A5 ;First character of pair 0174 09A5 17 03 ld_get_hi: IN 03H ;Get hi-order nybble of pair 0175 09A7 0C 02 ANDIM 02H ;check RxRDY bit 0176 09A9 14 A5 09 JPZ ld_get_hi ;not ready, loop 0177 09AC 17 02 IN 02H ;get char from data port 0178 09AE 12 60 0F STM temp ;Store character 0179 09B1 0A 0D SUBIM 0DH ;Carriage return? 0180 09B3 14 72 0A JPZ ld_done ;Yes, return to monitor 0181 09B6 17 03 ld_loop_1: IN 03H ;No, output character and validate 0182 09B8 0C 01 ANDIM 01H ;check TxRDY bit 0183 09BA 14 B6 09 JPZ ld_loop_1 ;loop if not ready 0184 09BD 11 60 0F LDM temp ;get char back 0185 09C0 18 02 OUT 02H ;send to UART for output 0186 09C2 ;Code to validate hex character 0187 09C2 0F 30 CMP 30H ;Lower limit of hex characters 0188 09C4 16 CA 09 JPC ld_next_1 ;Char >= 30H, possibly valid 0189 09C7 13 E8 09 JMP ld_invalid ;Char < 30H, invalid hex char 0190 09CA 0F 47 ld_next_1: CMP 47H ;ASCII for "G" 0191 09CC 16 E8 09 JPC ld_invalid ;Char is G or greater, invalid 0192 09CF 0F 41 CMP 41H ;ASCII for "A" 0193 09D1 16 DC 09 JPC ld_validAF_hi ;Char is valid A-F 0194 09D4 0F 3A CMP 3AH ;ASCII for ":" 0195 09D6 16 E8 09 JPC ld_invalid ;Char is ":" or greater, but < "A", invalid 0196 09D9 13 E3 09 JMP ld_valid09_hi ;Char is valid 0-9 0197 09DC 0C 0F ld_validAF_hi: ANDIM 0FH ;Mask off high bits 0198 09DE 08 09 ADDIM 9 ;Adjust ASCII to binary value 0199 09E0 13 EB 09 JMP ld_shift_hi 0200 09E3 0C 0F ld_valid09_hi: ANDIM 0FH ;Mask off high bits 0201 09E5 13 EB 09 JMP ld_shift_hi 0202 09E8 13 75 0A ld_invalid: JMP ld_error ;Invalid hex char, quit 0203 09EB 12 62 0F ld_shift_hi: STM byte ;Will eventually contain the byte to load 0204 09EE 12 60 0F STM temp ;Value to add 0205 09F1 10 10 LDI 10H ;Multiply x 16 to shift into high-order nybble 0206 09F3 12 63 0F STM counter 0207 09F6 11 63 0F ld_multloop: LDM counter 0208 09F9 1A DEC 0209 09FA 14 0C 0A JPZ ld_get_lo ;Have added 16 times, done 0210 09FD 12 63 0F STM counter 0211 0A00 11 60 0F LDM temp ;Original nybble 0212 0A03 00 62 0F ADD byte ;Add to BYTE and store 0213 0A06 12 62 0F STM byte 0214 0A09 13 F6 09 JMP ld_multloop ;Keep adding 0215 0A0C 17 03 ld_get_lo: IN 03H ;Get lo-order nybble of pair 0216 0A0E 0C 02 ANDIM 02H ;check RxRDY bit 0217 0A10 14 0C 0A JPZ ld_get_lo ;not ready, loop 0218 0A13 17 02 IN 02H ;get char from data port 0219 0A15 12 60 0F STM temp ;Store character 0220 0A18 17 03 ld_loop2: IN 03H ;Output character 0221 0A1A 0C 01 ANDIM 01H ;check TxRDY bit 0222 0A1C 14 18 0A JPZ ld_loop2 0223 0A1F 11 60 0F LDM temp ;When ready, retrieve character and output 0224 0A22 18 02 OUT 02H 0225 0A24 17 03 ld_loop3: IN 03H 0226 0A26 0C 01 ANDIM 01H 0227 0A28 14 24 0A JPZ ld_loop3 0228 0A2B 10 20 LDI 20H ;Space character 0229 0A2D 18 02 OUT 02H ;send to UART for output 0230 0A2F ;Code to validate hex character 0231 0A2F 11 60 0F LDM temp ;Retrieve character and validate 0232 0A32 0F 30 CMP 30H ;Lower limit of hex characters 0233 0A34 16 3A 0A JPC ld_next2 ;Char >= 30H, possibly valid 0234 0A37 13 E8 09 JMP ld_invalid ;Char < 30H, invalid hex char 0235 0A3A 0F 47 ld_next2: CMP 47H ;ASCII for "G" 0236 0A3C 16 E8 09 JPC ld_invalid ;Char is G or greater, invalid 0237 0A3F 0F 41 CMP 41H ;ASCII for "A" 0238 0A41 16 4C 0A JPC ld_validAF_lo ;Char is valid A-F 0239 0A44 0F 3A CMP 3AH ;ASCII for ":" 0240 0A46 16 E8 09 JPC ld_invalid ;Char is ":" or greater, but < "A", invalid 0241 0A49 13 56 0A JMP ld_valid09_lo ;Char is valid 0-9 0242 0A4C 0C 0F ld_validAF_lo: ANDIM 0FH ;Mask off high bits 0243 0A4E 08 09 ADDIM 9 ;Now lo nybble correct 0244 0A50 00 62 0F ADD byte ;Combine with hi nybble stored in BYTE 0245 0A53 13 6B 0F JMP ld_indexed_stm ;Store the byte in RAM 0246 0A56 0C 0F ld_valid09_lo: ANDIM 0FH ;Mask off high bits 0247 0A58 00 62 0F ADD byte ;Now full byte assembled 0248 0A5B 18 00 OUT 00H ;Display on LEDs 0249 0A5D 13 6B 0F JMP ld_indexed_stm ;Store the byte in RAM 0250 0A60 11 6C 0F ld_stm_back: LDM ld_indexed_stm+1 ;Increment byte pointer, lo byte first 0251 0A63 19 INC 0252 0A64 12 6C 0F STM ld_indexed_stm+1 0253 0A67 11 6D 0F LDM ld_indexed_stm+2 ;Increment hi byte if a carry occurred when lo byte incremented 0254 0A6A 09 00 ADCIM 00H 0255 0A6C 12 6D 0F STM ld_indexed_stm+2 0256 0A6F 13 A5 09 JMP ld_get_hi 0257 0A72 13 31 08 ld_done: JMP sm_warm ;Return to monitor 0258 0A75 18 00 ld_error: OUT 00H ;Display erroneous character on LEDs 0259 0A77 13 31 08 jmp sm_warm 0260 0A7A 0261 0A7A ;Monitor routine for binary load 0262 0A7A ;Gets load target address and number of bytes from terminal 0263 0A7A ;Loads bytes in RAM and returns to monitor 0264 0A7A 13 47 0C sm_bload jmp get_address 0265 0A7D 11 5E 0F bl_addr_back ldm address 0266 0A80 12 7E 0F stm bl_indexed_stm+1 0267 0A83 11 5F 0F ldm address+1 0268 0A86 12 7F 0F stm bl_indexed_stm+2 0269 0A89 0270 0A89 ;Gets number of bytes in decimal from input using get_line, called as level 0 subroutine 0271 0A89 ;Write newline 0272 0A89 11 1A 0F bl_get_bytes ldm bytes_str 0273 0A8C 12 84 0F stm ws_inst+1 0274 0A8F 11 1B 0F ldm bytes_str+1 0275 0A92 12 85 0F stm ws_inst+2 0276 0A95 call0(write_string) 0276 0A95 0276 0A95 11 A4 0A 0276 0A98 12 90 0F 0276 0A9B 11 A5 0A 0276 0A9E 12 91 0F 0276 0AA1 13 4C 0D 0276 0AA4 A6 0A 0277 0AA6 0278 0AA6 ;Get input decimal number string 0279 0AA6 call0(get_line) 0279 0AA6 0279 0AA6 11 B5 0A 0279 0AA9 12 90 0F 0279 0AAC 11 B6 0A 0279 0AAF 12 91 0F 0279 0AB2 13 F2 0C 0279 0AB5 B7 0A 0280 0AB7 0281 0AB7 ;Get word value from input string 0282 0AB7 ;No error checking for final value -- must be between 0 and 65535 (0000 and FFFF hex) 0283 0AB7 ;No error checking for numerals -- must be 0 to 9 0284 0AB7 0285 0AB7 10 00 ldi 0 ;starting value 0286 0AB9 12 50 0F stm dp_value ;zero final value variable 0287 0ABC 12 51 0F stm dp_value+1 0288 0ABF 11 57 0F dp_input ldm gl_str_len ;input string length from get_line 0289 0AC2 0F 05 cmp 5 0290 0AC4 16 DE 0A jpc dp_setup_5 0291 0AC7 0F 04 cmp 4 0292 0AC9 16 FF 0A jpc dp_setup_4 0293 0ACC 0F 03 cmp 3 0294 0ACE 16 1A 0B jpc dp_setup_3 0295 0AD1 0F 02 cmp 2 0296 0AD3 16 2F 0B jpc dp_setup_2 0297 0AD6 0F 01 cmp 1 0298 0AD8 16 3E 0B jpc dp_setup_1 0299 0ADB 13 31 08 jmp sm_warm 0300 0ADE 0301 0ADE 11 A4 0F dp_setup_5 ldm buffer+4 0302 0AE1 12 56 0F stm dp_1s 0303 0AE4 11 A3 0F ldm buffer+3 0304 0AE7 12 55 0F stm dp_10s 0305 0AEA 11 A2 0F ldm buffer+2 0306 0AED 12 54 0F stm dp_100s 0307 0AF0 11 A1 0F ldm buffer+1 0308 0AF3 12 53 0F stm dp_1000s 0309 0AF6 11 A0 0F ldm buffer 0310 0AF9 12 52 0F stm dp_10000s 0311 0AFC 13 47 0B jmp dp_10000_mult 0312 0AFF 11 A3 0F dp_setup_4 ldm buffer+3 0313 0B02 12 56 0F stm dp_1s 0314 0B05 11 A2 0F ldm buffer+2 0315 0B08 12 55 0F stm dp_10s 0316 0B0B 11 A1 0F ldm buffer+1 0317 0B0E 12 54 0F stm dp_100s 0318 0B11 11 A0 0F ldm buffer 0319 0B14 12 53 0F stm dp_1000s 0320 0B17 13 69 0B jmp dp_1000_mult 0321 0B1A 11 A2 0F dp_setup_3 ldm buffer+2 0322 0B1D 12 56 0F stm dp_1s 0323 0B20 11 A1 0F ldm buffer+1 0324 0B23 12 55 0F stm dp_10s 0325 0B26 11 A0 0F ldm buffer 0326 0B29 12 54 0F stm dp_100s 0327 0B2C 13 8B 0B jmp dp_100_mult 0328 0B2F 11 A1 0F dp_setup_2 ldm buffer+1 0329 0B32 12 56 0F stm dp_1s 0330 0B35 11 A0 0F ldm buffer 0331 0B38 12 55 0F stm dp_10s 0332 0B3B 13 AD 0B jmp dp_10_mult 0333 0B3E 11 A0 0F dp_setup_1 ldm buffer 0334 0B41 12 56 0F stm dp_1s 0335 0B44 13 CF 0B jmp dp_1_mult 0336 0B47 0337 0B47 0338 0B47 0339 0B47 ;decimal parser multiplication 0340 0B47 11 52 0F dp_10000_mult ldm dp_10000s 0341 0B4A 0A 30 subim 30h ;ASCII for '0' 0342 0B4C 14 69 0B jpz dp_10000_done 0343 0B4F 10 10 ldi 10h ;hex low byte of 10,000 decimal 0344 0B51 00 50 0F addm dp_value 0345 0B54 12 50 0F stm dp_value 0346 0B57 10 27 ldi 27h ;hex high byte of 10,000 decimal 0347 0B59 01 51 0F adcm dp_value+1 0348 0B5C 12 51 0F stm dp_value+1 0349 0B5F 11 52 0F ldm dp_10000s 0350 0B62 1A dec 0351 0B63 12 52 0F stm dp_10000s 0352 0B66 13 47 0B jmp dp_10000_mult 0353 0B69 dp_10000_done 0354 0B69 11 53 0F dp_1000_mult ldm dp_1000s 0355 0B6C 0A 30 subim 30h ;ASCII for '0' 0356 0B6E 14 8B 0B jpz dp_1000_done 0357 0B71 10 E8 ldi 0e8h ;hex low byte of 1000 decimal 0358 0B73 00 50 0F addm dp_value 0359 0B76 12 50 0F stm dp_value 0360 0B79 10 03 ldi 03h ;hex high byte of 1000 decimal 0361 0B7B 01 51 0F adcm dp_value+1 0362 0B7E 12 51 0F stm dp_value+1 0363 0B81 11 53 0F ldm dp_1000s 0364 0B84 1A dec 0365 0B85 12 53 0F stm dp_1000s 0366 0B88 13 69 0B jmp dp_1000_mult 0367 0B8B dp_1000_done 0368 0B8B 11 54 0F dp_100_mult ldm dp_100s 0369 0B8E 0A 30 subim 30h ;ASCII for '0' 0370 0B90 14 AD 0B jpz dp_100_done 0371 0B93 10 64 ldi 64h ;hex low byte of 100 decimal 0372 0B95 00 50 0F addm dp_value 0373 0B98 12 50 0F stm dp_value 0374 0B9B 10 00 ldi 00h ;hex high byte of 100 decimal 0375 0B9D 01 51 0F adcm dp_value+1 0376 0BA0 12 51 0F stm dp_value+1 0377 0BA3 11 54 0F ldm dp_100s 0378 0BA6 1A dec 0379 0BA7 12 54 0F stm dp_100s 0380 0BAA 13 8B 0B jmp dp_100_mult 0381 0BAD dp_100_done 0382 0BAD 11 55 0F dp_10_mult ldm dp_10s 0383 0BB0 0A 30 subim 30h ;ASCII for '0' 0384 0BB2 14 CF 0B jpz dp_10_done 0385 0BB5 10 0A ldi 0ah ;hex low byte of 10 decimal 0386 0BB7 00 50 0F addm dp_value 0387 0BBA 12 50 0F stm dp_value 0388 0BBD 10 00 ldi 00h ;hex high byte of 10 decimal 0389 0BBF 01 51 0F adcm dp_value+1 0390 0BC2 12 51 0F stm dp_value+1 0391 0BC5 11 55 0F ldm dp_10s 0392 0BC8 1A dec 0393 0BC9 12 55 0F stm dp_10s 0394 0BCC 13 AD 0B jmp dp_10_mult 0395 0BCF dp_10_done 0396 0BCF 11 56 0F dp_1_mult ldm dp_1s 0397 0BD2 0A 30 subim 30h ;ASCII for '0' 0398 0BD4 00 50 0F addm dp_value 0399 0BD7 12 50 0F stm dp_value 0400 0BDA 10 00 ldi 00h ;hex high byte of 100 decimal 0401 0BDC 01 51 0F adcm dp_value+1 0402 0BDF 12 51 0F stm dp_value+1 0403 0BE2 0404 0BE2 ;Set up byte counter and write ready string 0405 0BE2 11 50 0F ldm dp_value 0406 0BE5 12 58 0F stm bl_byte_counter 0407 0BE8 11 51 0F ldm dp_value+1 0408 0BEB 12 59 0F stm bl_byte_counter+1 0409 0BEE 11 34 0F ldm bl_ready_str 0410 0BF1 12 84 0F stm ws_inst+1 0411 0BF4 11 35 0F ldm bl_ready_str+1 0412 0BF7 12 85 0F stm ws_inst+2 0413 0BFA call0(write_string) 0413 0BFA 0413 0BFA 11 09 0C 0413 0BFD 12 90 0F 0413 0C00 11 0A 0C 0413 0C03 12 91 0F 0413 0C06 13 4C 0D 0413 0C09 0B 0C 0414 0C0B 0415 0C0B ;Loop to get binary data and store 0416 0C0B 17 03 bl_chk_loop: in 03h ;get status 0417 0C0D 0C 02 andim 02h ;check RxRDY 0418 0C0F 14 0B 0C jpz bl_chk_loop 0419 0C12 17 02 in 02h ;get binary from port 0420 0C14 13 7D 0F jmp bl_indexed_stm ;store in RAM 0421 0C17 11 7E 0F bl_back ldm bl_indexed_stm+1;increment pointer 0422 0C1A 19 inc 0423 0C1B 12 7E 0F stm bl_indexed_stm+1 0424 0C1E 11 7F 0F ldm bl_indexed_stm+2 0425 0C21 09 00 adcim 0 0426 0C23 12 7F 0F stm bl_indexed_stm+2 0427 0C26 11 58 0F ldm bl_byte_counter ;decrement byte counter 0428 0C29 1A dec 0429 0C2A 12 58 0F stm bl_byte_counter 0430 0C2D 11 59 0F ldm bl_byte_counter+1 0431 0C30 0B 00 sbbim 0 0432 0C32 12 59 0F stm bl_byte_counter+1 0433 0C35 14 3B 0C jpz bl_low_zero ;check if byte counter = zero 0434 0C38 13 0B 0C jmp bl_chk_loop 0435 0C3B 11 58 0F bl_low_zero ldm bl_byte_counter 0436 0C3E 14 44 0C jpz bl_done ;yes, done -- return to monitor 0437 0C41 13 0B 0C jmp bl_chk_loop ;no, get next byte 0438 0C44 13 31 08 bl_done jmp sm_warm 0439 0C47 0440 0C47 0441 0C47 0442 0C47 ;Routine to get address 0443 0C47 ;Not called as a subroutine, return jump by switch structure 0444 0C47 11 06 0F get_address ldm addr_str 0445 0C4A 12 84 0F stm ws_inst+1 0446 0C4D 11 07 0F ldm addr_str+1 0447 0C50 12 85 0F stm ws_inst+2 0448 0C53 call0(write_string) 0448 0C53 0448 0C53 11 62 0C 0448 0C56 12 90 0F 0448 0C59 11 63 0C 0448 0C5C 12 91 0F 0448 0C5F 13 4C 0D 0448 0C62 64 0C 0449 0C64 0450 0C64 ;Get hex input string for address 0451 0C64 call0(get_line) 0451 0C64 0451 0C64 11 73 0C 0451 0C67 12 90 0F 0451 0C6A 11 74 0C 0451 0C6D 12 91 0F 0451 0C70 13 F2 0C 0451 0C73 75 0C 0452 0C75 0453 0C75 ;Write newline 0454 0C75 11 96 0E ldm new_line 0455 0C78 12 84 0F stm ws_inst+1 0456 0C7B 11 97 0E ldm new_line+1 0457 0C7E 12 85 0F stm ws_inst+2 0458 0C81 call0(write_string) 0458 0C81 0458 0C81 11 90 0C 0458 0C84 12 90 0F 0458 0C87 11 91 0C 0458 0C8A 12 91 0F 0458 0C8D 13 4C 0D 0458 0C90 92 0C 0459 0C92 0460 0C92 ;No error checking for length of string -- must be exactly 4 hex characters 0461 0C92 ;Memory address stored in address variable 0462 0C92 11 A0 0F ldm buffer ;first character 0463 0C95 12 5A 0F stm char_pair 0464 0C98 11 A1 0F ldm buffer+1 ;second character 0465 0C9B 12 5B 0F stm char_pair+1 0466 0C9E call1(hex_pair_to_byte) 0466 0C9E 0466 0C9E 11 AD 0C 0466 0CA1 12 93 0F 0466 0CA4 11 AE 0C 0466 0CA7 12 94 0F 0466 0CAA 13 B9 0D 0466 0CAD AF 0C 0467 0CAF 16 31 08 jpc sm_warm ;non-hex character detected, quit 0468 0CB2 12 5F 0F stm address+1 ;high byte of address 0469 0CB5 11 A2 0F ldm buffer+2 ;third character 0470 0CB8 12 5A 0F stm char_pair 0471 0CBB 11 A3 0F ldm buffer+3 ;fourth character 0472 0CBE 12 5B 0F stm char_pair+1 0473 0CC1 call1(hex_pair_to_byte) 0473 0CC1 0473 0CC1 11 D0 0C 0473 0CC4 12 93 0F 0473 0CC7 11 D1 0C 0473 0CCA 12 94 0F 0473 0CCD 13 B9 0D 0473 0CD0 D2 0C 0474 0CD2 16 31 08 jpc sm_warm ;non-hex character detected, quit 0475 0CD5 12 5E 0F stm address ;low byte of address 0476 0CD8 ;Switch for return jumps 0477 0CD8 11 61 0F ldm choice 0478 0CDB 0F 35 cmp '5' 0479 0CDD 16 7D 0A jpc bl_addr_back 0480 0CE0 0F 34 cmp '4' 0481 0CE2 16 99 09 jpc ld_addr_back 0482 0CE5 0F 33 cmp '3' 0483 0CE7 16 87 09 jpc run_addr_back 0484 0CEA 0F 32 cmp '2' 0485 0CEC 16 74 08 jpc d_addr_back 0486 0CEF 13 31 08 jmp sm_warm 0487 0CF2 0488 0CF2 ;Get_line subroutine, call as level 0 0489 0CF2 ;Gets a line from input, puts zero-terminated string in buffer 0490 0CF2 ;Echos characters to screen, except terminating carriage return 0491 0CF2 ;Address of buffer in buff_low and buff_high constants 0492 0CF2 ;Uses RAM variable address instruction gl_indexed_stm 0493 0CF2 ;length of input string returned in gl_str_len 0494 0CF2 ;Returns when carriage return entered 0495 0CF2 0496 0CF2 10 00 get_line: ldi 0 0497 0CF4 12 57 0F stm gl_str_len ;string length 0498 0CF7 10 A0 ldi buff_low ;low byte of buffer address 0499 0CF9 12 8A 0F stm gl_indexed_stm+1 0500 0CFC 10 0F ldi buff_high ;high byte of buffer address 0501 0CFE 12 8B 0F stm gl_indexed_stm+2 0502 0D01 17 03 gl_chk_loop: in 03h ;get status 0503 0D03 0C 02 andim 02h ;check RxRDY 0504 0D05 14 01 0D jpz gl_chk_loop 0505 0D08 17 02 in 02h ;get char from port 0506 0D0A 12 60 0F stm temp ;save character 0507 0D0D 0A 0D subim 0dh ;is it a return character? 0508 0D0F 14 1F 0D jpz gl_end_of_line ;yes, replace with a zero 0509 0D12 11 57 0F ldm gl_str_len ;no, increment string length 0510 0D15 19 inc 0511 0D16 12 57 0F stm gl_str_len 0512 0D19 11 60 0F ldm temp ;get back char 0513 0D1C 13 22 0D jmp gl_store_it ;place character in buffer 0514 0D1F 12 60 0F gl_end_of_line: stm temp ;place zero in temp 0515 0D22 13 89 0F gl_store_it: jmp gl_indexed_stm ;store character in buffer 0516 0D25 11 60 0F gl_back: ldm temp ;check if end-of-line (temp = 0) 0517 0D28 14 49 0D jpz gl_done ;yes, quit 0518 0D2B 17 03 gl_out_loop: in 03h ;no, send char to screen 0519 0D2D 0C 01 andim 01h ;check TxRDY 0520 0D2F 14 2B 0D jpz gl_out_loop ;loop if not ready 0521 0D32 11 60 0F ldm temp 0522 0D35 18 02 out 02h ;output character to port 0523 0D37 11 8A 0F ldm gl_indexed_stm+1 ;increment indexing pointer 0524 0D3A 19 inc 0525 0D3B 12 8A 0F stm gl_indexed_stm+1 0526 0D3E 11 8B 0F ldm gl_indexed_stm+2 0527 0D41 09 00 adcim 00h ;16-bit addition 0528 0D43 12 8B 0F stm gl_indexed_stm+2 0529 0D46 13 01 0D jmp gl_chk_loop 0530 0D49 gl_done: ret0 0530 0D49 13 8F 0F 0531 0D4C 0532 0D4C ;Write_string subroutine, call as level 0 0533 0D4C ;Writes a zero-terminated string to screen at current cursor location 0534 0D4C ;Must set up address of string to be written in ws_inst+1 and ws_inst+2 0535 0D4C write_string: 0536 0D4C 17 03 ws_chk_loop: in 03h ;get status 0537 0D4E 0C 01 andim 01h ;check TxRDY 0538 0D50 14 4C 0D jpz ws_chk_loop 0539 0D53 13 83 0F jmp ws_inst ;get a character when port ready 0540 0D56 14 6D 0D ws_back: jpz ws_done ;quit if end-of-string 0541 0D59 18 02 out 02h ;output character to port 0542 0D5B 11 84 0F ldm ws_inst+1 ;indexing pointer 0543 0D5E 19 inc 0544 0D5F 12 84 0F stm ws_inst+1 0545 0D62 11 85 0F ldm ws_inst+2 0546 0D65 09 00 adcim 00h ;16-bit addition 0547 0D67 12 85 0F stm ws_inst+2 0548 0D6A 13 4C 0D jmp ws_chk_loop 0549 0D6D ws_done: ret0 0549 0D6D 13 8F 0F 0550 0D70 0551 0D70 ;Subroutine hex_to word -- call as level 0 0552 0D70 ;Calls hex_pair_to_byte as level 1 0553 0D70 ;Get 16-bit word value from input string in buffer 0554 0D70 ;No error checking for length of string -- must be exactly 4 hex characters 0555 0D70 ;16-bit value placed in h2w_value 0556 0D70 11 A0 0F hex_to_word: ldm buffer ;first character 0557 0D73 12 5A 0F stm char_pair 0558 0D76 11 A1 0F ldm buffer+1 ;second character 0559 0D79 12 5B 0F stm char_pair+1 0560 0D7C call1(hex_pair_to_byte) ;high-order byte 0560 0D7C 0560 0D7C 11 8B 0D 0560 0D7F 12 93 0F 0560 0D82 11 8C 0D 0560 0D85 12 94 0F 0560 0D88 13 B9 0D 0560 0D8B 8D 0D 0561 0D8D 16 B6 0D jpc h2w_done ;non-hex character detected, exit with carry set 0562 0D90 12 5D 0F stm h2w_value+1 ;high byte of address 0563 0D93 11 A2 0F ldm buffer+2 ;third character 0564 0D96 12 5A 0F stm char_pair 0565 0D99 11 A3 0F ldm buffer+3 ;fourth character 0566 0D9C 12 5B 0F stm char_pair+1 0567 0D9F call1(hex_pair_to_byte) ;low-order byte 0567 0D9F 0567 0D9F 11 AE 0D 0567 0DA2 12 93 0F 0567 0DA5 11 AF 0D 0567 0DA8 12 94 0F 0567 0DAB 13 B9 0D 0567 0DAE B0 0D 0568 0DB0 16 B6 0D jpc h2w_done ;exit with carry set if error 0569 0DB3 12 5C 0F stm h2w_value ;low byte of address 0570 0DB6 h2w_done ret0 0570 0DB6 13 8F 0F 0571 0DB9 0572 0DB9 ;Subroutine to convert hex character pair to byte, call as level 1 0573 0DB9 ;Character pair in memory location char_pair, stored hi-low 0574 0DB9 ;Returns with byte in accumulator and carry flag clear if no error 0575 0DB9 ;Returns with character in accumulator and carry flag set if error 0576 0DB9 ;Calls char_to_nybble as level 2 subroutine 0577 0DB9 11 5A 0F hex_pair_to_byte: ldm char_pair ;high order character of pair 0578 0DBC 12 60 0F stm temp ;char_to_nybble needs char in TEMP 0579 0DBF call2(char_to_nybble) 0579 0DBF 0579 0DBF 11 CE 0D 0579 0DC2 12 96 0F 0579 0DC5 11 CF 0D 0579 0DC8 12 97 0F 0579 0DCB 13 64 0E 0579 0DCE D0 0D 0580 0DD0 16 15 0E jpc c2n_error 0581 0DD3 12 62 0F STM byte ;Will eventually contain the byte to load 0582 0DD6 12 60 0F STM temp ;Value to add 0583 0DD9 10 10 LDI 10H ;Multiply x 16 to shift into high-order nybble 0584 0DDB 12 63 0F STM counter 0585 0DDE 11 63 0F MULTLOOP: LDM counter 0586 0DE1 1A DEC 0587 0DE2 14 F4 0D JPZ GET_LO ;Have added 16 times, done 0588 0DE5 12 63 0F STM counter 0589 0DE8 11 60 0F LDM temp ;Original nybble 0590 0DEB 00 62 0F ADD byte ;Add to BYTE and store 0591 0DEE 12 62 0F STM byte 0592 0DF1 13 DE 0D JMP MULTLOOP ;Keep adding 0593 0DF4 11 5B 0F GET_LO: ldm char_pair+1 0594 0DF7 12 60 0F stm temp 0595 0DFA call2(char_to_nybble) 0595 0DFA 0595 0DFA 11 09 0E 0595 0DFD 12 96 0F 0595 0E00 11 0A 0E 0595 0E03 12 97 0F 0595 0E06 13 64 0E 0595 0E09 0B 0E 0596 0E0B 16 15 0E jpc c2n_error 0597 0E0E 00 62 0F ADD byte ;Combine with hi nybble stored in BYTE 0598 0E11 1C ccf ;in case addition changed it 0599 0E12 13 16 0E JMP c2b_done ;Done, no error 0600 0E15 1B c2n_error: scf 0601 0E16 c2b_done: ret1 0601 0E16 13 92 0F 0602 0E19 0603 0E19 ;Subroutine to convert byte to hex character pair, call as level 0 0604 0E19 ;Gets byte from byte variable 0605 0E19 ;Returns with character pair in memory location char_pair, stored hi-low 0606 0E19 ; 0607 0E19 byte_to_hex_pair: 0608 0E19 11 62 0F ldm byte 0609 0E1C 0C F0 andim 0f0h ;dealing with high nybble 0610 0E1E 12 60 0F stm temp 0611 0E21 10 00 ldi 00h ;prepare to shift down (divide by 16) 0612 0E23 12 63 0F stm counter 0613 0E26 11 60 0F b2h_divide: ldm temp 0614 0E29 0A 10 subim 16 0615 0E2B 16 3B 0E jpc b2h_cont ;continue if nybble >=0 0616 0E2E 11 63 0F ldm counter ;hi-nybble now in low position 0617 0E31 0F 0A cmp 10 ;is value <10? 0618 0E33 16 48 0E jpc b2h_hi_A2F ;yes, jump and convert to char 0619 0E36 08 30 addim 30h ;no, convert to char 0620 0E38 13 4A 0E jmp b2h_store_hi 0621 0E3B 12 60 0F b2h_cont: stm temp 0622 0E3E 11 63 0F ldm counter 0623 0E41 19 inc 0624 0E42 12 63 0F stm counter 0625 0E45 13 26 0E jmp b2h_divide 0626 0E48 08 37 b2h_hi_A2F: addim 37h 0627 0E4A 12 5A 0F b2h_store_hi: stm char_pair ;hi-order hex char 0628 0E4D 11 62 0F ldm byte 0629 0E50 0C 0F andim 0fh ;dealing with low-order nybble 0630 0E52 0F 0A cmp 10 ;is value <10? 0631 0E54 16 5C 0E jpc b2h_lo_A2F ;yes, jump and convert to char 0632 0E57 08 30 addim 30h ;no, convert to char 0633 0E59 13 5E 0E jmp b2h_store_lo 0634 0E5C 08 37 b2h_lo_A2F: addim 37h 0635 0E5E 12 5B 0F b2h_store_lo: stm char_pair+1 ;now char pair is in variable 0636 0E61 ret0 0636 0E61 13 8F 0F 0637 0E64 0638 0E64 0639 0E64 ;Subroutine to convert hex char to nybble, call as level 2 0640 0E64 ;Checks for validity of char, 0-9 and A-F (upper case only) 0641 0E64 ;Carry flag set on exit if error 0642 0E64 ;Carry flag clear if character valid 0643 0E64 ;Call with char in temp 0644 0E64 ;Exits with nybble in lower half of accumulator if no error 0645 0E64 ;Original character in accumulator if error 0646 0E64 0647 0E64 11 60 0F char_to_nybble: ldm temp ;Get character 0648 0E67 0F 30 cmp 30H ;Lower limit of hex characters 0649 0E69 16 6F 0E jpc c2n_next ;Char >= 30H, possibly valid 0650 0E6C 13 8F 0E jmp invalid ;Char < 30H, invalid hex char 0651 0E6F 0F 47 c2n_next: cmp 47h ;ASCII for "G" 0652 0E71 16 8F 0E jpc invalid ;Char is G or greater, invalid 0653 0E74 0F 41 cmp 41h ;ASCII for "A" 0654 0E76 16 81 0E jpc validAF ;Char is valid A-F 0655 0E79 0F 3A cmp 3Ah ;ASCII for ":" 0656 0E7B 16 8F 0E jpc invalid ;Char is ":" or greater, but < "A", invalid 0657 0E7E 13 89 0E jmp valid09 ;Char is valid 0-9 0658 0E81 0C 0F validAF: andim 0fh ;Mask off high bits 0659 0E83 08 09 addim 9 ;Adjust ASCII to binary value 0660 0E85 1C ccf ;exit no error 0661 0E86 ret2 0661 0E86 13 95 0F 0662 0E89 0C 0F valid09: andim 0fh ;Mask off high bits 0663 0E8B 1C ccf ;exit no error 0664 0E8C ret2 0664 0E8C 13 95 0F 0665 0E8F 11 60 0F invalid: ldm temp ;put char in accumulator 0666 0E92 1B scf ;Set carry flag 0667 0E93 ret2 0667 0E93 13 95 0F 0668 0E96 ;String constants 0669 0E96 98 0E new_line .dw $+2 0670 0E98 0D 0A 00 .db 0dh,0ah,0 0671 0E9B 9D 0E sm_greeting: .dw $+2 0672 0E9D 0D 0A .db 0dh,0ah 0673 0E9F 43505576696C .text "CPUville 8-bit processor system monitor v.1" 0673 0EA5 6C6520382D6269742070726F636573736F722073797374656D206D6F6E69746F7220762E31 0674 0ECA 0D 0A 00 .db 0dh,0ah,0 0675 0ECD CF 0E sm_prompt .dw $+2 0676 0ECF 0D 0A .db 0dh,0ah 0677 0ED1 456E74657220 .text "Enter number: 1=restart 2=dump 3=run 4=load 5=bload " 0677 0ED7 6E756D6265723A20313D7265737461727420323D64756D7020333D72756E20343D6C6F616420353D626C6F616420 0678 0F05 00 .db 0 0679 0F06 08 0F addr_str .dw $+2 0680 0F08 0D 0A .db 0dh,0ah 0681 0F0A 416464726573 .text Address (hex): 0681 0F10 732028686578293A20 0682 0F19 00 .db 0 0683 0F1A 1C 0F bytes_str .dw $+2 0684 0F1C 0D 0A .db 0dh,0ah 0685 0F1E 427974657320 .text Bytes to load (dec): 0685 0F24 746F206C6F61642028646563293A20 0686 0F33 00 .db 0 0687 0F34 36 0F bl_ready_str .dw $+2 0688 0F36 0D 0A .db 0dh,0ah 0689 0F38 52656164792C .text Ready, start transfer 0689 0F3E 207374617274207472616E73666572 0690 0F4D 0D 0A 00 .db 0dh,0ah,0 0691 0F50 0692 0F50 ;RAM Variables 0693 0F50 00 00 dp_value .dw 0000h 0694 0F52 00 dp_10000s .db 00h 0695 0F53 00 dp_1000s .db 00h 0696 0F54 00 dp_100s .db 00h 0697 0F55 00 dp_10s .db 00h 0698 0F56 00 dp_1s .db 00h 0699 0F57 00 gl_str_len .db 00h 0700 0F58 00 00 bl_byte_counter .dw 0000h 0701 0F5A 00 00 char_pair .dw 0000h 0702 0F5C 00 00 h2w_value .dw 0000h 0703 0F5E 00 00 address .dw 0000h 0704 0F60 00 temp .db 00h 0705 0F61 00 choice .db 00h 0706 0F62 00 byte .db 00h 0707 0F63 00 counter .db 00h 0708 0F64 00 line_counter .db 00h 0709 0F65 00 char_count .db 00h 0710 0F66 00 byte_counter .db 00h 0711 0F67 00 nybble_counter .db 00h 0712 0F68 0713 0F68 ;RAM instructions with variable address (must initialize opcode when monitor is in ROM) 0714 0F68 ;Jump instruction for run routine, must be in RAM 0715 0F68 13 00 00 run_jump jmp 0000h 0716 0F6B ;Indexed load for load routine, must be in RAM 0717 0F6B 12 00 00 ld_indexed_stm stm 0000h 0718 0F6E 13 60 0A jmp ld_stm_back 0719 0F71 ;Indexed load and store instructions for dump, must be in RAM 0720 0F71 11 00 00 d_indexed_ldm ldm 0000h 0721 0F74 13 E6 08 jmp d_ldm_back 0722 0F77 12 00 00 d_indexed_stm stm 0000h 0723 0F7A 13 05 09 jmp d_stm_back 0724 0F7D ;Indexed store instruction for binary loader, must be in RAM 0725 0F7D 12 00 00 bl_indexed_stm: stm 0000h 0726 0F80 13 17 0C jmp bl_back 0727 0F83 ;Indexed load instruction for write_string, must be in RAM 0728 0F83 11 00 00 ws_inst: ldm 0000h 0729 0F86 13 56 0D jmp ws_back 0730 0F89 ;Indexed store instruction for get_line, must be in RAM 0731 0F89 12 00 00 gl_indexed_stm: stm 0000h 0732 0F8C 13 25 0D jmp gl_back 0733 0F8F ;Return instruction for level 0 call macros, must be in RAM 0734 0F8F 13 00 00 return_jump0: jmp 0000h 0735 0F92 ;Return instruction for level 1 call macros, must be in RAM 0736 0F92 13 00 00 return_jump1: jmp 0000h 0737 0F95 ;Return instruction for level 2 call macros, must be in RAM 0738 0F95 13 00 00 return_jump2: jmp 0000h 0739 0F98 0740 0F98 return: .set 0810h ;assembler needs variable label set back to original value 0741 0F98 .end 0742 0F98 0743 0F98 0744 0F98 0745 0F98 0746 0F98 0747 0F98 0748 0F98 tasm: Number of errors = 0