******************************************************************************** * Name: David DiPaola * * File: program3.asm * * Due Date: 5/7/2009 11:00pm * * Description: This program prompts the user for decimal integers, stopping * when the user presses the return key after entering nothing. As the * user enters values, this program computes the total using postfix * notation. If the user presses a key that is neither a number nor a * valid mathematical symbol, the program will give the user an error * message. An error will also be displayed when the user's total exceeds * 65535. After displaying errors, the program will re-prompt. * * Input: The user enters integers via a text prompt displayed in a * serial terminal. The total is checked to determine if it can be * represented in two bytes, if it cannot, an error is passed to * the user who must then enter a new expression. If the user enters * characters which are not 0-9, +, -, /, or * then the program will * also give an error and the user will be able to type in a new * expression. * * (Note: negative numbers are not allowed, and use of a hyphen or * the minus sign will result in an iaccurate calculation) * * Output: The result of the summation is displayed for the user in the * serial terminal readout. * * Errors: There are two possible errors: * * If the user enters values which cannot be represented in two * bytes, they will be given an error, the erroneous expression will be * thrown away, and the user will be asked to enter a new one. * * If the user types a character which is not numerical nor a * valid mathematical operation (+ - * /) into the terminal, then an * error will be displayed and the user will be given another prompt in * which they can enter a new expression. ******************************************************************************** ********** Equates ************************* ZERO EQU $0000 ;ZERO is a symbol for $00 STACK_S EQU $2000 ;Stack space starts here GETCHAR EQU $EE84 ;This is where we jump to to get to GETCHAR PUTCHAR EQU $EE86 ;This is where we jump to to get to PUTCHAR PRINTF EQU $EE88 ;This is where we jump to to get to PRINTF CR EQU $000D ;Carraige return LF EQU $000A ;Line feed A_TO_D EQU $0030 ;Converts ASCII to decimal PLUS EQU $002B ;The "+" sign MINUS EQU $002D ;The "-" sign MULT EQU $002A ;The "*" sign DIVIDE EQU $002F ;The "/" sign U_BND EQU $0039 ;Upper character bound (inclusive) L_BND EQU $002A ;Lower character bound (inclusive) IN_1 EQU $002C ;First invalid character in the range IN_2 EQU $002E ;Second invalid character in the range NU_BND EQU $0039 ;Upper number bound (inclusive) NL_BND EQU $0030 ;Lower number bound (inclusive) CRF_SET EQU $00FF ;Character flag set value CRF_RST EQU $0000 ;Character flag reset value ********** Variable Declarations *********** ORG $3000 ;These are our prompt and result strings prompt DB CR,LF,"Enter an expression to evaluate",CR,LF,0 result DB CR,LF,"The answer is %u",0 ic_err DB CR,LF,"Error: Invalid character",0 ov_err DB CR,LF,"Error: Overflow",0 total DW $0000 ;The running total temp DW $0000 ;Temporary area for IDIVS crflag DW CRF_RST ;Character flag, it's set when the user enters something ********** Main **************************** ORG $3100 ;Starting address LDS #STACK_S ;Set the stack pointer to our stack space ******************************************** * ASK * * This routine prints the prompt, and * proceeds to taking character input. ******************************************** ASK LDX #CRF_RST ;Load the clear fvalue into X STX crflag ;Clear the character flag LDD #prompt ;Load the text address into D JSR [PRINTF,PCR] ;Jump to PRINTF LDD #ZERO ;Clear D (A & B) ******************************************** * KEEP_ASK * * This routine gets characters from the * serial line and displays them. It also * checks for invalid characters and * overflows. It also adds the characters * together to accurately represent the * value being typed on-screen. ******************************************** KP_ASK LDY GETCHAR ;Load the address into Y JSR 0,Y ;Jump to what Y points to ;We've now gotten an ASCII charater, and stored it to B LDY PUTCHAR ;Load the address into Y JSR 0,Y ;Jump to what Y points to ;We've pushed that same character out the serial port CMPB #CR ;Did the user press enter? LBEQ PRESULT ;Print the result ;Is the character invalid? CMPB #U_BND ;Compare the character to our upper bound BGT ER_CHR ;If it's greater, put out an error CMPB #L_BND ;Compare the character to our lower bound BLT ER_CHR ;If it's lesser, put out an error CMPB #IN_1 ;Compare the character to our first invalid BEQ ER_CHR ;If it's equal, put out an error CMPB #IN_2 ;Compare the character to our second invalid BEQ ER_CHR ;If it's equal, put out an error ;Now that the user has entered a valid character... LDX #CRF_SET ;Load the set value into X STX crflag ;Set the character flag CMPB #PLUS ;Is it an addition? BEQ ADD ;Then add! CMPB #MINUS ;Is it a subtraction? BEQ SUB ;Then subtract! CMPB #MULT ;Is it a multiplication? BEQ MUL ;Then multiply! CMPB #DIVIDE ;Is it a division? BEQ DIV ;Then divide! SUBB #A_TO_D ;Convert B to decimal LDAA #ZERO PSHD ;Since we're not doing an operation, it's a number, so push it. BRA KP_ASK ;Grab more characters ******************************************** * ER_CHR * * This routine prints an error message * telling the user that they've entered * an invalid character. ******************************************** ER_CHR LDD #ic_err ;Load the text address into D JSR [PRINTF,PCR] ;Jump to PRINTF BRA ASK ;Prompt again ******************************************** * ER_OVF * * This routine prints an error message * telling the user that they've entered * values which have resulted in an * overflow. ******************************************** ER_OVF LDD #ov_err ;Load the text address into D JSR [PRINTF,PCR] ;Jump to PRINTF BRA ASK ;Prompt again ******************************************** * DONE * * This routine ends the program with a * software interrupt. ******************************************** DONE SWI ;End the program ADD LDY #ZERO ;Clear Y LDD #ZERO ;Clear D PULD ;Pull a stack value into D PULY ;Pull a stack value into Y STY temp ;Store Y to temp ADDD temp ;D + temp, store in D BCS ER_OVF ;If we've overflowed, print error PSHD ;Push D to the stack BRA KP_ASK ;Keep looking for chars SUB LDY #ZERO ;Clear Y LDD #ZERO ;Clear D PULD ;Pull a stack value into D PULY ;Pull a stack value into Y STY temp ;Store Y in temp SUBD temp ;D - temp, store in D BCS ER_OVF ;If we've overflowed, print error PSHD ;Push D to the stack BRA KP_ASK ;Keep looking for chars MUL LDY #ZERO ;Clear Y LDD #ZERO ;Clear D PULD ;Pull a stack value into D PULY ;Pull a stack value into Y EMULS ;D * Y, store in Y:D BCS ER_OVF ;If we've overflowed, print error PSHD ;Push D to the stack LBRA KP_ASK ;Keep looking for chars DIV STX temp ;Store X to temp LDX #ZERO ;Clear X LDD #ZERO ;Clear D PULD ;Pull a stack value into D PULX ;Pull a stack value into X IDIVS ;D / X, store in D BCS ER_OVF ;If we've overflowed, print error LDX temp ;Load temp back to X PSHD ;Push D to the stack LBRA KP_ASK ;Keep looking for chars ******************************************** * PRESULT * * This routine prints the message telling * the user the total sum of all entered * values. It ends the program if the user * did not enter anything. ******************************************** PRESULT PULD ;Load the final value from the stack STD total ;Store it to total LDD total ;Load sum to be pushed PSHD ;Push sum to the stack LDD #result ;Load the result string to be pushed JSR [PRINTF,PCR] ;Jump to PRINTF LDX crflag ;Load the character flag for comparison CPX #CRF_SET ;Has the user entered anything? LBEQ ASK ;If so, keep prompting LBRA DONE ;If not, we're done