Welcome to the first lesson of the Ash School! This first lesson
may be a bit boring, but it's really necessary to know how the calculator
works and a bit about the RAM memory, so you know what you do when you
program. In the end of the lesson we'll make a classic "Hello World!"
program. All software necessary to compile the program are downloadable
at the "How to compile" section.
Contents
Binary and hex
I will now explain a very important part when you're programming a lowlevel
language. You who know this stuff may skip this section.
Our own number system has the base 10, and that's because we humans
have 10 fingers. Computers (and calculators) don't have fingers, they have
electricity. To make it easy, there are two conditions, on and off, or
0 and 1. That is a bit. Since it's a bit unpractical to work with
the base 2, we put together 8 bits and then we got a byte (ex 01101011).
A byte range between 0 and 255 (there are 2^8 = 256 different ways to combinate
8 bits). 16 bits are called a word (0-65535). Less common is a nibble
which range between 0 and 15 (4 bits) and octal (0-7 and 3 bits).
What is hexadecimal? In the hexadecimal representation, a group
of four bits (nibble) is encoded as one hexadecimal digit. Hexadecimal
digits are represented by the symbols from 0 to 9, and by the letters A
(10), B (11) ... F (15). A byte is represented by two hexdigits (ex D3).
When you are using TASM all numbers you write are assumed to be in decimal, if you
want to write it as a binary or hexadecimal number you have to tell it to TASM. A hex
number can either be written like this $5E or like this 5Eh (if the number starts with a
letter you should put a 0 in front of it). Binary numbers are either written like this
%11010001 or 11010001b. I prefer to use % and $ because i find it easier to read.
Convert between decimal - hexadecimal - binary
One way is to use the calc of course, but it's often faster to do it
in your head. It's very easy to convert between hex and binary. Remember
that a hexadecimal number consist of two groups of four bits. Just take
one group at a time.
| 0100 | 1100 | -> 4C
D5 -> | 1101 | 0101 |
Binary to decimal is simple math. Just go from right to left and take
bit n * 2^n. The bits in a byte are numbered 0-7, right to
left. Each bit is worth 1, 2, 4, 8 and so on.
10010101 = 1*2^0 + 0*2^1 + 1*2^2 + ... + 1*2^7 = 1 + 4 + 16 + 128 = 149
To convert from decimal to binary is also easy. One way is to divide
the decimal number with two, and keep the remainder and so on.
173/2 = 86, remainder 1, 86/2 = 43, remainder 0, 43/2 = 21, remainder 1,
21/2 = 10, remainder 1, 10/2 = 5, remainder 0, 5/2 = 2, remainder 1,
2/2 = 1, remainder 0, 1/2 = 0, remainder 1.
Collect the remainders backwards and you get 10101101
When you want to go between hex and decimal (the most common convertation)
you can first convert to binary and then convert it to decimal/hexadecimal.
Choose your own way, because you will do it often.
Negative numbers
I won't write so much here because it's really simple. You only need
know a little about two compliment and you know the rest, because the compiler
will do it automatically when you compile your assemly program. You need
to know what happens to some length though.
What you need to know is this: -1 = 255, -2 = 254. You should understand
the rest then :-) If you want to add 5 with -3 for example, this is what
will happen:
5 = 00000101
-3 = 253 = 11111101
--------
100000010
Since a byte only can store 8 bits, the first 1 will disappear and 00000010
is left = 2 which is the correct result! (The bit doesn't really disappear,
it will be stored in the Carry Flag. More about that in the next lesson)
The memory in the TI-82
The TI-82 uses a 8-bit Z80 processor. Since it's a 8-bit processor,
instructions that only take one byte are generally faster executed than
longer instructions. A Z80 can "reach" 64k (1k = 1024 byte. 64k
= 65536 byte) byte in the memory, so there are some limitations. (even
worse than Bill Gates 640k...)
The first 32k contains the ROM (The ROM is actually 128k, but only 32k
is accessable at one time) and the second 32k contains the RAM. You don't
have 32k to play with though, because about 4,5k is reserved for different
things (cursor positions, graph mem, text mem, menu pointers and a lot
more). Another difficulty is that all variables are moving around in the
memory when you create new vars or just change the Ans variable. Ash 3.0
however makes sure that you program is always in the same place in the RAM
when it is started. This makes it a lot easier for you as a programmer to access
data within your program.
Your first program!
If you haven't tried before, this will be your first program. And of
course it must be a classic "Hello World!" program! The source
code will follow below, and then I'll explain what each row does. I think
it's easiest that way. In the next lesson, I'll explain a bit more about
what each instructions really do.
#include "ti82.h"
#include "keys.inc"
.org START_ADDR
.db "My first program!",0
ROM_CALL(CLEARLCD)
ld hl,0
ld ($800C),hl
ld hl,Text
ROM_CALL(D_ZT_STR)
WaitKey:
call GET_KEY
cp G_MODE
jr nz,WaitKey
ret
Text:
.db "Hello World!",0
.end
The first line includes the ti82.h file which contains a lot of alias
(I write those aliases with capital letters). Without it the code will
be very harder to understand. Most aliases is just an alias for a memory
address or a byte. The second line includes keys.h which is a file which
contains aliases for the keys.
All programs begin with .org STARTS_ADDR. This tells the assembler
where in the memory Ash will put your program. If you forget this
you program will not work, so always rember this as the first line.
The second line is just a description of the program. It will be displayed
in Ash. It must end with ,0 so Ash will know where the string ends
(strings ended with ,0 are called zero-terminated strings).
Then the program starts. The rom_call is just an alias which is included
in the ti82.h file, and what really happens is that it jumps into a place
in the ROM where the screen is cleared. In that way, we don't need to write
our own code to clear the LCD.
The next two rows moves the cursor to the top left corner of the screen,
and the next row after that loads the text string at the bottom program
into hl (or more exactly, hl points to the string).
Then we display the string with another rom_call and at the end we wait
for the user to press the Mode key. Remember to use the names of the keys,
and not a number you need to include the file keys.h.
This was just a quick description of how the program worked, and if
you didn't understand it all, don't worry.
How to compile a program
You need a couple of programs. First, you need TASM
3.0.1 (not Turbo Assembler) and you also need PRGM82 and FIX.COM,
which you should have since it's included in the Ash package. Then you
need a link program, but you probably already have one. Of course you
also need Ash 3.0
, else it will definately not work :-).
When you compile the program, you must have the file tasm80.tab (included
in the tasm zip file) in the same directory. To compile the program use the
batch file ASM.BAT which came with Ash 3.0. The following line will do all the work.
asm myfile.asm
where myfile.asm is your source. If your code is big (>1000 lines),
it will take a while because TASM is slow. If you get errors it will show...
There is one thing you should know when you use TASM: You must
make at least one space from the left margin if the row in the source contains
an instructions, and all label may not contain any spaces. Else
you get a lot of errors when compiling. Also remember to make on blank line
after the .END at the end of each file.