TI-85 Assembler Programming Guide

by Patrick Davidson


Part I : Introduction


This page intends to give you some help in programming ZShell, Usgard, PhatOS, or Rigel games. Part II describes some topics essential for all programmers. If you don't understand what I am talking about in Part II, look in part III and hopefully it will explain it. Part III provides a tutorial of TI-85 programming and shows in detail how to make some simple programs. P This information is (to the best of my knowledge) reasonably accurate, but I am making no guarantees about it. Always make suure you have backed up all data on your calculator that you need to keep before you start experimenting with assembly programming. If you see any errors or omissions in this document, or want to ask me something about programming, E-Mail me!!


Part II : Essential TI-85 Programming Information


What you need to get started

Unlike with BASIC, you will need more than just your calculator to program games. You need:

All of the software and reference documents can be downloaded at ticalc.org. You can also get the instructions for making a your own graph-link there. You should print out all of the reference documents, as you will need them!


Binary and Hexadecimal

To program the TI-85 in assembler, you will need some knowledge of binary and hexadecimal number bases. Math teachers usually want you to think that this is extremely difficult, but they are just trying to fool you! It's EASY!

In our usual decimal system, each digit of a number can have ten values (0-9). So, using the decimal system, we count like this : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10... Wwwooaahhh! Something strange seems to have happened between those last two numbers. It sure did! Whenever the units digit must go past its maximum value, you set it back to zero and then increment the digit to the left of it (in the case here, that digit was originally a 0). The second digit reprents a number of tens, making it more significant than the first. This amazing phenomenon is called place value. Let's try counting some more : 96, 97, 98, 99, 100... as you see, the next time the units digit reaches nine, you must increment the next digit to the left. But, when it is already nine (the highest it can be in the decimal system), you set it to zero and increment the next digit to the left. This digit has a value of a hundred (that is, you multiply it by a hundred to find its value).

The binary system works in about the same way, but only uses the digits 0 and 1. Thus you count in binary like this : 0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010... using the same method as in the decimal system. This time, however, the highest digit you can use is 1. Thus the second place (from the left) has a value of 2 (in decimal). The next place has a value of 4, then 8, 16, 32, 64, 128, 256... Binary numbers are usually denoted by preceding the value with a % or following it with a b, such as %1110 (14 decimal) or 10001b (17 decimal). Want to double a binary number? Add a zero to the right side. Multiply by four? Add two zeros. It works just like adding zeros to multiply by 10 and 100 in decimal (as 2 and 4 are %10 and %100).

The hexadecimal system gives you 16 digits, 0-9 and then A-F. Hex numbers are indicated by a preceding $ or a following h. The values of the hex digits are like this:

HexadecimalBinaryDecimal
$0%00000
$1%00011
$2%00102
$3%00113
$4%01004
$5%01015
$6%01106
$7%01117
$8%10008
$9%10019
$A%101010
$B%101111
$C%110012
$D%110113
$E%111014
$F%111115
The second place in a hex number has a place value of 16. The third place, 256, and the fourth, 4096. Converting between binary and hex is easy, as each hex digit matches a specific sequence of binary digits. If the length of a binary number you want to change to hex is not a multiple of 4, just add zeros on the left side...

You do not in any way need to learn to do number base conversions! Your TI-85 can do this for you. Just hit [2nd] and then [1] to get into the hex menu. [F1] takes you into a menu where you can get the special A-F digits for use in hex numbers. [F2] gives you the suffixes b and h which you can add to numbers to show that they are binary or hex. [F3] gives you a conversion operators which will change the result to a number in a specific base.


Bits, Nybbles, Bytes, and Words

A bit is a single binary digit. It can be a 0 or 1, and represents the smallest unit of data. A bit is "set" if it contains the value of 1, and "reset" or "cleared" if its value is 0.

A nybble is 4 binary digits, from %0000 to %1111. It can be represented as one hex digit.

A byte is 8 bits, or 2 nybbles. Most Z80 commands operate on at least one byte at a time. This is two digits long in binary and 8 digits long in hex. The most significant bit is the one with the highest place value, in this case 128. The least significant bit is the units digit. The bits are numbered with the least significant as bit 0 and the most significant as bit 7.

A word consists of 2 bytes. These can be represented by four hex digits. The Z80 processor uses words to represents memory addresses. The bits in a word are numbered with the least significant as bit 0 and the most significant (with a place value of 32,768) as bit 15.


Two's Complement

