Tiny Binary Computer Programming Patterns

As of Summer, 2026, this is a work in progress.

Programming in assembly language is different from programming in a high-level language like Python. Something as simple as displaying "Hello World!" on the screen can take over a dozen assembler statements and a hundred or so instruction times. This page explains how to make TBC's assembly language do many of those things that are built in to high-level languages.

Clicking the copy icon copy in a code block will copy that code block to the clipboard. You can then paste it into the assembler source pane or into a program file.

Table of Contents

Display a String

Although TBC has a "behind the scenes" mechanism for displaying numbers, displaying a string involves loading each character of the string into the accumulator and sending it to the screen with the outc command.

Suppose you have a string like this:

      hello    dat    "Hello,World!",0x0a,0

That 0x0a is the new line character. It will move the display to the next line. The 0 marks the end of the string. It assembles to a word of all zeros, also called a null. Here is code to display a string:

  1.         ldi     msg     // get address of msg 
  2.         sta     ptr     // Save address in "ptr"
  3. loop    lia     ptr     // value loaded from address in "ptr"
  4.         brz     done    // null means done
  5.         outc            // Output character
  6.         lda     ptr     // pointer back in Acc
  7.         inc             // Increment to next character
  8.         sta     ptr     // Save it
  9.         br      loop    // Go around
  10. done    hlt
  11.  
  12. ptr     dat
  13. newline equ     0x0a     // new line character
  14. msg     dat     "Hello, World!",newline,0
copy

Simple Subroutine Calls

Subroutines provide a way to have only one copy of code that would be needed at two or more places. Instead of duplicating the code, the program calls the subroutine each time it is needed. When complete, the subroutine returns control to the instruction immediately after the call. The TBC instructions to do this are call and ret The program below just prints 1-2-3-4-5, but it uses subroutines to print the 2, 3 and 4 to show how subroutine calls work.

  1.         ldi     1       // a number to display
  2.         out             // display it
  3.         call    two     // subroutine call
  4.         ldi     5
  5.         out
  6.         hlt
  7.  
  8. two     ldi     2
  9.         out
  10.         call    three   // a call within a call
  11.         ldi     4       // "two" continues here
  12.         out
  13.         ret             // returns to main program
  14.  
  15. three   ldi     3
  16.         out
  17.         ret             // returns to "two"
copy

Subroutines have the same problem Hansel and Gretel had; getting there is easy because the subroutine name comes right after the call. The problem is how to get back. The call and ret instructions use a stack that grows downward from address 0x07e to keep track of how to get back. A call puts the proper return address on the stack and a ret gets the address at the "top" of the stack and loads it into the program counter. Since the program counter holds the address of the next instruction, execution continues at that address.

Click the "copy" icon to copy this snippet, paste it into the assembler pane, assemble and run it. Watch what happens at the high memory addresses when the program runs.

Call a Subroutine with One Argument

If you have a subroutine that needs one argument that will fit in a 12-bit word, you can pass the argument on the stack.

Call a Subroutine with Two or More Arguments

It isn't practical to pass more than one argument to a subroutine using the stack. Instead, the calling program builds a parameter list and passed the address of that parameter list using the stack.  Subroutines can pass the number of parameters as the first item of the list. Note: It is possible to return more than one result using the stack.

  1.         ldi     5       // Some value for first argument
  2.         sta     a1      
  3.         ldi     4       // And a value for the second
  4.         sta     a2
  5.         ldi     a1      // Address of the "list"
  6.         push            // Param list on stack
  7.         call    gfam    // Multiply the two arguments
  8.         pop
  9.         sta     result
  10.         out             // Display the result
  11.         hlt
  12.         
  13. a1      dat             // the parameters must be together
  14. a2      dat
  15. result  dat
copy

Note: to run this, you must also copy the gfam subroutine and add it to the source pane in the assembler.

Multiplication

Like most early, small computers, TBC does not have a multiply instruction. Instead, multiplication is performed by repeated addition. That's somewhat slow, but it works. Here is the gfam (go forth and multiply) subroutine. Call it with an argument list of two words. See Call a Subroutine with Two or More Arguments for help with that. The product is returned on the stack. A pop instruction right after the call will get the product into the accumulator.

  1. gfam    sswp    temp    // Go Forth And Multiply
  2.         pop             // address of parameter list
  3.         sta     params
  4.         lia     params  // get first param
  5.         sta     mcand   // store multiplicand
  6.         sta     product // product now multiplicand times 1
  7.         lda     params 
  8.         inc             // increment to next param
  9.         lia     params  // get second param
  10.         dec             // product already times 1
  11.         sta     mplier  // store multiplier
  12. loop    lda     product
  13.         add     mcand
  14.         sta     product
  15.         lda     mplier
  16.         dec
  17.         sta     mplier
  18.         brz     return
  19.         br      loop
  20. return  lda     product
  21.         push
  22.         sswp    temp
  23.         ret
  24.  
  25. temp    dat     0,0
  26. params  dat             // address of caller's argument list
  27. mplier  dat
  28. mcand   dat
  29. product dat
copy