TI-83+ Z80 ASM for the Absolute Beginner
LESSON FIVE:
· The
Translation of the 1 + 5 Program
· Labels,
Variables, and How the Calculator Works with Them
THE TRANSLATION OF THE 1 + 5 PROGRAM
I would like you to remember, for this lesson, that when you write an
ASM program, it is translated into a bunch of numbers that the calculator
reads, and the calculator reads these numbers and translates them into
instructions to execute. Feel free to review
Lesson #1 if you need to. Also remember
that the program is stored in ram starting at RAM address 40339.
Most ASM tutorials do not tell you what this translated program looks like. While I don’t argue the methods used in those
tutorials, I don’t agree that it’s unnecessary to understand the translation of
an ASM program. It’s extremely easy to see the translation
of an ASM program, and it’s one of your first steps to see HOW something
works. And believe me: if you understand
how your program works and why, you get awesome calculator games like Desolate
and Wolfenstein. Therefore, throughout this lesson, and
perhaps from time to time on other lessons, I’ll show you some ASM programs
translated into numbers.
Like I said, this part is not difficult. Just remember that these lessons are for the
absolute beginner, so I’m putting this up knowing you as the reader can handle
it. Besides, unlike a the translation of
a simple Visual Basic program or even a simple C++ program, the translation of
a simple Ti-83+ ASM program takes only, oh, maybe 25-30 bytes.
The translation for the first ASM program you wrote is on page 4. Some of the translations I will explain
immediately, others I will explain later, and some of the translations do not require
explanation. By the way, a blue box
means a number that takes two bytes, aka a word.
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, 1 |
40344 |
62
1 |
add a, 5 |
40346 |
198
5 |
ld h, 0 |
40348 |
38
0 |
ld l, a |
40350 |
111 |
B_CALL _DispHL |
40351 |
239 17671 |
B_CALL _getKey |
40354 |
239 18802 |
B_CALL _ClrLCDFull |
40357 |
239 17728 |
ret |
40360 |
201 |
For starters, notice that the first two lines aren’t
translated. The first line, which tells
the calculator to include the file “ti83plus.inc,” is not translated, because
it contains code that is only put in the program when needed, and it tells
SPASM exactly how to put it in the calculator.
In other words, SPASM puts in the program what is needed, when needed,
from ti83plus.inc…SPASM does not need to put in the whole file.
I will explain later in this lesson why .org 40339 is not
translated/compiled, but for right now, the main reason is the line is a
reference for SPASM, not for the calculator.
_ClrLCDFull,
_getKey, _DispHL, t2ByteTok and tAsmCmp are all constants. Since _ClrLCDFull is a constant equal to
17728, SPASM replaces _ClrLCDFull with the number 17728 wherever _ClrLCDFull is
located. Similarly, t2ByteTok is a constant
equal to 187, so SPASM saw t2ByteTok and translated it to the number 187.
_ClrLCDFull, _getKey, and _DispHL are constants referring to where
these instructions needed by the ASM program are located. They are ROM addresses, not RAM
addresses. The instructions that ASM
programs can access are located in ROM as part of the Ti-83+ operating system.
Notice that when you choose a value to load into A or H,
the translation is equal to that value?
Pretty sweet, huh? But not
surprising.
Now to tell you about .db.
.Db is used to enter data for the calculator. When you use .db, you’re entering exact data
that you want, so SPASM does nothing to alter the data. For instance, if you type in .db 1, 2, 3, 4,
5 and 6, the translated program contains, in decimal numbers, 1 2 3 4 5 6 in
that order: nothing altered, nothing changed.
All ASM programs require the numbers 187 and 109 to identify them as ASM
programs, so .db tells SPASM that these numbers should be in the translated
program EXACTLY as the numbers 187 and 109.
However, there is one exception to this rule, which you’ll
learn about in a later lesson.
Exercise: Translate the
following program into numbers. The
answer is on the next page.
Hint: Remember that
Number_Seven and Number_Four are constants, since they use the word .equ. What does Spasm do with constants?
ANSWER:
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
NumberSeven .equ 7 |
|
|
NumberFour .equ 4 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187 109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, NumberSeven |
40344 |
62
7 |
add a, NumberFour |
40346 |
198
4 |
ld h, 0 |
40348 |
38
0 |
ld l, a |
40350 |
111 |
B_CALL _DispHL |
40351 |
239 17671 |
B_CALL _getKey |
40354 |
239 18802 |
B_CALL _ClrLCDFull |
40357 |
239 17728 |
ret |
40360 |
201 |
LABELS, VARIABLES, AND HOW THE CALCULATOR WORKS WITH THEM
As a Ti-Basic programmer, you understand that Labels are
used to mark places where your program needs to jump to from time to time. You also understand that Variables are used
to hold values that you need saved. But
do you ever get annoyed that Labels can only be two letters/numbers long and
variables are also somewhat limited?
In ASM programming, names for labels and variables can be
as big as you want. However, there are
two rules that apply to SPASM when applying variable names:
1. Labels and variables cannot start with a number
2. Labels and variables can only contain numbers,
letters and underscores.
As a good rule of thumb, you should include a colon at the end of your
labels and variables. It is not
required, but it is good practice. Here
are some examples of valid labels:
FunctionNumberOne:
Function_Number_One:
Function_Number1:
And, here are some examples of invalid labels and
variables:
2Function1:
Function#1:
We’ll start by working with labels.
You’ll learn later how to tell the calculator when to jump and when not
to jump, but for right now, I’ll be teaching you how to tell the calculator to
“goto” your label no matter what. There
are two ways to do this, and it depends on how far away you want to jump.
JR is an abbreviation for “Relative jump.” You can use JR whenever the distance to where
you want to jump is short. Spasm will
tell you when you cannot use JR by saying “Relative jump is over 128
bytes.” In other words, when Spasm is
translating your program, if the label is more than 128 bytes away, you cannot
use JR.
In which case you use JP, which is a “jump.” This allows much bigger jumps. In fact, the jumps allowed are so big that
you can even jump outside your program.
There’s a big, big difference between JR and JP which will be
described later in this lesson. However,
some smaller differences are, JR takes fewer bytes and, for the most part, is
faster than JP. You should use JR every time
you need a jump; if you can’t use it, Spasm will tell you, and you can change
it to JP in a matter of moments.
Here’s an ASM program for you to write. By the way, if you decide to just copy and
paste the program (which I don’t recommend), at least rewrite the first
#include line. If you just copy and
paste it, chances are Spasm won’t work correctly.
What happened here? Notice
the ret after add a, 5? The program ended early! Now, don’t give me crud such as “Oh, we can
easily fix that by just removing the ret statement!” That is very true, but just bear with me. We’re going to take a different
approach. Take this program, and add the
lines highlighted in blue. Then run it,
and it should work correctly:
Now, I would like to show you how THIS program translates so you can
see how JR works. This is important,
believe me.
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, 2 |
40344 |
62
2 |
add a, 5 |
40346 |
198
5 |
jr Continue_Program |
40348 |
24 1
|
ret |
40350 |
201 |
Continue_Program: |
|
|
ld h, 0 |
40351 |
38
0 |
ld l, a |
40353 |
111 |
B_CALL _DispHL |
40355 |
239 17671 |
B_CALL _getKey |
40357 |
239 18802 |
B_CALL _ClrLCDFull |
40360 |
239 17728 |
ret |
40363 |
201 |
Notice that the label is not translated! The calculator uses a different approach than
what you might expect. If you notice,
ret is only one byte of instructions when translated. So, jr tells the calculator to skip one byte
of instructions, hence the number “1” in the translation. The program “jumps”, “skips” over one byte of
instructions. Since ret is only one byte
of instructions when translated, ret is skipped.
Let’s replace jr with jp. Then
notice there’s a change:
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, 2 |
40344 |
62
2 |
add a, 5 |
40346 |
198
5 |
jp Continue_Program |
40348 |
195 40352 |
ret |
40351 |
201 |
Continue_Program: |
|
|
ld h, 0 |
40352 |
38
0 |
ld l, a |
40354 |
111 |
B_CALL _DispHL |
40356 |
239 17671 |
B_CALL _getKey |
40358 |
239 18802 |
B_CALL _ClrLCDFull |
40361 |
239 17728 |
ret |
40364 |
201 |
This time, the jump is not translated as “how far to jump.” It is translated as “where to jump.” Instead of being
told to skip a number of bytes, the calculator is told the RAM address to jump
to.
Now, I can tell you why .org is not translated, but why it is needed
as a reference for Spasm. As was stated
earlier, the ASM program is run from RAM address 40339 of the calculator. However, Spasm doesn’t know that. It assumes that the address starts at 0! So suppose you did not tell Spasm that the
calculator starts the program at 40339.
Then, when jp is translated, it would read as 195 13, meaning it would tell the calculator to
jump to address 13, not address
40352. Your program would not work. Try it!
Remove the line .org 40339, and run the program on an emulator. The answer to the problem 2 + 5 is not
displayed.
Exercise:
Before the label Continue_Program:, add three more
“rets.” For example:
jr Continue_Program
ret
ret
ret
ret
Continue_Program:
Now translate the program using jp and the program using
jr. Answers are on the next pages: jr on
the first page, and jp on the second.
ANSWER FOR JR:
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, 2 |
40344 |
62
2 |
add a, 5 |
40346 |
198
5 |
jr Continue_Program |
40348 |
24 4
|
ret |
40350 |
201 |
ret |
40351 |
201 |
ret |
40352 |
201 |
ret |
40353 |
201 |
Continue_Program: |
|
|
ld h, 0 |
40354 |
38
0 |
ld l, a |
40356 |
111 |
B_CALL _DispHL |
40358 |
239 17671 |
B_CALL _getKey |
40360 |
239 18802 |
B_CALL _ClrLCDFull |
40363 |
239 17728 |
ret |
40366 |
201 |
ANSWER FOR JP:
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ld a, 2 |
40344 |
62
2 |
add a, 5 |
40346 |
198
5 |
jp Continue_Program |
40348 |
195 40354 |
ret |
40350 |
201 |
ret |
40351 |
201 |
ret |
40352 |
201 |
ret |
40353 |
201 |
Continue_Program: |
|
|
ld h, 0 |
40354 |
38
0 |
ld l, a |
40356 |
111 |
B_CALL _DispHL |
40358 |
239 17671 |
B_CALL _getKey |
40360 |
239 18802 |
B_CALL _ClrLCDFull |
40363 |
239 17728 |
ret |
40366 |
201 |
For the last part of this lesson, we will talk about variables. Variables are, of course, stored in RAM to
retain more permanent storage. Thus,
variables can be stored anywhere in RAM that is safe to use. For now, since your ASM program is stored in
RAM, you will store variables as part of the program. Since your variable is part of the program
while it is running, nothing except your program can access that part of RAM,
so your variable is safe if you do not mess with it carelessly.
To store a variable, you use a combination of a label and .db. Using .db, you specify the value you wish the
variable to hold at the beginning of the program. This is usually zero. However, let’s use an example of a number of
lives being equal to 5.
Number_Of_Lives:
.db 5
To understand how to access this, remember that the
variable is stored in RAM. Therefore,
you access the variable using a RAM address.
Just like labels pertain to a particular RAM address (and jp tells the
calculator to jump to that particular RAM address), variable names pertain to
particular RAM addresses. I will tell
you about accessing the variable in a moment, but it is very important you
remember that the value 5 is stored in RAM and accessed by the address where it
is located. On the next page is a small
program, and its translation:
ASM |
RAM ADDRESS ON CALCULATOR |
TRANSLATION, IN DECIMAL NUMBERS |
#include “ti83plus.inc” |
|
|
.org 40339 |
|
|
.db t2ByteTok, tAsmCmp |
40339 |
187
109 |
B_CALL _ClrLCDFull |
40341 |
239 17728 |
ret |
40343 |
201 |
Number_Of_Lives: |
|
|
.db 5 |
40344 |
5 |
So Number_Of_Lives pertains to RAM address 40344. Inside 40344 is the number of lives.
There are many, many different ways to access this
value. For now, use the statement ld a,
(variable name). You always use
parentheses when you want to access whatever is inside of RAM at a particular
address. So by using the statement ld a,
(Number_Of_Lives), you are telling the calculator to access whatever data is in
RAM address 40344. Ld a,
(Number_Of_Lives) is the same as ld a, (40344).
So now a contains the value 5.
On the next page is a
program that demonstrates this.
That recalls a variable.
To store a value to a variable (for right now), register A must contain
the value that you want to store in the variable. Then use ld (Variable), A. On the next page
is an example. It will store the answer
to the addition problem 5 + 7, so that you do not lose the answer to the
problem.
You have enough now to
start your project ASM Gorillas, so in the next lesson we will begin to work on
it.