<IMG SRC="pierotating.gif" WIDTH=80 HEIGHT=80 BORDER=0>

Introduction

Lesson 1
Lesson 2
Lesson 3
Lesson 4
Lesson 5
Lesson 6

TI-85 Page
Ash

Welcome to the second lesson of the Ash School! Today you'll learn a little about registers and how to store bytes, words and strings in the memory. You'll also learn some common instructions so you will understand the "Hello world!" program you wrote in the last lesson a bit better.

Contents


Registers

In most programming languages (in fact, all other languages I know) you use variables to store information like bytes, integers, strings and such. But, in assembly there is no such thing as a variable. So how do you do? Inside each processor there are a few very quick ways to store information, the registers. On a PC the most frequently used registers are called ax, bx, cx and dx and on an Amiga, I think, they're called d0, d1, d2 and so on. What are they called on a Z80, which is the CPU on a TI-82?

The common registers are called A, B, C, D, E, H and L (There are other registers, though they aren't important right now). Pretty easy? They are 8-bits registers, which means that you'll fit a byte in them. Now, how do you do if you want to store a word for example? You "simply" put the registers together two and two. There are three register pairs, called BC, DE and HL. As you probably can figure out, the BC register uses both the B and C register. Important also is that you can't combine the registers in another way, ie registers such as BD, HA and so isn't possible. Also important is that if you store something in the B register, it will be destoryed when storing something later in the BC register, because they are the same (sort of).

Since the registers are few you'll need to know how to store things in the memory. This method is a bit slower, so numbers you often use you should store in the registers more often. All calculations require that at least one of the numbers you want to add or sub is stored in a register. Anyway, since the RAM memory is 32k, how do you know where in the memory it's safe to store things? You don't want to write to some location in the memory where other programs are stored because then you might destroy them. Lucky for us is that there are a few places in the memory that aren't used by the TI when where not in "basic-mode". One of those places are the text memory, which starts at address $808F. There you'll fit 8x16 (the text screen size) = 128 bytes. The reason you can use the text memory as storage is that when writing something to the screen, you write it directly to the LCD memory, not via the text memory. You don't have to understand this really, you just need to know that you're able to store things in the text memory. Other places to store things in is the second text memory (128 bytes, starts at $8BDF), the graph memory (756 bytes, starts at $88B8). and the APD backup buffer (756 bytes, starts at $8228). First you should use the text memory, then the second one, then the APD backup buffer and last the graph mem. Of course, if you need to store big arrays, it's perhaps necessary to use the APD backup buffer or the graph mem.

What if you have many variables? How do you do then? 128+128+756+756 = 1768 bytes isn't that much. Then you have to store it directly in the program. The disadvantage of this is that the program gets bigger (since you allocate space in the program).

OK, that was a big explanation of this. Now, how do you use it practically? First you need to now how to explain that you mean a memory address instead of a word. The way to to this is that you put ( ) around the address, for example ($80DF). Then the compiler will now that you mean the address $80DF, not the word $80DF.

LD, the most common instruction

As you saw in the previous lesson, ld is used very often. What does it do? Not so hard to guess actually. LD stands for Load, which means that you store the second argument in the first argument. Example: ld a,53 stores 53 in the A register. Now there are a couple of different ways to do this. A list below show you some ways to use ld.

  • ld d,63
  • ld bc,$7A3B
  • ld ($80DF),a
  • ld a,($80F5)
  • ld b,(hl)
  • ld (de),a
  • ld ($8641),hl

You can probably guess what these instructions will do. As you see I always use the hexadecimal form when I use address location. You should do that, because that is standard. Another thing you may need to know about when storing words is that they are stored "backwards". For example ld bc,$7A3B will put $7A in the C register and $3B in the B registers, not the other way round. Always when you deal with words the LSB (least significant byte) is stored first. The last example, ld ($8641),hl, will store L in ($8641) and H in ($8642).

Sadly, there are some rules you must follow when using ld. Some things that aren't allowed are listed below.

  • You are not allowed to store a 16-bit registers in a 8-bit registers and vice versa.
  • You can't load a 16-bit reg with another 16-bit reg. Ld bc,hl isn't allowed with other words. You have to ld b,h and ld c,l to do that.
  • When you use a direct memory allocation, ($80F5) for example, the other register must be A or a 16-bit register. Ld b,($80F5) is not allowed but ld bc,($80F5) is allowed. Note that (hl) is not a direct memory allocation.
  • An important thing to know is that (hl) acts exactly like other 8-bit registers (with the exception that the A reg is a bit special). You could say that it's an 8th register. (which, in fact, it is if you look at how the opcodes are made) When I say "only registers", I always mean that (hl) is also possible. Because of that, hl is very often used as a memory pointer.

I think that covered the registers we've been through so far. When the other registers are introduced I'll explain how to access them.

Some more instructions

There are a few other instructions that are easy to use that you should now.

Add

Add does an addition. Simple? Yes, except that there are limitations of course. The first arg must be the A reg (if you want to make a 8-bit addition) or HL (16-bit addition). If the first arg is A, then the second arg can be a direct value or a 8-bit register (remember that (hl) acts like an 8-bit register), not a memory location! If the first arg is HL, the the second arg must be a 16-bit register! Add hl,hl is also possible. The answer is always stored in the first register. Some example of correct additions are listed below.

  • add a,7
  • add a,(hl)
  • add a,c
  • add hl,bc

Inc and Dec

Inc and dec are very useful when you want to make small additions or subtractions. They only have one arg, which is a register, 8-bit or 16-bit. Worth notifying is that if you want to add a 8-bit reg (excluding A) with 3, it's smarter to Inc that register three times, because if you for example want to add the C reg with 3, you have to ld a,c \ add a,3 \ ld c,a. That takes four byte (you'll see that if you look at the opcodes of the instructions. Very good to have a book with opcodes when programming) but inc c \ inc c \ inc c only takes three bytes. When it comes to 16-bit reg, it's even more useful to use Inc, especially when you want to add bc with de for example.

Dec works exactly like Inc, but since Sub (see below) is even more limited than Add, you can use many Dec in a row and still it takes lesser bytes than a sub would have done.

Sub

As I said, subtraction is even more limited than addition. That's because you must sub from the A reg. Because of that, you only have one arg, which can be a 8-bit reg or a byte. But what do you do if you want to make a 16-bit sub? Well, there is a trick you can use. There are a 16-bit sub, but it requires that you clears the Carry flag (more about flags in the next lesson). If you want to sub hl with de, you do like this: or a \ sbc hl,dr. Or a is the easiest way to clear the carry. What or really does will be explained in a later lesson.

Back to the "Hello world!" program

Let us first look at the program again.

    #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
    

You should understand the beginning. The reason why we store $0000 in ($800C) is because that ($800C) holds the current cursor position. Since you store a word, both ($800C) and ($800D) will be 0. That's good since ($800C) contains the x-pos and ($800D) contains the y-pos. 0,0 is the top left corner on the screen.

ROM_CALL(D_ZT_STR) display a zero terminated string with start at (hl). Then we must first load hl with the correct address. The string we want to display are stored last in the program (good place for storing constants). Ld hl,Text loads hl with the address of the string.

The last part may be a bit cryptic, but it waits until the mode key is pressed. More about those instructions in the next lesson.





This page is maintained by Dines Justesen. All lessons are based on Jimmy Mårdels Online ZShell School.
(c)1999 Content: Dines Justesen and Jimmy Mårdel; Design, Graphics, Animation: mousewasher's WebDesign
These sites are optimised for IE4+ 800x600