; ; PROG: dataconv.asm ; ; NAME: Solution ; SEC: 000 ; SSN: 123456789 ; DATE: Nov 12, 2000 ; ; DESC: dataconv.asm accepts an integer between -32768 and ; 32767 and prints the hexadecimal equivalent to the ; console. ; ; The program requires that TRAP x30 read a character ; from the console. If the character is a digit, the ; binary value of the character is stored in R0. The ; TRAP routine should also echo the character to the ; console and account for sign characters '-' and '+' ; storing x0001 or x0000 in R0. ; ; The program requires that TRAP x31 print the ; hexadecimal equivalent of the low order four bits ; in R0. ; ; The program prints an error if the input value is ; empty, too many digits, or the magnitude is out of ; range. Input is completed with any character other ; than a digit. ; ; A quirk of the application is that input can be ; completed with a character other than a newline. TRAP ; x30 echoes the character to the output so that valid ; input could appear as digits followed by a single ; character, e.g. 123g. ; .ORIG x3000 ; ; R0 = holds return value from TRAP x30 ; R1 = holds error code from TRAP x30 ; R2 = temporary storage ; R3 = temporary storage ; R4 = input counter ; R5 = holds final result ; R6 = holds input sign information ; R7 = for return addresses from subroutines ; AND R0, R0, x00 ; clear contents of R0 AND R1, R1, x00 ; clear contents of R1 AND R2, R2, x00 ; clear contents of R2 AND R3, R3, x00 ; clear contents of R3 AND R4, R4, x00 ; clear contents of R4 ADD R4, R4, x05 ; number of characters AND R5, R5, x00 ; clear contents of R5 AND R6, R6, x00 ; clear contents of R6 AND R7, R7, x00 ; clear contents of R7 JSR INST ; print out instructions ; ; Read in the first character and determine if it is a sign ; character, a digit, or an invalid character. If a sign char ; copy value to sign flag. If a digit, copy value to result ; and decrement counter. If invalid then error. ; TRAP x30 ; read the first character ADD R2, R1, R2 ; copy error into R2 BRn FSTSGN ; was a sign character ADD R2, R2, x00 ; check for digit BRp ERROR ; not sign or digit ADD R5, R5, R0 ; a valid digit was input AND R2, R2, x00 ; register R2 <- -1 NOT R2, R2 ; . ADD R4, R4, R2 ; decrement counter JMP SCDCHR ; get second character FSTSGN ADD R6, R6, R0 ; get sign flag ; ; Read in the second character and determine if it is a digit ; or an invalid character. If an invalid character then check ; to see if a digit was already entered. If so then process ; value, otherwise no valid digit was entered and error occurs. ; If a digit then check contents of R5. If there is something ; there, multiply it by ten and add new digit. If nothing ; there then just copy new digit ; SCDCHR TRAP x30 ; read second character ADD R1, R1, x00 ; check for digit BRnp CHKERR ; not a digit character ADD R5, R5, x00 ; check R5 contents BRz FSTCHR ; this is first digit AND R2, R2, x00 ; clear out R2 AND R3, R3, x00 ; clear out R3 ADD R2, R2, R5 ; copy R5 contents ADD R3, R3, R5 ; copy R5 contents ADD R2, R2, R2 ; shift left one ADD R3, R3, R3 ; shift left one ADD R3, R3, R3 ; shift left one ADD R3, R3, R3 ; shift left one ADD R5, R2, R3 ; R5 <- R5 * decimal 10 ADD R5, R5, R0 ; add in new digit AND R2, R2, x00 ; register R2 <- -1 NOT R2, R2 ; . ADD R4, R4, R2 ; decrement counter JMP REMCHR ; get remaining chars CHKERR ADD R5, R5, x00 ; check R5 contents BRz ERROR ; no digit present, error JMP PROCESS ; assume end of input FSTCHR ADD R5, R5, R0; ; copy digit to result AND R2, R2, x00 ; register R2 <- -1 NOT R2, R2 ; . ADD R4, R4, R2 ; decrement counter ; ; Now that we've done some error checking on the first two ; characters input we can continue getting characters until we ; encounter and invalid one signifying end of input or we get ; more than the number of characters expected. ; REMCHR ADD R4, R4, x00 ; check value of counter BRz EATCHR ; eat remaining characters TRAP x30 ; get next character ADD R1, R1, x00 ; check for digit BRnp PROCESS ; process current digits AND R2, R2, x00 ; clear out R2 AND R3, R3, x00 ; clear out R3 ADD R2, R2, R5 ; copy R5 contents ADD R3, R3, R5 ; copy R5 contents ADD R2, R2, R2 ; shift left one ADD R3, R3, R3 ; shift left one ADD R3, R3, R3 ; shift left one ADD R3, R3, R3 ; shift left one ADD R5, R2, R3 ; R5 <- R5 * decimal 10 ADD R5, R5, R0 ; add in new digit AND R2, R2, x00 ; register R2 <- -1 NOT R2, R2 ; . ADD R4, R4, R2 ; decrement counter JMP REMCHR ; get remaining chars ; ; Last character should be a newline. If it is another digit ; then too many characters have been input and an error ; condition occurs. ; EATCHR TRAP x30 ; get next character ADD R1, R1, x00 ; check for digit BRnp PROCESS ; process current value LOOP TRAP x30 ; get next character ADD R1, R1, x00 ; check for digit BRnp ERROR ; input too long JMP LOOP ; continue eating chars ; ; At this point we have been accumulating the inputs into the ; register R5. The only checks here are to determine if the ; magnitude of the value is too large. If so then an error ; occurs. Otherwise we print out the contents of R5 using the ; hexadecimal output trap. ; ; A negative magnitude is valid only if its value is x8000. ; That value would be -32768. This is a special check in the ; following instructions. ; PROCESS ADD R5, R5, x00 ; check the value of R5 BRn NEGINP ; negative value in R5 ADD R6, R6, x00 ; check value of R6 BRz OUTPUT ; positive sign value NOT R5, R5 ; convert to negative ADD R5, R5, x01 ; . JMP OUTPUT ; output section of code NEGINP LD R2, MAXMAG ; load maximum magnitude ADD R2, R5, R2 ; subtract max magnitude BRp ERROR ; invalid magnitude ADD R6, R6, x00 ; check value of sign flag BRz ERROR ; value should be positive OUTPUT LEA R0, M_HEX ; load hexadecimal prompt PUTS ; print prompt AND R0, R0, x00 ; clear contents of R0 ADD R0, R0, R5 ; copy contents of R5 JSR ROTL4 ; print out TRAP x31 ; print hexadecimal equiv JSR ROTL4 ; print out TRAP x31 ; print hexadecimal equiv JSR ROTL4 ; print out TRAP x31 ; print hexadecimal equiv JSR ROTL4 ; print out TRAP x31 ; print hexadecimal equiv HALT ; halt the processor ERROR JSR NEWLINE ; print a newline JSR NEWLINE ; print another newline LEA R0, M_ERR ; load the error message PUTS ; print error message HALT ; halt the processor ; ; INST subroutine ; prints instructions to the console ; ; registers used ; R0 output register ; R7 return address for PUTS ; INST ST R0, INSTR ; save register R0 ST R7, INSTret ; save return address LEA R0, M_INST1 ; load the first instruction line PUTS ; print it to the console LEA R0, M_INST2 ; load the second instruction line PUTS ; print it to the console LEA R0, M_INST3 ; load the third instruction line PUTS ; print it to the console LEA R0, M_PRMPT ; load the prompt line PUTS ; print it to the console LD R0, INSTR ; restore R0 LD R7, INSTret; ; restore return address RET ; return to the calling routine ; ; NEWLINE subroutine ; prints a newline character to the console ; ; registers used ; R0 output register ; R7 return address for OUT ; NEWLINE ST R0, NEWLR ; save register R0 ST R7, NEWLret ; save return address AND R0, R0, 0 ; clear out register R0 ADD R0, R0, x0A ; load R0 with newline OUT ; print the newline LD R0, NEWLR ; restore R0 LD R7, NEWLret ; restore return address RET ; return to calling routine ; ; ROTL4 subroutine ; rotates the contents in register R0 by four ; bits to move the high order four bit to the ; low order four bits for masking and output, ; the contents of R0 are not restored and are ; left as the rotated quantity ; ; registers used ; R1 counter ; R2 -1 to decrement counter ; ROTL4 ST R1, ROTLR1 ; save register R1 ST R2, ROTLR2 ; save register R2 AND R2, R2, x00 ; clear out R2 NOT R2, R2 ; initialization of R2 to -1 AND R1, R1, x00 ; clear out R1 ADD R1, R1, x04 ; initialize to 4 RLOOP ADD R0, R0, x00 ; determine if high bit set BRn ADDONE ; if so, branch to ADDONE ADD R0, R0, R0 ; add to itself, shift left ADD R1, R1, R2 ; decrement counter BRnp RLOOP ; again is not complete JMP RRET ; return after 4 shifts ADDONE ADD R0, R0, R0 ; add to itself, shift left ADD R0, R0, 1 ; add one, result of overflow ADD R1, R1, R2 ; decrement counter BRnp RLOOP ; again if not complete RRET LD R1, ROTLR1 ; restore register R1 LD R2, ROTLR2 ; restore register R2 RET M_ERR .STRINGZ "there was an error in your input\n" M_INST1 .STRINGZ "dataconv accepts a decimal number in the\n" M_INST2 .STRINGZ "range of -32768 to 32767 and prints to the\n" M_INST3 .STRINGZ "the hexidecimal equivalent of the input\n\n" M_PRMPT .STRINGZ "==> " M_HEX .STRINGZ "\nhex: x" MAXMAG .FILL x8000 INSTR .BLKW 1 INSTret .BLKW 1 NEWLR .BLKW 1 NEWLret .BLKW 1 ROTLR1 .BLKW 1 ROTLR2 .BLKW 1 .END