68K Programming in Fargo II
A comprehensive introduction to programming for Fargo II.
Welcome the the wonderfull world of 68k ASM. This will now be your new and permenent home. It is HIGHLY recommended that you only continue if you have the guts and the time to pursue learning 68k. In this doc, you will be given a series of "lessons" to begin your journey into the unknown. In writing this, I am assuming that you at least know TI-BASIC very well (because I will compare) and that you don't know jack about ASM. Which is excactly where I was no more than a few months ago. This doc is going to be built in pieces (Lessons) that you will only find on our home page and Dimension-TI. Put on your thinking cap, take an asprin, and let's get ready to rumble...
Stuff you need to know
All computers understand a very simple language called binary. The 'bi' in the word stands for two, which is exactly the number a letters in this language. In binary, you can only use the numbers '1' and '0' (each character is called a bit. There are different ways to group these and they are named depending how many characters there are in a group. For example, 8 bits form a BYTE; 16 bits form a WORD; 32 bits form a LONGWORD. Different parts of the byte, word, and longword are named different things. The lower-byte of a word is the 8 bits on the right of the word (0101001101100111). The upper-byte is the 8 bits on the left of the word (0101001101100111). The same goes for the lower and higher word in a longword. With lower word being the right 16 bits in a longword.. Personally, I think of the "Titanic" sinking to remember. The right of the word is the "nose of the ship" (The part that sank 1st = lower...get it?) And the left of the word is the "rear of the ship" (The last part to sink = highest) But that's just me... There is much more to binary, but I won't go into that now. Because I remember when I was learning the basics, binary scared the crap out of me. So we'll go into that later. I don't want to frighten you...yet.
The innards of a TI-92
memory - This is where your program is stored (in
binary). This is the RAM. Usually 128K most of the 92's. (Not counting
the 92 plus module)
processor - This, as I'm sure you know, is the
heart and soul of the calc. Without it, the calc wouldn't do a @$%^
thing when you do something as press a key. The processor itself has 2
- registers - A small portion of memory divided into
five sections, built into the processor itself to store instructions in
a program that are soon to be executed.
- data registers - There are 8 of these types of regs.
D0-D7. These regs can hold 32 bits (Longword) of information. You can
store anything you want in these regs. They can also be used as
temporary (fast) variables in a program. But don't worry about that
- address registers - There are 7 of these types
of regs, A0-A6. These regs can also do what the dataregs can (and
more). 32 bits of of info can be stored into them.
- program counter - Abbreviated 'PC', 24 bit
register does one thing and one thing only; it stores the address in
memory of the very next instruction to be excecuted by the processor.
This reg cannot be changed.
- stack register - The register A7 is a special
address reg which is similar to the address regs, but it is used
entirerly different. I have found that toying with the stack reg is
like taking apart a nice car; if you want to run it right ever again
(the calc) you better fix what you changed.
- flag register - This is a 16 bit reg that the
calc uses constantly. The flag register consists of: 0 0 0 X N Z V C.
You can toy with this, but I recommend that you know what you're doing.
The 5 flags to the right are used mainly in operations such as "cmp.x"
or "beq"...etc. And if you have NO idea what the heck I just typed,
- processor - This is where everything is done. Interaction of external parts, arithmitic, EVERYTHING!
Opcodes are the instructions in which you will write your program. Without these, all you would have is data that the calc wouldn't understand. (Please keep in mind that "data" and "opcodes" are two different things!) For example, I will so you one of the easiest opcodes in 68k:
move.x D1,D2 ("move.x" is the opcode, and "D1,D2" is the data.)
What this opcode does is move or copy the data contained in datareg D1 to D2. (similar to "a->b" in TI-BASIC.) "move.x" tells the calc what to do with the data, D1,D2. The "x" is replaced with the length of the data that you want to move. Remember the BYTE, WORD, and LONGWORD? In chosing the length of the data you wish to move, you can move a "part" of the data in D1, to D2. Hmmm...wait...here is an example...
This opcode with the ".b" (byte) extentsion moves only the LOWER byte of D1 to D2. The same goes for the ".w" extension. This will move the LOWER word of D1 to D2. The ".l" extension will move the entire contents of D1 to D2. Hmm...still with me here?
Note: To get the "ins and outs" of just about every single opcode used in Fargo II, I HIGHLY RECOMMEND that you read
The Guide To 68000 Assembly Language, by Jimmy Mardell. (An ASM genius) That guide taught me a good 40-50% of my 68k knowledge.
Source from a sample program
In this section, we will take a look a simple program that displays text on the screen. This is probably the easiest program to write, but it helps teach alot of the basics in 68k. Now in this source, there will be things that you will not understand right now, but I'm putting this in early to paint a picture in your head of what a Fargo program should look like. Don't worry. Everything you see here will be explained.
dc.b "My name is (Your name)",0
dc.b "My 1st 68k prgm",0
This is the format of a Fargo II program. First we will look at the structure of a fargo II assembly file. The following is the format of the fargo II file:
dc.b "Description shown in FBrowser",0
This is the basic structure of a fargo II assembly file. As you can see, the 1st two rows are INCLUDE "xxx.h" This is where you include files called Libraries. For example, the include "flib.h" is a textfile that has a description of the functions in the Flib library. It also provides the functions that are exported by the library. Then follows the "XDEF." It is this that defines the entry point of the program. There are only 5 items that can come after xdef:
_main - This is paramount. This defines the entry point of the prog.
_comment - This is also important. This text is shown in the fargo shell.
_library - This is like _main, but the entry point of a library.
_tibasic - Compiled TI-BASIC code. I've never used it though...
name@xxxx - Entry point of a library function.
After all this stuff starts the program with _main. You will notice the RTS operand. This operand will let the calc know that this is the end of the code (if not at the end of a subroutine...more later) and will return to either the Fargo II shell or the TIOS. You need this. Without it, you're probably get an "address error" and the calc will crash. Then, as the last variable in the program, comes the _comment var. The contents of this var is a zero terminated string. (All strings in a program are zero terminated. The zero lets the calc know the string has ended.) This string is what is displayed in the Fargo shell
Next, I'm sure you're wondering, what on earth does the "dc.b" stand for?!? Well, this is known as a typdefinition. A typdefinition lets the calc know if a var is all characters, or if it must reserve space, and also what the length of the var is. The first two characters "dc" lets the calc know that the var is all characters. Then comes the type. The ".b" lets the calc know that the var is a byte (remember that?). Stings can only be a byte. That goes for all strings. Of course, other vars can either be a word ".w" or a longword ".l".
Some examples for you:
welcome dc.b "Welcome to Dimension TI",0
var1 dc.b 0
var2 dc.w 0
var3 dc.l 0
savespace ds.b (or .w, .l) 10
array dc.w (or .b, .l) 0,0,0,0,0
Oh yeah, the semicolon " ; " after any statement in a program defines a comment. This is completely ignored in the compiler. But this comes in handy to let you know what your program does. (Like the "c" in 92 TI-BASIC) Also, comments do not increase the size of your prog.
Ok, the var "welcome" is a string. "var1" is a var that is the length of a byte and starts at 0. (It could be 1,3...etc...I just choose to start a 0) "var2" is a word. And "var3" is a longword. "Savespace" is a var that allocates space for 10 "var1's" you can say.It is like a list with a dimension of 10, each "slot" starting at 0. "array" is a list with a dimension of 5.
Now at the very end of your program, you place the operand "END". This lets the compiler know that the source code has ended. Don't leave it out.
What the sample program does
Ok. Now that you know the format of a Fargo II file, lets take a deeper look into the sample program. 1st, you might be wondering what "jsr flib::zap_screen" is. Well, "jsr" is an opcode that stands for Jump to Subroutine. What this does is quickly jump to the function "zap_screen" in the flib library. This function clears the screen. Then after the function is complete, the calc returns to the program and continues to the next line of code; which in this case is "move.w #2.-(a7)". -(a7)??? Well, this like described earlier, is the stack pointer. What this code does is move 2 into the stack. Why are we moving 2 into the stack? Usually, tios subroutines require that you push certian things into the stack in order for the subroutine to work. For example the tios function DrawStrXY needs the following pushed into the stack:
DrawStrXY (WORD x, WORD y, BYTE *string, WORD color)
Also, parameters are pushed into the stack backwards. (Just like C) In other words, from right to left. What goes in first here is the 2 = color (note that it's a word). Then the string, "pea string(PC)", then the y postition...etc. Then, after the subroutine is complete, you MUST restore the SP (Stack pointer) to it's original value. If you don't, your calc will crash. To do this, we do "lea 10(a7),a7", this adds 10 to the stack. Why 10? In this case, you must add up the typesizes that were pushed into the stack and add the value of that addition to the stack. In this program, these typesizes were:
Word (move.w #2,-(a7) ) + Pointer (pea string(PC) ) + Word + Word
2 + 4 + 2 + 2 = 10
It is paramount that you correct the stack when calling a subroutine that uses it! (Trust me, I've spent hours debbugging such errors!)
Now, after the contents of string are displayed on the screen with DrawStrXY, the calc jumps to the flib library function "idle_loop". What this does is wait for any key to be pressed, then returns to the program. After comes the RTS operand. After a key is pressed, when this operand is encountered, the calc returns to the Fargo shell or the TIOS. In other words, the program is done.
There we go! Now you should know what the sample program does! Now read over it again and I bet you'll understand much more if not all of it! Now, it is required that you read the fargo.txt document that comes with Fargo II to understand how to set up your computer to compile Fargo II programs.
End of lesson 1
Well, that about does it for now! Play with that sample program, compile it, and see what you get! In the next lesson, lesson 2, we will learn more about Subroutines, how to use pointers (not just the stack), hex, binary, simple arithmitic, and some more neat 68k stuff! Happy programing!
If you have any questions or comments, email us at MrKJM99@aol.com. You can also send us your progs to look at.