1 / 38

Stacks and Subroutines

Stacks and Subroutines. Some example stacks. Stacks and subroutine usage. The stack is a special area of the random access memory in the overall memory system The stack is used for General data storage (limited) Temporary data storage (true)

edric
Download Presentation

Stacks and Subroutines

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Stacks and Subroutines

  2. Some example stacks

  3. Stacks and subroutine usage • The stack is a special area of the random access memory in the overall memory system • The stack is used for • General data storage (limited) • Temporary data storage (true) • Parameter and control information storage for subroutines (yes!)

  4. Stack • Last-in, first-out (LIFO) structure • All access is at the top of the stack • Operations • Push • Places an item onto the stack • Pull • Removes an item from the stack • Some (most!) people use the term “pop” • Bottom of the stack is at highest memory address, and top of the stack is at the lowest address • Stack grows from high to low address Cont..

  5. Stack • For EVBU, stack is usually placed at $01FF • Stack Pointer (SP) • Register that points to the memory location immediately preceding the top of the stack • In other words, the SP normally contains the address for a new data item to be pushed Cont..

  6. HC11 Implementation

  7. PUSH Instructions • Push instructions • PSHA, PSHB, PSHX, PSHY • Stores data in memory at address pointed to by SP • Decrements SP • For 16-bit values, low-order byte is pushed first, followed by high-order byte • How can we push CCR?

  8. PUSH Instructions • Pull instructions • PULA, PULB, PULX, PULY • Increments SP • Loads data from memory address pointed to by SP

  9. Other Stack Operations • Other stack operations • Can modify or read the SP LDS Load the SP STS Store the SP INS Increment SP DES Decrement SP TSX Transfer SP+1 to IX TSY Transfer SP+1 to IY TXS Transfer IX-1 to SP TYS Transfer IY-1 to SP

  10. Stacks • Stacks • Remember to initialize SP at beginning of • program • Important to pull data in reverse order that you pushed it • Note that SP points to empty memory location (= location where next value will be stored)

  11. Using the Stacks • Using the stack • Passing parameters to subroutines (more on this later) • Temporary storage • 68HC11 has limited number of registers • Use stack to preserve register values • Example: Multiply ACCA and ACCB, round to 8 bits PSHB ; save value in ACCB MUL ; ACCD = ACCA*ACCB ADCA #$00 ; round to 8 bits PULB ; restore ACCB Cont..

  12. Using the Stacks • Using the stack • You can also use the stack to save intermediate • values • Example: (Listing 3.1 in text) This calculates x squared plus y squared. x and y are 8-bit numbers stored in addresses $1031 and $1032. The 8-bit result is put in ACCA. ORG $E000 BEGIN: LDS #$FF ; initialize SP LDAA $1031 ; get x value TAB ; square it Cont..

  13. Using the Stacks MUL ADCA #$00 ; round to 8 bits PSHA ; save it LDAA $1032 ; get y value TAB ; square it MUL ADCA #$00 ; round to 8 bits PULB ; retrieve first result ABA ; add them

  14. Dangers Using the Stacks • Dangers in using the stack • Overflow • Too many pushes Stack grows so large that it overwrites portions of memory that are being used for other purposes • Example: ORG $E0 FOO RMB 2 ORG $E000 LDS #$FF ; initialize SP LDAB #$FF ; initialize loop count LOOP: Cont..

  15. Dangers Using the Stacks PSHA ; push value on stack DECB ; decrement count BNE LOOP ; and repeat • Underflow • Too many pulls • SP points to address higher than the intended bottom of the stack • The HC11 does not protect you from overflow or underflow! • Only way to recover is to reset the system • Be aware of the stack size that your program needs. Cont..

  16. Dangers Using the Stacks • Typical memory layout for EVBU: • 512 bytes of RAM ($00-$1FF) • $00 - $FF used by Buffalo monitor • Don’t use these locations in your programs • User variables should start at $100 ($100-?) • Stack starts at $1FF (? - $1FF) • More variables = less stack space

  17. Subroutine • Why use them? • Provides modularity to reduce program complexity • Creates many smaller, but more easily developed and tested program units • May save on memory space (to store program) • Can be reused in different parts of a program • Can be placed in a library for use by many programs and applications • Subroutines should . . . • Be small, to ease writing, testing, and modifying • Have a well defined purpose • Have a well defined interface Cont..

  18. Subroutine • Be well documented (like the rest of the program!) • Describe input parameters • Registers, memory locations, values on the stack, etc. • Describe output parameters • Registers, memory locations, stack, condition codes • Describe any side effects • Registers that are changed, condition codes, etc.

  19. Example of proper Documentation Format • Example of proper documentation format: ;****************************** ; Function: ToUpper ; This function replaces all lower-case ; characters in a string with upper-case. ; The end of the string is marked with ; $00. ; Input: IX = starting address of string ; Output: none ; Registers affected: ACCA, CCR ;*******************************

  20. Calling Subroutines • Calling a subroutine JSR sbr BSR sbr • Address of next instruction (return address) is pushed onto the stack • This is the current value of PC • PC is loaded with the starting address of the subroutine • Next instruction fetched will be from the subroutine

  21. Returning Subroutine • Returning from a subroutine • RTS instruction • Must be the last instruction in subroutine • Pops return address off the stack, loads it into PC • Next instruction fetch will be the instruction following the JSR/BSR • If your subroutine manipulates the stack, be aware of where the return address is stored. • It must be at the top of the stack when you execute the RTS

  22. Subroutine Parameter Passing • Subroutine parameter passing -- how are the parameters / arguments for the subroutine passed to it? • Registers • Parameters are placed in predetermined register locations • Simple and fast • Number of parameters is limited by the number of "free" registers • Code is not reentrant • Dedicated memory • A series of (predetermined) memory locations are used to hold the parameters Cont..

  23. Subroutine Parameter Passing • Simple, but added overhead due to memory operations • Possible to pass many parameters • Code is not reentrant • Pointer to memory • Pass the subroutine a register value containing the address of the parameters in memory • More complex, extra overhead for use of the pointer • Code is reentrant • Use the stack • Parameters, in addition to the return address, are pushed onto the stack -- the combination is called the stack frame • You must push the parameters before the JSR/BSR Cont..

  24. Subroutine Parameter Passing • Requires care in manipulating the parameters • Don’t forget about the return address! • Many parameters can be passed • Separate parameter stack can be created and used in addition to the system stack • Code is reentrant

  25. Example • Example: • Timing delay • Write a subroutine that will delay for a specified number of milliseconds. The delay time is passed as a parameter in ACCB. • The subroutine should also preserve the contents of all registers as well as the condition codes • Main program: LDAB #$0A ; delay for 10 ms JSR DELAY

  26. Example • Example: • Write a subroutine to find the maximum of two signed 8-bit numbers. The two numbers are passed to the subroutine on the stack, and the maximum is returned to the calling routine on the stack. • Main program: LDAA #$73 ; load the 2 values LDAB #$A8 PSHA ; push them on the stack PSHB JSR MAX ; find the max PULA ; pull max off stack

  27. Example • Example: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Subroutine - MAX ; This subroutine returns the maximum of 2 ; signed 8-bit numbers. ; Input - The 2 numbers are passed on the stack ; Output - The maximum is returned on the stack ; Registers used - ACCA, ACCB, IY, CCR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MAX: PULY ; save return address PULB ; get the 2 numbers Cont..

  28. Example PULA CBA ; compare them BGT A_IS_MAX ; branch if ACCA > ACCB B_IS_MAX: PSHB ; return the value in ACCB BRA MAX_EXIT A_IS_MAX: PSHA ; return the value in ACCA MAX_EXIT: PSHY ; put return address back on stack RTS ; and return

  29. Example • Example: • Convert an 8-bit hex number into 2 ASCII characters • For example, convert $3F into ‘3’ and ‘F’ • The hex number is passed to the subroutine on the stack, and the 2 ASCII characters are returned on the stack, with the high-order character on top. • Main program: LDAA #$3F ; get hex number PSHA JSR HEX_TO_ASCII ; convert it PULB ; ACCB = ‘3’ = $33 PULA ; ACCA = ‘F’ = $46

  30. Example • Example • Converting hex digit to 2 ASCII characters • Pseudo code: Get hex digit from stack Convert lower nibble to ASCII Push char on stack Convert upper nibble to ASCII Push char on stack Return • We’ll use a second subroutine to convert a nibble to ASCII • Note that the ASCII codes for 0-9 are $30-$39, and the codes for A-F are $41-$46 Cont..

  31. Example • Pseudo code: Add #$30 to nibble If (result > $39) Add #$07 Return

  32. Example • Example: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Subroutine - CONVERT_NIBBLE ; This subroutine converts a nibble (4-bit value) ; to ASCII. ; Input: ACCB contains the nibble ; Output: ACCB contains the ASCII code ; Registers affected: None ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CONVERT_NIBBLE: PSHA ; save ACCA Cont..

  33. Example TPA ; save CCR PSHA ADDB #$30 ; convert to ASCII CMPB #$39 ; is nibble > 9? BLS CN_EXIT ; branch if not ADDB #$07 ; for A-F CN_EXIT: PULA ; restore CCR TAP PULA ; restore ACCA RTS ; return

  34. Example • Example: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Subroutine - HEX_TO_ASCII ; This subroutine converts an 8-bit hex number ; to two ASCII digits. ; Input: Hex number is passed on the stack ; Output: ASCII characters are returned on the ; stack, with the high-order nibble on top. ; Registers affected: ACCA, ACCB, IY, CCR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HEX_TO_ASCII: PULY ; save return address Cont..

  35. Example PULA ; get hex number TAB ; copy it to ACCB ANDB #$0F ; get lower nibble JSR CONVERT_NIBBLE PSHB ; save ASCII on stack TAB ; get hex number again LSRB ; get upper nibble LSRB LSRB LSRB JSR CONVERT_NIBBLE Cont..

  36. Example PSHB ; save ASCII on stack PSHY ; push return address RTS ; and return

  37. Summary • Summary • Stack • Be sure to initialize the stack pointer at the beginning of your program LDS #$1FF • Don’t do this if you’re calling your program from Buffalo • Buffalo initializes SP for you • Push and Pull operations • Remember SP points to next empty location

  38. Summary • Summary • Subroutines • Break your program into subroutines • Well-defined (and documented!) function • Well-defined (and documented!) interface • Passing parameters • Use registers if possible • Else, use stack if needed • Don’t forget about the return address

More Related