Atari Assembler Course ----------------------------------- 4.1 The Stack The Stack occupies 256 bytes of memory from $100 to $1FF or all of "page one" and is used by both the processor and the programmer for temporary storage. The stack is filled from its top ($1FF) to its bottom ($100) on a "last-in, first-out" basis. Here are some instructions that utilize the stack: 4.1.1 JSR/RTS - "Gosub/Return" ,-----. | JSR | -- Jump to Subroutine '-----' ,-----. | RTS | -- Return from Subroutine '-----' The JSR operation is similar to the BASIC "GOSUB" command. It allows a program to be structure with subroutines that are used repeatedly. When a subroutine is "called", the 6502 saves its present location in the main program on the stack with the high byte first. When an RTS is encountered at the end of the subroutine, the 6502 recovers the return address back from the stack and continues with the main program. This operation is important to remember if you plan on using the stack for other purposes. 4.1.2 PLA/PSH - "Pull/Push" Stack ,-----. | PLA | -- "Pull" Acc. from Stack '-----' ,-----. | PHA | -- "Push" Acc. on Stack '-----' The PLA instruction removes a byte from the stack, saves it in the accumulator, and moves the stack-pointer to the previous byte. The PHA is the opposite of the PLA; it tranfers the accumulator to the stack and points to the next space on the stack. These operations allows the programmer to use the stack for temporary storage or for passing parameters to subroutines. But, remember that the processor uses the stack to save the return address from a subroutine. 4.1.3 TSX/TXS - Transfer Stack-Pointer ,-----. | TSX | -- Transfer Stack-Pointer '-----' to the X-Register ,-----. | TXS | -- Transfer X-Register to '-----' the Stack-Pointer If the stack is used exstensively, it may fill completely to the bottom of page-one ($100). In some applications, it may be necessary to check how "full" the stack is. The TSX operation transfers the stack-pointer to the X-register so that this condition may be checked. After the TSX instruction, the X register contains the location within page-one where the next byte will go on the stack. The TXS instruction changes the stack-pointer to the value of the X-register. This is used force the stack to point to a certain location within page-one. 4.1.4 The Basic "USR" Command The "USR" command in Atari BASIC is a good example of the Stack at work. Like any Assembly language call with a JSR, the return address (back to BASIC in this case) is saved on the stack. Then, on the stack, BASIC saves the values of the variables as 2-byte numbers. In order to tell how many bytes to take from the stack, the number of variables passed is stored on the stack last. Using the PLA instruction, we can take a look at these numbers and use them in a machine language subroutine. To get back to BASIC, a RTS instruction takes the address originally saved and returns control to the BASIC program. It is important to make sure that all of the parameters have been removed from the stack so that the RTS will use the correct return address! I don't know of a any good discussions of the "USR" command in the texts I've seen. "The Atari Assembler" by Inman & Inman gives it a try in Chapter 3 but I don't recommend this book in general. 4.2 Indexed Addressing So far, we have used "immediate" addressing such as "LDA #10" to operate on constants, "absolute" addressing such as "LDA $1000" to operate on memory, and "relative" addressing like "BEQ LOOP" to control branching. Another form of addressing uses the index registers, X or Y, to give us a variable offset into memory and, naturally, it is called "indexed" addressing. Because this acts as an index into a string or array, it becomes very useful in our programming structures. In the follwing example, a BASIC program and its Assembly Language equivalent are shown for a simple string assignment and indexing. 10 DIM STRING1{10) 20 DIM STRING2{10) 30 STRING1$="EXAMPLE #1" 40 STRING2$=STRING1$ 50 A=ASC(STRING2{4,4)) 60 END 10 *=$4000 ;start at hex 4000. 20 START LDX #9 ;for 0->9... 30 START1 LDA STRING1,X ;move from. 40 STA STRING2,X ;move to. 50 DEX ;for each char. 60 BPL START1 ;until X<0. 70 LDX #3 ;the 4th char. 80 LDA STRING2,X ;of STRING2 90 BRK ;back to cartridge. 100 ;the Acc. will contain the 4th 110 ;character or $4D for ASC("M"). 120 ;The strings will be saved in 130 ;memory right after the program: 140 STRING1 .BYTE "EXAMPLE #1" ;reserve 10 bytes and initialize. 150 STRING2 *=*+10 ;reserve 10 bytes without initializing. 160 .END ;optional end of program. 4.3 Some Assembler "Directives" "Directives" are instruction that tell the Assembler to do something during the assembly of the source code to machine code. They are sometimes called "pseudo ops" because they are used along with the normal op-codes. All directives are identified by a dot or "." at the beginning. The exception is the "*=" or origin directive. Most of the directives effect the way the listing is formated during assembly time and don't generate any code. But, as we've seen, others like the ".BYTE" directive can actually generate data in the program. Read Chapter 4 in the Assembler/Editor manual and read some program listings to become familiar with the use of directives.