Mano Utilities

Utilities for Mano's Basic Computer

Example Links:
Other Links:

Writing a String

Code
Pseudo-code
Nearer assembly language
Comments
// date: Aug 8, 2012
// author: Nicholas Duchon
// purpose: write an ascii string
//     in Mano basic computer
// use: put the address of the
//   start of the string into AC,
//   -- String must end with a dot!

// example of calling routine
           ORG 10
           LDA STRLOC
           BSA WRTSTR
           HLT
STRLOC     HEX STRING // string addr
STRING     STR "ONE."

// subroutine to write a string
           ORG 100
WRTSTR     HEX 0
           STA WRTSTRA  // save str
WRTSTR0    LDA WRTSTRA I // get word
           CIR  // get high byte
           CIR
           CIR
           CIR
           CIR
           CIR
           CIR
           CIR
           AND BYTEMASK // see 1 byte
           ADD WRTSTRDOTN // dot?
           SZA
           BUN WRTSTR1 // not dot
           BUN WRTSTR I // dot > ret
WRTSTR1    ADD WRTSTRDOT // restore
           OUT           // write
           LDA WRTSTRA I // for low
           AND BYTEMASK // see 1 byte
           ADD WRTSTRDOTN // dot?
           SZA
           BUN WRTSTR2 // not dot
           BUN WRTSTR I dot > ret
WRTSTR2    ADD WRTSTRDOT // restore
           OUT           // write
           ISZ WRTSTRA   // next word
           BUN WRTSTR0   // loop
WRTSTRA    HEX 0
WRTSTRDOT  CHR '.'
WRTSTRDOTN HEX FFD2
BYTEMASK   HEX FF

WRTSTR (strlocation)
  while true
    get char
    if char = dot
      return
    else
      write char
  end while
end subroutine
WRTSTR <return address here>
   AC -> WRTSTRA <string pointer>
         // effectively i=0
loop: load AC with str[i]
   CIR x 8, move high byte to low
   mask ff, remove high byte
   add ascii for -dot
   if 0, return
   add ascii dot,restoring char
   write char
   load AC with str[i]
   mask ff // now low byte
   add ascii -dot
   if 0 return
   add ascii dot, restore char
   write char
   i < i+1 // next 2 chars
   go to loop
A string is defined using the STR assembler directive, and for this subroutine to work correctly, the string should end with a dot (period).

Since the computer uses 16-bit words, a string is packed 2 ASCII characters per word, so the subroutine needs to first print the upper byte, then the lower byte. Also the subroutine needs to check each byte to see if it is the dot, which will indicate the end of the string, and will not be printed.

In the calling routine, the address of the start of the string must be placed in AC as the input parameter to the subroutine. Again because of the limitations of the machine language of Mano's computer, another labelled word needs to be declared which will hold the address of the start of the string, such as STRLOC in the example program.

Stacks

Code
Pseudo-code
Comments
// Code for stacks:
//   STKPUSH - push AC onto stack
//   STKPOP  - pop top of stack to AC
//   WRTSTR  - write string utility
// code at 150+
// stack at 200 (STKTOS)
// max elements 100 (STKMAX)

            ORG 150
STKPUSH     HEX 0
            STA STKTMP
            LDA STKCNT
            INC
            STA STKCNT
            ADD STKMAX
            SZA
            BUN STKP2
            LDA STK2MSGL
            BSA WRTSTR
            HLT // overflow error
STKP2       LDA STKTMP
            STA STKTOS I
            ISZ STKTOS
            BUN STKPUSH I // return

STKPOP      HEX 0
            LDA STKCNT
            ADD NEGONE
            SNA
            BUN STKP3
            LDA STK3MSGL
            BSA WRTSTR
            HLT
STKP3       STA STKCNT
            LDA STKTOS
            ADD NEGONE
            STA STKTOS
            LDA STKTOS I
            BUN STKPOP I

