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 |
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:
The ()'s around TEXT_MEM indicate that we are talking about a memory location.
In the same way, if we would do the following:
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.
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).
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 (Lives),a ; decrease lives
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.
ret ; end of program
.dw 0 ; highscore word
.ds 20 ; define 20 bytes
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!
ld a,1 ; a is 1
inc a ; a is now 2
push af ; save AF
push de ; save DE
pop de ; get back DE
pop af ; get back AF
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:
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:
With this example, the contents of BC gets copied into HL.
Here is a little table with all the new instructions from this lesson.
||Push a register to the stack
mm can be AF, BC, DE, HL, IX, IY
||POP a register back from the stack
mm can be AF, BC, DE, HL, IX, IY
Previous lesson |