Karma Universe - demuynck.org Lesson 12
TI-82 ASM Corner :: Programming Guide :: Lesson 12 Back | Home | Search
Lesson 12 : Saving information

In this lesson, you will learn various ways to save information from one of the registers so that you can refer to it later. You will learn about saving to a certain memory address and about the stack.

To system RAM | Inside program | On the stack | Example

To system RAM

You already know that the system RAM has some locations that are safe to be used to store our data. How to do this is very simple: If you want to load 5 to the first byte of TEXT_MEM you'll do the following:

 ld	a,5
 ld	(TEXT_MEM),a
 

The ()'s around TEXT_MEM indicate that we are talking about a memory location. In the same way, if we would do the following:

 ld a,(TEXT_MEM)
 

A would not get the value of TEXT_MEM, but the contents of the memory address would be loaded into A.

Please note that it is only possible to do this with the A register. Only one exception: ld r,(hl) and ld (hl),r where r can be A,B,C,D,E,H or L. 16 bit loads can be done with HL,BC or DE.

Valid examples:

 ld	($800c),a
 ld	($800c),hl
 ld	a,(TEXT_MEM)
 ld	b,(hl)
 ld	(hl),l
 ld	(APD_BUF+10),a
 ld	bc,(TEXT_MEM2+5)
 ld	($8215),de
 ld	a,(bc)
 

Bad examples:

 ld	($800c),e
 ld	($800c),bc
 ld	b,(TEXT_MEM)
 ld	hl,(hl)
 ld	(APD_BUF+10),f
 ld	d,(bc)
 

Often, programmers make their own definitions for memory locations at the beginning of their program. This way, the programs are easier to read and write (also for the programmer).

An example:

.include "ti82.h"
.include "keys.inc"
.org START_ADDR
.db "SuperGame",0

PlayerX=TEXT_MEM        ; byte
PlayerY=TEXT_MEM+1      ; byte
EnemyX=TEXT_MEM+2       ; byte
EnemyY=TEXT_MEM+3       ; byte
Score=TEXT_MEM+4        ; word
TimeLeft=TEXT_MEM+6     ; word
Lives=TEXT_MEM+8        ; byte
GameBoard=APD_BUF       ; 144 bytes
<and so on>

 ...
 ld hl,(Score)          ; get Score
 ...
 ld a,(Lives)
 dec a
 ld (Lives),a           ; decrease lives
 ...
 

Inside program

You can also store your data to areas inside your program, since your program is located in the RAM.

Space for your variables is allocated with .db, .dw or .ds assembler directives. How to use this assembler directives is explained in lesson 4

This method can be useful when saving highscores or the current level, because the information remains in memory even after the program quit back to the shell.

An example:

 ld	hl,(highscore)
 ...
 ret                    ; end of program

highscore:
.dw 0                   ; highscore word
savedgame:
.ds 20                  ; define 20 bytes
 

The stack

Another way of saving registers is pushing them on the stack with the PUSH instruction. You can get them back later with the POP instruction. Only 16 bit registers can be pushed/popped.

So what exactly is the stack? Well, you could see it as a pile of cards. You can put cards on top of it (pushing) and take back the top card (popping). So, the last thing that was pushed onto the stack will be the first thing to be popped and the first thing pushed on the stack will be tha last thing to be popped.

The stack is a FILO buffer, First In Last Out. Please remember this, because errors with pushs and pops mostly cause the calc to crash.

The stack starts from $FFFF and grows backwards. The top location of the stack is stored in the SP register (stack pointer). Each time something is pushed, this register is decreased with 2. When something is popped, it is increased by 2.

There is no limit on the amount of data that you can push to the stack, but remember that if you push too much, you will end up overwriting other information like the VAT or programs!

Example:

 ld	a,1      ; a is 1
 call	routine
 inc	a        ; a is now 2
 ret

routine:
 push	af       ; save AF
 push	de       ; save DE
 ld 	a,10    
 inc	de
 ...
 pop	de       ; get back DE
 pop	af       ; get back AF
 ret
 

This subroutine does not destroy the A,D,E and F registers, thanks to pushing and popping.

Let's take a look at how the stack looks like in the previous example:

Stack

Note: In the image above, the stack pointer starts at $FFFF (is empty) when the routine is started. In reality, this will never be the case, though. This is because the normal TI-OS, as well as the Ash/CrASH shell also place information on the stack. It could even be that your program had already pushed some things onto the stack as well.

Please note that it is NOT necessary to pop back to the same register you pushed. Example:

 push	bc
 pop	hl
 

With this example, the contents of BC gets copied into HL.

New instructions

Here is a little table with all the new instructions from this lesson.

New instructions
Mnemonic Operation
PUSH mm Push a register to the stack
mm can be AF, BC, DE, HL, IX, IY
POP mm POP a register back from the stack
mm can be AF, BC, DE, HL, IX, IY

Previous lesson | Contents | Next lesson