Thursday, October 16, 2003

Computer architecture
Computer Systems 2nd Edition
J. Stanley Warford
Section 6.2 Stack Relative Addressing and procedure Calls

In C++ procedure call changes flow to the first line of the procedure. In assembler we have to do much more work. The higher level C++. Because of abstraction we miss the pushing of information on the stack that the machine code actually has to do. To do those we use the JSR command. The JSR pushed the program counter onto the stack and then loads the operand into the program counter. To do the JSR it should be done in immediate mode. To return from the called routine we use the RTS instruction which pops the address back off the stack and into the program counter.

Program 6.7
In program 6.7 we just make three calls to the procedure call, one after the other.

Stack-Relative Addressing
One of the steps that the JSR does is to decrement the sack counter by 2. It does this because it works from the top down in the stack. If we want to add and remove things to the stack ourselves we have to have a way to decrement and to increment the stack pointer as well. ADDSP allows us to add a value to the stack pointer.

Program 6.8
Program 6.8 uses two commands to put information on the stack.

LOADA c#/r/,i
STYBTA d#-1,s


This puts an r in the register a and then the STYBTA stores the r in the stack pointer -1. We do not have to know the memory location of the pointer as it is relative addressing.
The program after it loads the data then moves the pointer with the ADDSP d#-4,i command. This moves the pointer in negative (downward) direction which is what we need as the stack builds down from the top. Next the program pulls information of the stack and outputs it. In the end the ADDSP d#4,i sets the counter back to the original place. While this does not erase the information in memory, it does remove it from use. Now the pointer can use those memory locations again (overwriting the information there when it does).

Program 6.9
In order for us to be able to go to the subroutine, then we have to put any local variables on the stack. The reason why is that we could need the memory location or even wind up inadvertently changing the variables. For that reason, variable values should be put on the stack by loading them into register A and writing them to a stack memory location and then ADDSP d#-2,i moves the counter down. (see the same instructions above in program 6.8). Once that is done we can jump to the subroutine (in this case printBar).
The subroutine now needs to set up its memory needs. We do this by using .EQUATE at the start to set up memory locations. This sets the information on the stack. We can then use relative addressing to access them. At the end use a ADDSP with a positive number to dealocte any local variables used. It then RTS to go back to the main routine. Once there the main routine pop the information back off and go on with its business. The numbers used in this program are good for this program only. The compiler (or coder) would have to allocate memory in line with the size variables that he is using.
All of this is hidden from us by the higher level languages like C++.

Program 6.10
Program 6.9 only called a subroutine (a function in C++, but a function that does not return a value). In this case we are doing a function and this function will be returning a value. Remember stated above that the information is still on the stack when we return to the main program. That fact means that the calling routine (in our case the main program) can now call that information off of the stack and use it (even though the stack pointer is back above it, we use relative addressing).

No comments:

Post a Comment