* ======================================================== *
*  Thomas C. Penick   ID# 452 80 6040         Program   4  *
*  EE319K Microprocessor Programming          due 3/12/98  *
*  Instructor: Laurence                       Section   B  *
*  MC6811 Program Source Code  PA4.asm        Roster#  32  *
*  Create Subroutines DECtoBin and BintoDEC                *
* ======================================================== *

         org  0
String   rmb  10        Input signed decimal string of ASCII characters
Result   rmb  10        Output signed decimal string of ASCII characters
StrStrt  rmb  2         Memory address of where String begins (BintoDEC
StrCurr  rmb  2         Memory address current location in String (BintoDEC)
         org  $E000     start of ROM
Main     lds  #$00FF    initialize the stack pointer
         jsr  InitSCI   Set up correct baud rate on SCI interface
Parta    ldab #20       Maximum number of characters to be input
         ldx  #String   Load the memory address of "String" into X
         jsr  InString  Input characters into string
*  Register X still points to the input string
CallDEC  jsr  DECtoBin  Convert decimal to binary
DidDEC   bvs  Parta     Repeat if there is an overflow

         tab            Save the contents in Reg A to Reg B
         ldaa #CR       Load carriage return into Reg A
         jsr  OutCh     Carriage return
         clra           Clear Reg A (so value will be in RegD)
         jsr  OutHex    Outputs value to screen in hex format.
         tba            Restore Reg A
*  Register A now contains the 8-bit signed number

Partb    ldx  #Result   Place to put string
CallBin  jsr  BintoDEC  Convert signed 8-bit binary to characters
*  Register X still points to Result string  /  (BintoDEC)

DidBin   ldaa #CR       Load carriage return into Reg A
         jsr  OutCh     Carriage return
         jsr  OutString
         ldaa #CR       Load carriage return into Reg A
         jsr  OutCh     Carriage return
         bra  Parta

**************** DECtoBin ******************************** start
*  Subroutine DECtoBin accepts a string of decimal characters
*  pointed to by RegX and converts it to a signed 8-bit binary
*  integer which is placed in RegA.  The first character may be 
*  a "+", "-", or digit.  Remaining characters should be digits.  
*  Invalid character sets the V-bit.
DECtoBin pshb           put B on the stack
First    ldaa 0,X       load a character into RegA
         ldab #0        RegB = 0 (means positive integer, default)
         pshb           Push RegB onto stack (save positive info)
         cmpa #EOT      Check for End of String
         beq  Done
         cmpa #'+       Check for "+"
         beq  ReadCh    Read next (second) character
         cmpa #'-       Check for "-"
         bne  ReadNum
         ins            Increment the stack pointer (to overwrite +/- info)
         ldab #1        RegB = 1 (means negative integer)
         pshb           Push B onto stack (save negative info)
         clrb           Zero RegB (to be the accumulated value)
         bra  ReadCh    Read next (second) character
* Now we have 1-byte of +/- info on the stack, first character in RegA,
* and zero in RegB.

ReadNum  cmpa #EOT      Check for End of String
         beq  Done      Character reading completed
         cmpa #'0
         blo  Err       Less than ASCII 0 is error
         cmpa #'9
         bhi  Err       Greater than ASCII 0 is error
         suba #$30      Convert ASCII 0-9 to value in RegA

* Operate on the accumulated value (multiply by 10) because we have
* a more significant digit.
         psha           Save RegA to the stack (the current value)
         lslb           Left shift RegB (multiply by 2)
         bcs  ErrOvr2   Error: value too large for register
         pshb           Save RegB to the stack (the x2 value)
         lslb           Left shift RegB (now multiplied by 4)
         bcs  ErrOvr3   Error: value too large for register
         lslb           Left shift RegB (now multiplied by 8)
         bcs  ErrOvr3   Error: value too large for register
         pula           Retrieve x2 value from stack
         aba            Add the two registers and store in A (we have x10)
         bcs  ErrOvr2   Error: value too large for register
         pulb           Retrieve the current value
         aba            Add the current value to 10x the previous
         bcs  ErrOvr1   Error: value too large for register
         tab            Store in RegB (the accumulator)

ReadCh   inx            Increment RegX
         ldaa 0,X       Read a character
         bra  ReadNum   Unconditional branch to "ReadNum"

*** ERROR MESSAGES 
ErrOvr3  ins            Increment the stack pointer
ErrOvr2  ins            Increment the stack pointer
ErrOvr1  ins            Increment the stack pointer
ErrOvr   ldx  #OverFlo  Load X with the address of the message string
         jmp  ShowMes   Display the message
Err      ldx  #Invalid  Load X with the address of the message string
         ins            Increment the stack pointer
ShowMes  jsr  OutString Display the message
         sev            Set the V-bit to indicated an error to program
         bra  DoneErr   Skip the next commands so the V-bit will remain set.
Done     tba            Transfer the accumulated value in RegB to RegA

*** CHECKING FOR POSITIVE/NEGATIVE
* Now check for +/- and update RegA as appropriate.
         pulb           Get +/- (0 means positive and 1 means negative)
         cmpb #0        Check if it's positive
         beq  ChkPosi   Move to additional checking of the positive number
* Checking a negative number
         cmpa #128      See if it is the max permissible negative magnitude
         beq  DoneErr   The binary 10000000 already means -128; we're done
         tab            Transfer A to B so A is in memory
         bmi  ErrOvr    If bit 7 is set then the magnitude is too great
         coma           Complement RegA
         inca           Two's complement of A
         bra  DoneErr   We're outa here!
* Checking a positive number
ChkPosi  tab            Transfer A to B so A is in memory
         bmi  ErrOvr    If bit 7 is set then number is too large for 2's comp.

DoneErr  pulb           Restore RegB
         rts
**************** DECtoBin ******************************** end

**************** BintoDEC ******************************** start
*  Subroutine BintoDEC converts an 8-bit signed binary number into a 
*  string of decimal characters.  The input is in RegA and the
*  output is at the memory location pointed to by RegX.
BintoDEC pshb           Save RegB to stack
         pshy           Save RegY to stack
         xgdx           Exchange D and X (cause we want to store X)
         std  StrStrt   Store the beginning address of the string
         xgdx           Exchange D and X
         tab            Save a copy of A in RegB
         bpl  PosiNum   Branch if bit 7 is clear (number is positive)
         coma           Complement RegA (converting to unsigned value)
         inca           Increment RegA  (now converted to unsigned)
         ldab #'-       Load "-" into RegB
         stab 0,X       Store "-" at the memory location pointed to by X
         inx            Increment RegX
PosiNum  tab            Load A into RegB (RegD)
         clra           Clear RegA (now value is in RegD)
         xgdx           Exchange D and X (cause we want to store X)
         std  StrCurr   Store the current address of the string pointer
         xgdx           Exchange D and X

* This section similar to "OutDEC"
* We convert the binary value in A to decimal, saving the digits on the
* stack and counting the digits in Y
         ldy  #0        Number of characters
BDLoop   ldx  #10       Convert to base 10
         idiv           Divide D/X -> Ans X remainder D
         pshb           Save remainder, reverse order
         iny            Increment Y
         xgdx           Exchange D and X
         cpd  #0        Compare D to zero
         bne  BDLoop    Branch if remainder is not zero (not done)
* Now we transfer the digits from the stack (converting to ASCII) 
* to a string in memory
         ldx  StrCurr   Load the memory address of the string pointer into RegX
BDOut    pula           Load a digit into A
         adda #'0       convert 0-9 to ASCII 0-9
         staa 0,X       Store the digit in the string
         inx            Increment X         
         dey            Decrement RegY
         bne  BDOut     Branch if Y not zero (more digits to do)
         ldaa #EOT       Store end of string in RegA
         staa 0,X       Store EOT to memory location pointed to by X
         ldx  StrStrt   Restore the memory address of the 
                        ;beginning of the string to RegX
         puly           Restore RegY from stack
         pulb           Restore RegB from stack
         rts
**************** BintoDEC ******************************** end

**************** ERROR MESSAGE STRINGS ******************* start
OverFlo  fcb  CR
         fcc  "Value out of range!"
         fcb  CR
         fcc  "Enter a new value."
         fcb  CR
         fcb  EOT
Invalid  fcb  CR
         fcc  "Invalid Character!"
         fcb  CR
         fcc  "Enter a new value."
         fcb  CR
         fcb  EOT
**************** ERROR MESSAGE STRINGS ******************* end
         org  $FFFE
         fdb  Main
         end


