Sie sind auf Seite 1von 5

The Stack

The stack is a last-in-first-out (LIFO) data structure. It is a queue with only one end; that is new items enter at the same point as old items leave. Items leave a stack in the reverse order in which they arrive. A LIFO queue is the same as a stack in conventional English. If you pile books on top of each other and then remove them from the top, it behaves exactly like a stack. In a computer a stack can be used in many ways. However, we are interested in the following three applications of the stack: 1. Storing subroutine return addresses 2. Passing parameters from a program to a subroutine 3. Providing temporary storage (local workspace) in a subroutine. The following diagram illustrates the 68Ks stack. The stack is a data structure that can be located in any region of memory. The stack grows up towards low addresses; that is, the address of an item at the top of the stack is lower than the address of an item at the bottom of the stack. Address register A7 is used as the stack pointer. It should not be used for any other purpose. When an item enters the stack it is said to be pushed on the stack. When an item leaves the stack, it is said to be pulled off the stack.

The 68Ks stack may contain word (16-bit) items or longword (32-bit) items. You may not push a byte element on the stack. This is a hardware limitation imposed by the 68Ks bus mechanism. The word in D0 is pushed on the stack by the instruction MOVE.W D0,(A7). This means that the contents of the stack pointer are decremented by 2 to point at the next free word above the top of stack. Then the contents of D0 are stored in this location. This location now becomes the new top of stack. The next figure shows the state of the stack after executing MOVE.W D0,-(A7) and MOVE.L D1,-(A7). These instructions first push the low-order word of D0 and then the entire value of D1. The value of the stack pointer is first decremented by 2 (to push a word) and then decremented by 4 (to push a longword).

The inverse operation to pushing data on the stack is to pull it off the stack. The instruction MOVE.W (A7)+,D0 pulls the word off the top of the stack and moves the stack pointer down by 2. Consider the following examples. MOVE.L MOVE.W MOVE.L MOVE.W MOVE.W (A7)+,D7 #123,-(A7) #123,-(A7) Temp4,-(A7) 8(A7),-(A7) ;Pull a longword off the top of the stack and put it in D7 ;Push the value 123 on the stack as a 16-bit word. ;Push the value 123 on the stack as a 32-bit longword. ;Push the contents of location Temp4 on the stack. ;Push the word 8 bytes below the top of the stack on to the stack.

Subroutine Call and Return In 68K assembly language you call a subroutine by using the instruction BSR XYZ where XYZ is the name of the subroutine. This symbolic name corresponds to the address of the first instruction in the subroutine. After the subroutine has been executed, you return to the point (i.e., instruction) immediately following the subroutine call. The return address is automatically saved on the stack as a longword. You return from a subroutine by using the RTS instruction. The processor pulls the top longword off the stack and puts it in the program counter to force a return to the calling point. Returning from a subroutine call involves pulling the return address off the stack. Consider the following. . BSR . . . . . RTS XYZ ;Call XYZ ;This is where your return ;This is the subroutine ;Return to point immediately after the call

XYZ

The next diagram demonstrates a subroutine call and a subroutine return. Calling a subroutine pushes the return address onto the stack. Whenever you enter a subroutine, the longword at the top of the stack is always the return address.

Passing a Parameter to a Subroutine When you call a subroutine, you often have to pass parameters to the subroutine. In a high level language you might call subroutine XYZ with parameters P and Q by XYZ(P,Q). In a low-level language, you may push the parameters on the stack immediately before calling the subroutine. The next diagram shows the effect of pushing a parameter on the stack before calling a subroutine. State (c) shows the situation after the subroutine has been called. Note that the parameter is 4 bytes below the top of the stack. You can get this parameter in D7 by means of MOVE.W 4(A7),D7. This instruction means move the word 4 bytes below the word pointed at by the stack pointer into D7.

Using the Stack An Example