NEGONE      DEC -1
STKTMP      HEX 0
STKCNT      HEX 0
STKMAX      DEC -100
STKTOS      HEX 200 // stack 200 start
STK2MSGL    HEX STK2MSG
STK2MSG     STR "Push stack overflow."
STK3MSGL    HEX STK3MSG
STK3MSG     STR "Pop stack underflow."


// subroutine to write a string
WRTSTR     HEX 0
           STA WRTSTRA  // save str
WRTSTR0    LDA WRTSTRA I // get word
           CIR  // get high byte
           CIR
           CIR
           CIR
           CIR
           CIR
           CIR
           CIR
           AND BYTEMASK // see 1 byte
           ADD WRTSTRDOTN // dot?
           SZA
           BUN WRTSTR1 // not dot
           BUN WRTSTR I // dot > ret
WRTSTR1    ADD WRTSTRDOT // restore
           OUT           // write
           LDA WRTSTRA I // for low
           AND BYTEMASK // see 1 byte
           ADD WRTSTRDOTN // dot?
           SZA
           BUN WRTSTR2 // not dot
           BUN WRTSTR I // dot > ret
WRTSTR2    ADD WRTSTRDOT // restore
           OUT           // write
           ISZ WRTSTRA   // next word
           BUN WRTSTR0   // loop

WRTSTRA    HEX 0
WRTSTRDOT  CHR '.'
WRTSTRDOTN HEX FFD2

BYTEMASK   HEX FF
push (AC)
  counter ++
  if (counter > max)
    error message
    halt
  end if
  TOS [counter] <-- AC
  TOS ++
  return
end push

pop ()
  counter --
  if (counter < 0)
    error message
    halt
  end if
  AC <-- TOS [counter]
  return
end pop
 
There are 3 subroutines in this code:
  • STKPUSH
  • STKPOP
  • WRTSTR

The last one is included to make it easier to copy/paste this code into my simulator. It is used by the push and pop routines to print error messages: stack overflow in push, and stack underflow in pop. Both of these errors cause the simulator to halt.

Push takes the value in AC and pushes it onto the stack, incrementing the number of elements in the stack (STKCNT) and incrementing the top of stack (TOS) pointer (STKTOS). TOS points to the next free location on the stack.

Pop takes the element at the top of the stack (TOS-1), returns it in the AC register, decrements the number of elements in the stack, and decrements the TOS.

ISZ can be used effectively for the increment operations, but since Mano's computer has not analogous instruction for decrement, subtracting one can only be done using the AC register, meaning that the contents of the AC are going to be lost, which in turn means that any code calling this routine will have to save the value in the AC register someplace safe before calling this routine the pop routine.

Testing

Code
Comments
// testing stacks: push, pop
// also testing WRTSTR
            ORG 10
            CLA
            INC
            INC
            BSA STKPUSH // 1
            INC
            BSA STKPUSH // 2
            INC
            BSA STKPUSH // 3
            INC
            BSA STKPUSH // 4
            INC
            BSA STKPUSH // 5
            INC
            BSA STKPUSH // 6
            INC
            BSA STKPUSH // 7
            INC
            BSA STKPUSH // 8
            BSA STKPOP  // 8
            OUT
            BSA STKPOP  // 7
            OUT
            BSA STKPOP  // 6
            OUT
            BSA STKPOP  // 5
            OUT
            BSA STKPOP  // 4
            OUT
            BSA STKPOP  // 3
            OUT
            BSA STKPOP  // 2
            OUT
            BSA STKPOP  // 1
            OUT
            BSA STKPOP  // 0
            OUT
            BSA STKPOP  // -1
            OUT
            HLT
This code will push 8 numbers onto the stack, then try to pop 10. The pop subroutine should complain when trying to pop the 9th element and halt the simulation. After each element is popped, the code will write the value of the element to the output, as a hex number, so to see the results, the output panel should be set to hex rather than ASCII.

The first number pushed is 2, then 3, 4, 5, 6, 7, 8 and 9, just to make the numbers a little interesting in the test.

end.


By Dr. Nicholas Duchon
Last update: Aug 11, 2012