0001 * HEX RPN Calculator 0002 * The calculator has only 2 functions: addition and subtraction 0003 * The user enters lines with operands and operators terminated 0004 * with a CR. Operands can have up to four HEX digits. 0005 * An empty line causes a return to the monitor. 0006 * The calculator uses reverse Polish notation 0007 * example: input: 1 FFFF 3210++ 0008 * output: TOS=3210 ; TOS=Top of Stack 0009 0010 * Declaration of constants: 0011 0012 * BUFFALO subroutines 0013 ffb8 outa equ $ffb8 output the ASCII character in A 0014 ffca outstrg equ $ffca output string at x ; string is terminated by $04 0015 ffc4 outcrlf equ $ffc4 output crlf 0016 ffb2 outlhlf equ $ffb2 output left nibble of a in ASCII 0017 ffb5 outrhlf equ $ffb5 output right nibble of a in ASCII 0018 ffc1 out2bsp equ $ffc1 output 2byte value at x in HEX 0019 ffac input equ $ffac a=input() ; a=0 if no char entered 0020 ffcd inchar equ $ffcd a=input() ; loop till user enters char 0021 ffa0 upcase equ $ffa0 a=upcase(a) 0022 ffa3 wchek equ $FFA3 z=1 if A={space,comma,tab} 0023 ffa6 dchek equ $FFA6 z=1 if A={space,comma,tab,CR} 0024 0025 * ASCII control codes 0026 000d cr equ $0d carriage return 0027 000a lf equ $0a line feed 0028 007f del equ $7f delete 0029 0004 eot equ $04 eot ; end of text 0030 0008 bsp equ $08 back space 0031 0032 c000 ORG $C000 0033 OPT s 0034 0035 * 0036 * Main Program 0037 * 0038 c000 org $C000 0039 0040 c000 ce c0 fb [ 3 ] ldx #headst point to header string 0041 c003 bd ff ca [ 6 ] jsr outstrg output header 0042 c006 18 ce c2 fe [ 4 ] ldy #ustack initialize user operand stack (16bit values) 0043 c00a ce c3 02 [ 3 ] loop ldx #buffer x points to start of input buffer 0044 c00d bd c0 2c [ 6 ] jsr getinp get input line from terminal into buffer 0045 c010 8c c3 02 [ 4 ] cmpx #buffer input buffer empty? 0046 c013 27 16 [ 3 ] beq quit 0047 c015 ce c3 02 [ 3 ] ldx #buffer point to first char in buffer 0048 c018 bd c0 56 [ 6 ] conv jsr convert convert input ASCI to binary 0049 c01b 81 0d [ 2 ] cmpa #cr end of input line? 0050 c01d 27 07 [ 3 ] beq disp 0051 c01f bd c0 99 [ 6 ] jsr operate do operation 0052 c022 81 0d [ 2 ] cmpa #cr end of input line? 0053 c024 26 f2 [ 3 ] bne conv 0054 c026 bd c0 e7 [ 6 ] disp jsr out else, output result and prompt 0055 c029 20 df [ 3 ] bra loop 0056 c02b 3f [14 ] quit swi 0057 0058 * 0059 * 0060 * Subroutine getinput 0061 * gets characters from input device, converts them to upper case 0062 * and puts them into the input buffer till end of buffer or CR 0063 * recognizes back space and delete characters 0064 * returns: x ; pointer to end of command line buffer 0065 * a ; last character read = CR 0066 * modifies flags 0067 0068 c02c ce c3 02 [ 3 ] getinp ldx #buffer set input buffer pointer 0069 c02f bd ff cd [ 6 ] iloop jsr inchar input loop 0070 c032 81 0a [ 2 ] cmpa #lf line feed? 0071 c034 27 f9 [ 3 ] beq iloop ignore lf's 0072 c036 81 7f [ 2 ] cmpa #del delete? 0073 c038 26 0c [ 3 ] bne case 0074 c03a 81 08 [ 2 ] cmpa #bsp back space? 0075 c03c 26 08 [ 3 ] bne case 0076 c03e 09 [ 3 ] dex 0077 c03f 8c c3 02 [ 4 ] cpx #buffer past begining of buffer? 0078 c042 27 e8 [ 3 ] beq getinp 0079 c044 20 e9 [ 3 ] bra iloop 0080 c046 bd ff a0 [ 6 ] case jsr upcase 0081 c049 a7 00 [ 4 ] store staa 0,x store character 0082 c04b 81 0d [ 2 ] cmpa #cr end of input line? 0083 c04d 27 06 [ 3 ] beq idone 0084 c04f 08 [ 3 ] inx point to next char 0085 c050 8c c3 52 [ 4 ] cpx #endb buffer full? 0086 c053 26 da [ 3 ] bne iloop 0087 c055 39 [ 5 ] idone rts 0088 0089 0090 * Subroutine convert 0091 * checks the next character in the input buffer for an ASCII HEX digit 0092 * if a digit is found the the ASCII HEX digit string with up to four 0093 * digits is converted to a binary number and pushed onto the user stack. 0094 * argument: x = pointer to last character in input buffer 0095 * y = pointer to user stack 0096 * returns : a = pointer to last nodigit character processed 0097 * modifies: b,flags 0098 * 0099 c056 cc 00 00 [ 3 ] convert ldd #0 0100 c059 18 ed 00 [ 6 ] std 0,Y clear top of user operand stack 0101 c05c 7f c0 98 [ 6 ] clr digit 0102 c05f a6 00 [ 4 ] getop ldaa 0,X load next character from input buffer 0103 c061 80 30 [ 2 ] suba #'0 hex digit? 0104 c063 2b 21 [ 3 ] bmi nodigit 0105 c065 81 09 [ 2 ] cmpa #9 digit 0-9? 0106 c067 23 06 [ 3 ] bls isdigit 0107 c069 80 07 [ 2 ] suba #7 convert hex A-F to binary 0108 c06b 81 0f [ 2 ] cmpa #$0F hex digit? 0109 c06d 2e 17 [ 3 ] bgt nodigit 0110 c06f a7 00 [ 4 ] isdigit staa 0,X save digit 0111 c071 7c c0 98 [ 6 ] inc digit 0112 c074 18 ec 00 [ 6 ] ldd 0,Y load current operand 0113 c077 05 [ 3 ] asld 0114 c078 05 [ 3 ] asld 0115 c079 05 [ 3 ] asld 0116 c07a 05 [ 3 ] asld 4bit shift 0117 c07b eb 00 [ 4 ] addb 0,X add digit 0118 c07d 18 ed 00 [ 6 ] std 0,Y update operand 0119 c080 08 [ 3 ] inx 0120 c081 8c c3 52 [ 4 ] cpx #endb end of buffer? 0121 c084 26 d9 [ 3 ] bne getop 0122 c086 b6 c0 98 [ 4 ] nodigit ldaa digit was a number encountered? 0123 c089 27 0a [ 3 ] beq nooper 0124 c08b 18 09 [ 4 ] dey accept number as new TOS 0125 c08d 18 09 [ 4 ] dey decrement operand stack pointer 0126 c08f 18 8c c2 00 [ 5 ] cpy #eustack user stack overflow? 0127 c093 2f 96 [ 3 ] ble quit 0128 c095 a6 00 [ 4 ] nooper ldaa 0,X a = next char (no digit) 0129 c097 39 [ 5 ] rts 0130 0131 c098 00 digit fcb 0 0132 0133 * Subroutine operate 0134 * performs an add or subtract between the operand on TOS+2 and 0135 * the operand TOS+4 if the character in A is in {+,-} and loads 0136 * the next character from the input buffer. 0137 * An error message is printed if 0138 * -an add or subtract overflow occurred 0139 * -if an unknown operator is encountered 0140 * argument: a = current input char from buffer 0141 * x = pointer to last character in input buffer 0142 * y = pointer to user stack TOS-2 0143 * result: The two operand of an add or subtract are poped 0144 * from the stack and the result is pushed onto the 0145 * user stack. 0146 * y points to TOS-2. 0147 * a next char from input line 0148 * modifies: b,flags 0149 0150 c099 bd ff a6 [ 6 ] operate jsr dchek is char white space? 0151 c09c 27 34 [ 3 ] beq endoper 0152 c09e 81 2b [ 2 ] cmpa #'+ is operator = + ? 0153 c0a0 26 17 [ 3 ] bne tsub 0154 c0a2 18 8c c2 fc [ 5 ] add cpy #ustack-2 user stack underflow? 0155 c0a6 24 33 [ 3 ] bhs stackuf 0156 c0a8 18 ec 02 [ 6 ] ldd 2,Y load TOS+2 0157 c0ab 18 e3 04 [ 7 ] addd 4,Y add TOS+4 0158 c0ae 29 26 [ 3 ] bvs overfl 0159 c0b0 18 08 [ 4 ] iny POP 0160 c0b2 18 08 [ 4 ] iny 0161 c0b4 18 ed 02 [ 6 ] std 2,Y put result on new TOS stack 0162 c0b7 20 19 [ 3 ] bra endoper 0163 c0b9 81 2d [ 2 ] tsub cmpa #'- is operator = - ? 0164 c0bb 26 23 [ 3 ] bne error 0165 c0bd 18 8c c2 fc [ 5 ] sub cpy #ustack-2 user stack underflow? 0166 c0c1 24 18 [ 3 ] bhs stackuf 0167 c0c3 18 ec 04 [ 6 ] ldd 4,Y load TOS+4 0168 c0c6 18 a3 02 [ 7 ] subd 2,Y subtract TOS+2 0169 c0c9 29 0b [ 3 ] bvs overfl 0170 c0cb 18 08 [ 4 ] iny POP 0171 c0cd 18 08 [ 4 ] iny 0172 c0cf 18 ed 02 [ 6 ] std 2,Y put result on stack 0173 c0d2 08 [ 3 ] endoper inx 0174 c0d3 a6 00 [ 4 ] ldaa 0,X 0175 c0d5 39 [ 5 ] rts 0176 0177 * print error message and return to monitor 0178 * 0179 c0d6 ce c1 2e [ 3 ] overfl ldx #ovmsg load pointer to overflow msg 0180 c0d9 20 08 [ 3 ] bra printm 0181 c0db ce c1 3b [ 3 ] stackuf ldx #stackum load pointer to stack overflow msg 0182 c0de 20 03 [ 3 ] bra printm 0183 c0e0 ce c1 19 [ 3 ] error ldx #emsg load pointer to error message 0184 c0e3 bd ff ca [ 6 ] printm jsr outstrg print error message 0185 c0e6 3f [14 ] swi 0186 0187 * Subroutine output 0188 * displays the TOS and prompts user for input 0189 * arguments: y points to TOS-2 0190 * modifies : a,x,flags 0191 * 0192 c0e7 ce c1 14 [ 3 ] out ldx #prompt 0193 c0ea bd ff ca [ 6 ] jsr outstrg ;output prompt 0194 c0ed 18 3c [ 5 ] pshy 0195 c0ef 38 [ 5 ] pulx 0196 c0f0 08 [ 3 ] inx 0197 c0f1 08 [ 3 ] inx x points to TOS 0198 c0f2 bd ff c1 [ 6 ] jsr out2bsp ;output TOS 0199 c0f5 86 3e [ 2 ] ldaa #'> 0200 c0f7 bd ff b8 [ 6 ] jsr outa 0201 c0fa 39 [ 5 ] rts 0202 0203 0204 * Definition of strings 0205 * 0206 0207 c0fb 43 4d 4c 20 48 45 headst fcc 'CML HEX RPN CALCULATOR' 58 20 52 50 4e 20 43 41 4c 43 55 4c 41 54 4f 52 0208 c111 0d 0a 04 fcb cr,lf,eot 0209 0210 c114 54 4f 53 3d prompt fcc 'TOS=' 0211 c118 04 fcb eot 0212 0213 c119 0d 0a emsg fcb cr,lf 0214 c11b 55 4e 4b 4e 4f 57 fcc 'UNKNOWN OPERATOR' 4e 20 4f 50 45 52 41 54 4f 52 0215 c12b 0d 0a 04 fcb cr,lf,eot 0216 0217 c12e 0d 0a ovmsg fcb cr,lf 0218 c130 4f 56 45 52 46 4c fcc 'OVERFLOW' 4f 57 0219 c138 0d 0a 04 fcb cr,lf,eot 0220 0221 c13b 0d 0a stackum fcb cr,lf 0222 c13d 4f 50 45 52 41 4e fcc 'OPERAND STACK UNDERFLOW' 44 20 53 54 41 43 4b 20 55 4e 44 45 52 46 4c 4f 57 0223 c154 0d 0a 04 fcb cr,lf,eot 0224 0225 0226 * Declaration of buffer and operand stack 0227 0228 c200 org $c200 0229 c200 eustack rmb 254 16bit operand stack 0230 c2fe ustack equ * 0231 c2fe 00 00 00 00 fcb 0,0,0,0 initial TOS,TOS-2 0232 c302 buffer rmb 80 input line buffer 0233 c352 endb equ * 0234 0235 df00 org $df00 0236 df00 31 20 46 fcc '1 F' 0237 df03 7f fcb del 0238 df04 33 32 31 30 fcc '3210' 0239 df08 0d 0a fcb cr,lf 0240 df0a 2b 2b fcc '++' 0241 df0c 7f 0d 0a fcb del,cr,lf 0242 df0f 31 20 46 46 46 46 fcc '1 FFFF 3210++' 20 33 32 31 30 2b 2b 0243 df1c 0d 0a fcb cr,lf 0244 df1e 30 20 61 62 63 64 fcc '0 abcd +' 20 2b 0245 df26 0d 0a fcb cr,lf 0246 df28 61 62 63 64 20 20 fcc 'abcd -' 2d 0247 df2f 0d 0a fcb cr,lf 0248 df31 30 20 31 20 2d fcc '0 1 -' 0249 df36 0d 0a fcb cr,lf 0250 df38 0d 0a fcb cr,lf add c0a2 bsp 0008 buffer c302 case c046 conv c018 convert c056 cr 000d dchek ffa6 del 007f digit c098 disp c026 emsg c119 endb c352 endoper c0d2 eot 0004 error c0e0 eustack c200 getinp c02c getop c05f headst c0fb idone c055 iloop c02f inchar ffcd input ffac isdigit c06f lf 000a loop c00a nodigit c086 nooper c095 operate c099 out c0e7 out2bsp ffc1 outa ffb8 outcrlf ffc4 outlhlf ffb2 outrhlf ffb5 outstrg ffca overfl c0d6 ovmsg c12e printm c0e3 prompt c114 quit c02b stackuf c0db stackum c13b store c049 sub c0bd tsub c0b9 upcase ffa0 ustack c2fe wchek ffa3