TI-86 Assembly Logs Vol. 1
Editor's note: The information contained in this article may be
outdated and/or inaccurate.
Ah... The joys of ASM programming. You're probibly reading this because you have this astounding idea in your head for a new action game, or a new operating system for your 86, and you just can't seem to pull it off with BASIC. To tell you the truth, that's how I started back when I only had my trusty 83. Well, I will tell you know, by the time you get done with this article, you will not be winning and World's Best Tetris Clone awards. As a matter of fact, if you are reading this (and not just criticizing it), you will probibly not be able to program much at all, even after the entire series of these bad boys (there is a reason I labeled this one "Vol. 1"). But, you will a little about the Z80, and a little about the TI-86's internal language.
Now, if you are anything like me, at this point you'd looking at me a little cross-eyed and asking yourself, "What on earth is this ASM I keep hearing about, Phil? Is it an acronym or something?" ASM is what we in the world of programming use so we don't have to remember how to spell 'assembly'. Basically, it got that name bcause most programmers are lazy, including myself. If you don't know what a TI-86 is, I will have to ask you to commit ritual Hari-Kiri to avoid the shame that this has brought upon you family line (please don't. It's just a joke.)
"Okay, Phil. Enough with the funny stuff. I'm starting to have nightmares about this 'Z80' thing attacking the city and taking away all our children!" No need to have such thoughts. When I refer to the Z80, I'm talking about the main processor on the TI-86. This processor is common among the 86's "sister" calculator, the 85, and also the 82, 83, 73, and 80. Once you learn the basics of the Z80, you'll know and understand the basics for all the TI-Calcs mentioned above (excluding the TI-80, which has no ASM ability. Sorry all you TI-80 fans. On a further note, the TI-73 does have the capability for ASM, but no one has found a way to do it yet.)
The next sections will let you in on the workings of the assembler, the basics of the Z80 processor, and some of the TI-86's ASM commands. First, though, I'll run through a list of what you need before you get started.
WHAT YOU NEED
Let's assume for a second that, if you are reading this, you know absolutely nothing about assembly. This is a signal for all you impatient people out there to skip ahead to the next section because you either think you are confident that you have all the programs and files you need, know another form of assembly language, or think I have no clue what I'm talking about.
Step one: the assembler. If you've ever journied into some TI-Calc archive site and took a look at some of the source code, you would notice that it is made up mostly of two- to four-letter acronyms, numbers, letters, and a few '$'s thrown in. That's what you're going to have to write, and what I'm attempting to teach you. As mentioned above, that's aclled 'source code.' This is as close to actual English that assembly language gets. The problem is, though, the only thing the processor understands is 1 and 0, or simple binary. I might get into that later, but understand that everything running through a processor is nothing more than groups of 1's and 0's.
"Huh?" you're probibly wondering. "Then how can I program BASIC, which is a bunch of words. I thought the processor could only understand 1 and 0." Simple. The wonderful people at TI realized that not everyone was skilled in programming Z80 assembly language, so they made is easier. They invented a language (surprisingly similer to computer BASIC) that humans could understand. This is called a 'high-level programming language.' In any high-level, the commands are as close to actual English as programming comes, so you can actually understand what you are telling the processor. In these high-level programming languages (like TI-BASIC, BASIC, C++, Java, VBasic, etc.) something is needed called a command interpriter (or a compiler -- they do the same things). When you tell the calculator a command like
The command has to be sent through the interpriter so it can be converted into assembly language, then into machine code (all the 1's and 0's), then it's fed through the processor. That looks like this:
BASIC Command -----> Command Interpriter -----> Processor -----> Output
"Gee," you say, "why don't you just bypass the command interpriter all together to save time?" Why not? That's the idea behind low-level programming languages. Assebmle is a low-level programming language. Here's how assembly goes through the calculator:
ASM Command -----> Processor -----> Output
Unfortuantely, the calculator has no flipping idea what to do with assembly source code. So, what you need to do is convert all that source into something that the calculator can understand. If you'd look at the paragraph above, you'd note that the BASIC commands are turned into machine code before being sent to the processor. What you have to do before sending an ASM program to the calculator is convert it into machine code. Lucky for you, you don't have to do it all by yourself because of a little program called an assembler.
So, basically, the assembler converts ASM source code into machine language so the processor can understand what you are trying to tell it. Where do you get one? Well, you can get a little program called The 86 ASM Studio. This bad boy helps you write the source code, test it, assemble it, and then send it to your calculator. "Wow!" I exclaimed when I saw this, and you should too. "Some nice person put Notepad, TASM301 (an assembler that I use for my 83), and TI's Graph Link into one program!" This program can be found at TiCalc.Org, URL: http://www.ticalc.org/pub/win/asm/asmstd.zip .
Now, I'm only assuming that you have A TI-86 and a Graph Link, else this software will not work. If you don't have a Graph Link, you are going to have to type the code in manually. If you don't have a TI-86, what's the point in reading this?
All right... Now you've got youself all the software you are going to need. Go ahead and install the 86 ASM Studio. Don't worry, I'll wait. Afterword, Start up the program. It will give you a Notepad-style interface with some interesting buttons on the top. Don't mess around with the buttons! Not yet, at least. You can press them if you want, but you'll be opening new windows and doing things that you might not understand yet. Nothing you can do will destroy your computer, but take my advice and don't play around with the buttons, okay? Press the "new document" button on the top, any you'll find yourself (or should find yourself) looking at a screen like this one:
For the purposes of this Log, please delete the part from 'nop' to 'ProgStart:'. This log was made before this header was placed in the program. It involves the use of an ASM shell, which we are not using right now. You should, deleting the required text, have a screen looking like this:
The very first line of code that the program gives you is this:
This is known as a "pre-processor command." This means that the command is meant for the compiler only. Once you get around to assembling this program, the compiler will follow the command '#include,' but it will not assemble it. All-in-all, this line of code will take up zero bytes on the 86.
The next line of code automatically placed in this program-to-be looks like this:
"What does this all mean, Phil? You are going way too fast for me!" Okay, here's where you'll need to know a little about the way the TI-86 orginizes its memory. When you put your new fangled ASM program onto the calculator, it stores it where ever it finds enough free memory. Then it makes a note of the program's possition in the VAT (that's the 'variable allocation table'). When you run this ASM program, it looks up where the program is stored and how long the program is in the VAT. After that, it has to copy all the information somewhere else in the memory. Why is this done? In all honosty, I'm not sure. But, I can therorize that the processor needs a refrence point the begin processing the code. '.org' tells the processor to copy all the bytes of the program to the area in memory starting at the following address. The 'following address,' in this case, is called "_asm_esec_ram", short for "assembly executable RAM." What (or where) is this on the processor? Well, for that answer we have to go back to that '#include' command.
The compiler has no clue what '_asm_exec_ram' means, so you have to tell it. The file "ti86asm.inc" does that for you. If you open up the file "ti86asm.inc" in a text-editor, you'd see that the very first few lines begin with semicolons, followed by a line that looks like this:
_homeup equ 4A95h
(Your's might also start with '_clrLCDfull equ 4A7Eh, depending on the version of ti86asm.inc you are using. If it's not the first line of the include code, pretend it is, okay?)
This line is telling the compiler "Whenever you see the word '_homeup', replace it with 4A95h." 4A95 is hexidecimal code (the small "h" afterword designates it as hexidecimal. This small "h" can be replaced by a "$" before the number, and it will have the same effect.) 4A95, in normal decimal, is 19093. This means that the instruction 19093 bytes into the memory is the instruction for '_homeup'. The processor, however, sees 4A95h ($4A95) as 100101010010101b (in the case of binary, you can put a '%' before the number, just like with hexidecimal.)
If you were to look through the include file, you'd see that '_asm_exec_ram' is "equated" (equal) to 0D748h. Knowing this, then you'd realize that '.org _asm_exec_ram' copies the program data to the memory starting at memory address $0D748.
In case you haven't figured it out yet, the '.end' command at the end of this pre-made template tells that processor that there is no more assembly code, and it shouldn't look for any more after this point.
Let's say that you wanted to make a simple ASM program that did the same thing as these simple commands:
:Disp "Salute Terra!"
That's all that BASIC sees the program as, but ASM would see it like this:
.db "Salute Terra!",0
Looks pretty complex for only two BASIC commands, eh? That's one of the problems with ASM... it takes many lines of code to do some very simple BASIC commands. Why is this, you ask? All BASIC commands are just a series of ASM commands. When you wall upon a BASIC command, it looks up that command (via the interprater), finds the ASM data in the ROM (read-only memory-- the stuff you can't write to), and sends that data to the processor.
"Okay, wise guy, what's with the jargon? I still don't understand ASM code!" Let me go step-by-step through each of these commands, starting with the first, 'call _clrLCDfull'.
The line 'call _clrLCDfull' can be divided into two parts. The first part is the actual processor command 'call'. This tells the processor to get ready to send to the processor anything at the memory address that follows. Let's just say that, at memory address $0001, there is a command that tells the processor to make poached eggs. Every time you'd use the command 'call $0001', the processor would make you poached eggs.
The second part, the '_clrLCDfull', actually stands for a number. If you'd look a few paragraphs above, you'd see that there is a line in "ti86asm.inc" that looks like this:
_clrLCDfull equ 4A7Eh
When the calculator reads any line with the text "_clrLCDfull" in it, it will automatically replace the text with the number 4A7Eh. Now you're asking, "Phil, why don't I just remember the number instead of '_clrLCDfull?" I mean, the number has only five characters, but the text has eleven! That's too much for my brain to handle!" Well, if you like numbers, then you'd better get real friendly with all 100+ commands for the TI-86. If you choose this route, I will warn you once: get one digit wrong in the memory address for a given command, and your calculator might become as useful as poached eggs.
Time for a quick lesson on numbers. I'll assume that most people reading this have either passed elementary school, or have access to a friend who has passed the 6th grade. If you see any number with no letters in it, that means you are talking in decimal. Counting in decimal is easy:
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11...
The word 'decimal' is derived from the Latin 'deca,' meaning ten. And, to answer your question, no, Romans did not invent the TI-86. Now, if you see any number with either an 'h' after it, or a '$' in front of it, you are talking in hexidecimal. Counting in hexadecimal is a little more compicated then counting in decimal:
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - A - B - C - D - E - F - 10 - 11...
The word 'hexidecimal' comes from the Latin 'hexa' and 'deca.' You know that 'deca' means ten, and now you know that 'hexa' means six (because I told you.) Six plus ten equals sixteen. If you notice the pattern, once you reach the sixteenth number in hexadecimal, you find that it is '10.' In other words, 'A'=11, and 'B'=12, hence '1A'=27, and '1B'=28. So when you see the line that looks like this:
_clrLCDfull equ 4A7Eh
You know that the decimal address is 19070.
For your final "learning to count lesson," there's also binary. The word 'binary' comes from the Latin 'bi,' meaning two (not what you're thinking, I'm sure. Perverts.) True to it's meaning, there are only two digits in binary--zero and one. This is how the calculator, and any other computer, counts:
0 - 1 - 10 - 11 - 100 - 101 - 110 - 111 - 1000 - 1001 - 1010 - 1011...
If you get it, good for you. I'm not going to go into a big hype about it because it's not too important yet.
Now you know how to clear the screen. Type in the following line in your new program:
REMEMBER: The <TAB> must be there, or else the assembler program will not recognize the line as a command. Only labels can be in the first column, which leads me to my next section:
ASM makes labels a lot more fun and easier to remember my letting you determine
the length and names of your labels. To write a label in a program, you just type a word
or phrase in the first column and place a colon after it, like so:
Remember how I told you that the commands in an ASM program
have to be in the first column? Well, this is because the assembler is stupid. It can' tell the
difference between a label and a command, so you have to make the two different by
putting the commands in the second column, or the <TAB> position, and the labels in the
first column, or home position. I named the label 'FIRST_LABEL' instead of
'1ST_LABEL' or 'FIRST LABEL' because you can't put a number as the first digit of a
label, and you can't use spaces. The colon is also VERY important. Without the colon,
the assembler thinks the label is just another command.
Now, "What do I care about lables, Phil?" you ask. Well, the processor sees all text strings as labels too. Here's how it works:
Now the processor knows that the following is all part of the 'STRING' label until either another lebel is defined, or the precessor reaches the end of the program (the latter of which is true in this case.) The processor command to define a string is the '.db' command, or the 'Define Byte' command. I have no idea why it is called 'Define Byte' because you can define strings, numbers, or series of numbers with this command. This is the second processor command that you have learned today ('call' was the first, remember?) Now we have this:
In order to actually put the string data in the string, if it is text, you need to inclose it in quotes. We want the text "Salute Terra!" in the string, so we put this:
.db "Salute Terra!"
But wait! The processor doesn't know that it is at the end of the text string yet. Leaving the string as it is would result in an assembler failure. We need to put a ',0' at the end of the string to tell the assembler and the processor "Enough!" (That's a zero, not the letter 'O,' if you were not sure.) To finish the string, put in the ',0':
.db "Salute Terra!",0
The Load Command
The load command is the most used command in all of assembly. In order to move one piece of information from one place to the next in ASM, you use the load command. The load command is simply 'ld.' The way you use it is like BASIC's '->', or 'Sto'. The difference is, instead of BASIC's order:
:Variable From -> Variable To
ASM reads it backwards:
ld Variable To,Variable From
Remember the syntax, though: 'ld To,From'. You might make up an acronym for it, like "Larry Doesn't Talk Frequently," or something of the sort. I just remember it because I use it so much.
The variable we are loading the string into in order to display it is 'hl'. 'Hl' is one of the most used built-in variables there is, save only for 'a', or the accumulator. Just to get the basics down, any variable built into the processor is called a register. All registers are 8-bit, and all registers have an 8-bit pair, making a 16-bit register. These registers are 'a', 'f', 'b', 'c', 'd', 'e', 'h', and 'l'. They are paired with the register closest to it, so there's 'af', 'bc', 'de', and 'hl'. We are using 'hl' becuase that's what the 'call _puts' uses.
About the other 'call' commands in this program, '_homeup' puts the cursor to the upper-left corner of the screen, and '_puts' displays the string currently loaded in 'hl' at the current curser position. Now look at the program again:
Just to let you know, the '.end.' at the end of the program is to tell both the assembler and the processor that the program is over. Remember, the assembler and the Z80 are both stupid. Also, something I might have neglected to tell you about: The 'ret' command. 'Ret' is short for 'RETURN.' All this command does is either return you back to the TI-OS (or any shell you are operating under,) or it will break you out of a 'jp' command. I'll cover that later.
Now, to assemble, select the 'Assembly' menu and chose the option 'Build and Send To Calculator.' BEFORE YOU DO THIS, PLUG YOUR CALCULATOR INTO YOUR TI GRAPH-LINK. If you do not have a graph link, ignore everything from this part down. Contact me, and I'll tell you how to assemble and type the program in manually.
If everything is set up properly, the program should be sent to your calculator after you save it as something. For now, save it as 'test.asm'. I might refer to it later.
In order to use this new program, you need to have a special BASIC command. If you attempt to run it normally, the calculator will give you an "error 07 syntax." The assembler automatically puts the command 'AsmPrgm' at the begining of the program before it sends it to your calculator. Whenever you attempt to use this command in a BASIC program, it will error you out. To tell the calc that you have an ASM program, find the command in the Catalog called 'ASM('. Use the command to paste 'ASM(' on the screen, then use the 'PRGM' menu to put the program name 'test' on the screen. You should have this:
Now, press <ENTER> and see what all that hard work brought you to:
Congradulations. You have just made your first ASM program. If you have any comments or suggestions, please let me know. I am only an 83 programmer, remember, and I am learning as I am doing this. In the next Log, I'll more than likely go over the simple commands of the processor ('ld', 'jp', 'ret', etc.) and the registers ('a', 'f', 'b', 'c', etc.). I appoligize if this log went a little too fast for some of you, but I didn't want to follow my pattern and tell you how to write to BASIC variables yet (as I did in my 83 ASM Logs.) I suppose a "Hello World" program was the best place to start. (By the way, "Salute Terra" means "Hello World.") Change the text and see what you can get. Add mulitiple strings to display and see what you get. Experiment--that's the only real way you are going to learn this language. Let me warn you, however: BACK-UP ALL OF YOUR DATA if you are plannig on keeping it around for any length of time. ASM is very touchy, and sometimes it will crash your system if you do the wrong thing. I hereby take no responisibility for any damage done to anyone's calculator, computer, or pet dog. (Phew, that felt good...)
Special thanks to Lindsay, Michelle, Emily, Mike, Mike, Mike, and Neely. Thanks for your support and inspiration, though you might not even know it (yet.)
Thanks for your time, and I'll see you in the ASM Log 2!