We will demonstrate the use of the stack in passing parameters to a subroutine. The example is unrealistically simple and no one would use a subroutine to do something so trivial. However, it clearly illustrates the use of the stack. Consider a subroutine ADD3 that add two numbers and multiplies them by 3. The numbers are passed as 16-bit values to the subroutine, and the result returned on the stack (replacing one of the two parameters). The possible code might be: ORG MOVE.W MOVE.W MOVE.W MOVE.W BSR MOVE.W ADD.L $1000 N1,D0 D0,-(A7) N2,D0 D0,-(A7) ADD3 (A7)+,D0 #2,A7 ;Start of code ;Get number 1 ;Push parameter 1 on the stack ;Get number 2 ;Push parameter 2 on the stack ;Calculate 3(N1+N2) ;Return here and pull result off the stack ;Mend the stack! Reclaim the space taken by N1

ADD3

MOVE.W MOVE.W ADD.W MULU MOVE.W RTS ORG DC.W DC.W

4(A7),D2 6(A7),D3 D2,D3 #3,D3 D3,4(A7) $2000 3 4

;Get N2 under the return address ;Get N1 under N2 ;Do the addition ;Do the multiplication to get 3(N1+N2) ;Return the result in the N2 slot on the stack ;Now go home ;Start of data area ;Dummy data for N1 ;Dummy data for N2

N1 N2

The next diagram demonstrates the state of the stack before the execution of the program, immediately before the subroutine call, and immediately after it. As you can see, parameters N1 and N2 are at 6 bytes and 4 bytes below the stack pointer, respectively, when in the subroutine ADD3.

Note that the notation MOVE.W 4(A7),D2 means move the word that is 4 bytes below that pointer at by address register A7 into data register D2. On return from the subroutine, parameters N2 and N1 are at the top of the stack. Executing MOVE.W (A7)+,D0 pulls the result that we put in N2 off the stack. This leaves the stack with parameter N1 at the top. We no longer need N1 and we can reclaim its stacks space by a dummy pull such as MOVE.W (A7)+,D1. However, we dont want this parameter. We can simply adjust the stack pointer by moving it down 2 bytes with ADD.L #2,A7. Note that a real programmer would write LEA 2(A7),A7 which does the same thing.

Passing a Parameter by its Address


Some languages let you pass parameters by reference rather than by value; that is, you send the address of the parameter to a subroutine. The 68K has an instruction that pushes the address of a parameter on the stack. This is PEA (push effective address). If you wish to push the address of a parameter called P4 on the stack, you write PEA P4. Note that MOVE.W P4,-(A7) would push the value of the parameter on the stack. When you retrieve a parameter passed by reference (address), you have to pull the address off the stack and then access the parameter by address register indirect addressing. Consider the following. PEA BSR . MOVE.L MOVE.W P4 ABC 4(A7),A0 (A0),D0 ;Push the address of P4 on the stack ;Call ABC ;Pull address of P4 off the stack and put in A0 ;Get the value of P4

ABC

. RTS

;Return

Note that retrieving a parameter by reference is a two step operation. The first part is to get the address and the second part is to get the value pointed at by that address. Note also that we used a .L operation to retrieve the address and a .W operation to retrieve the value of the parameter. All addresses are longword, whereas parameters may be bytes, words, longwords or anything you want.

Important Points
1. The stack is a last-in-first out queue maintained by the computer. The 68K uses address register A7 to point at the top of the stack. You can write A7 or SP in 68K programs; for example: MOVE.W 24,-(SP) 2. You can push a word or longword on the stack by MOVE.W source,-(A7) where source is any valid addressing mode. 3. You can pull a word off the stack by MOVE.W (A7)+,destination where destination is any valid addressing mode. 4. Making an error with a stack operation will invariably crash a program. 5. When you call a subroutine, the return address is pushed on the stack. When you return from the subroutine, the return address is pulled. 6. You return from a subroutine with an RTS instruction. You NEVER jump out of a subroutine directly with a BRA or JMP instruction. Doing this would leave the return address on the top of the stack. 7. You can call a subroutine with BSR or JSR (branch to subroutine and jump to subroutine). These two instructions have the same effect. The difference between them lies in the addressing modes they support. 8. The instruction PEA pushes an address on the stack and is used to pass a parameter by reference (address).

Das könnte Ihnen auch gefallen