Negative numbers in binary are represented by what is called two's complement. To negate a number, just invert every bit and add one. For example, 5 is represented by the byte %00000101. To negate this, just invert it (%11111010) and then increment it (%11111011). This binary numer is -5 in decimal (it's also 251). When you add these two bytes, you get %100000000. However, since you were doing a byte operation, only the lower 8 bits are kept, giving 0. Two's complement basically stores a negative value as 256 more than the value (for bytes) or 65536 more than the value (for words). The result is always 256 (or 65536) greater than the actual result should be, but it comes to the right value because the high bit is ignored. Actually, it isn't ignored since it's stored in the carry flag (will be discussed later), but it is not part of the resulting number.


TI-85 Memory

The TI-85 has 32 kilobytes (32,768 bytes) of RAM (memory contains your programs, and can be modified) and 128 kilobytes (131,072 bytes) of ROM (which contains all the built-in TI-85 software that cannot be changed). Since the Z80 processor stores all memory addresses as words, the range of memory it can address is from $0000 to $FFFF. This is not enough for all the TI-85's RAM and ROM, so the ROM is addressed through bank switching. This means that only a piece of the ROM is accessed at a time, and you must switch a different part into position to read it. The TI-85 memory architecture is like this:

StartEndSize in bytesContents
$0000$3FFF16,384ROM (always shows first part of ROM)
$4000$7FFF16,384ROM (this part can be switched to show any section
$8000$FFFF32,768RAM
Since the positions of routines in ROM (with a few exceptions) are different on different calculators, you cannot call ROM routines directly. Instead, you must use the ZShell ROM_CALL function. Some addresses in RAM are constant, but your program can be moved anywhere in RAM at any time! For this reasons, you cannot reference addresses within your own program directly under ZShell. Specially written PhatOS programs are, however, always loaded at the same address (current $8e57). They must always directly reference addresses within the program. In order to tell the assembler where the program is, you must start the program with ".org $85e7". Instead, you must read the value of (PROGRAM_ADDR) and add that to the address when trying to get a data address, or the special JUMP_ and CALL_ functions to redirect program flow. Under USGARD, you can reference these addresses directly, which is must faster, but must put an & in front of the label name to tell USGARD to relocate it. Programs written under PhatOS are always loaded to the same address at all times. Because of this, you don't need any relocation at all, and don't even need the &. Under PhatOS or Rigel, you should never use anything referencing PROGRAM_ADDR. You must put ".org $8e57" at the start of a PhatOS program and ".org PROG_START" at the top of a Rigel program, and use only direct addressing. RAM addresses which can be used are:
Start AddressSize in bytesUse
$80DF168Text memory. This is always set to all zeroes by ZShell before your program is started.
$8010100DELc buffer. This stores the text you last deleted with DELc in the program editor. This is not initialized to any specific value. You can use it for your own storage, but must set $800F to zero so the user won't try to undelete it and get garbage out.
$86411024Graph memory. This stores the image on your graph screen. It is not initialized to any speicfic value when your program is started. If you use this for your data, the graph screen will be scrambled after you exit the program. Since many users may not like to see this, you should execute the statement "set 0,(iy+3)" at some point during your program to tell the OS to redraw the graph screen the next time it is displayed.
$FC001024Video memory. This holds the image that is actually displayed. The TI-85 LCD has 128 columns and 64 rows, a total of 8192 pixles. Each byte in the range of $FC00 to $FFFF hold the value of a row of 8 pixels. $FC00 hold the first 8 pixles in the upper left corner, and $FFFF the 8 pixels in the lower right corner. It takes 16 bytes of the display memory to form one line of the display. The leftmost pixel is controlled by bit 7, and the rightmost pixel is bit 0. When the bit is set (has a value of 1), the pixel is black. When the bit is cleared (has a value of 0), the pixel is not shown.


Z-80 Architecture

The Z-80 processor (which is in the TI-85) is a very simple processor. It has few registers and a very limited instruction set. It doesn't even have a multiply instruction at all!

Like most microprocessors, the Z-80 does most of its calculations in registers. Registers are small temporary storage areas within the processor itself. They are usually used to hold values that are currently being worked with. The Z-80's registers are:


Control Statements

In Z-80, the program flow is controlled by special instructions which conditionally alter the program flow. Many of these rely on the data in the flags register.


Part III : Tutorial


Lesson I : First program

Lesson II : Don't overuse IX!

Lesson III : Bouncing logo

Lesson IV : Sprites

More lessons will be coming!!!!

Part IV : Your Turn!


The information above will hopefully give you a start in TI-85 assembler programming. The only way you can truly learn it is to try it yourself. If there's anything this world needs, it's more TI-85 games! So code as many games as possible, and be sure to spread your work for the benefit of the rest of the world!