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

  • View

  • Download

Embed Size (px)

Text of Stacks and Subroutines. Some example stacks Stacks and subroutine usage The stack is a special area...

  • Stacks and Subroutines

  • Some example stacks

  • Stacks and subroutine usageThe stack is a special area of the random access memory in the overall memory systemThe stack is used forGeneral data storage (limited)Temporary data storage (true)Parameter and control information storage for subroutines (yes!)

  • StackLast-in, first-out (LIFO) structureAll access is at the top of the stackOperationsPushPlaces an item onto the stackPullRemoves an item from the stackSome (most!) people use the term popBottom of the stack is at highest memory address, and top of the stack is at the lowest addressStack grows from high to low addressCont..

  • StackFor EVBU, stack is usually placed at $01FFStack Pointer (SP)Register that points to the memory location immediately preceding the top of the stackIn other words, the SP normally contains the address for a new data item to be pushedCont..

  • HC11 Implementation

  • PUSH InstructionsPush instructionsPSHA, PSHB, PSHX, PSHYStores data in memory at address pointed to by SPDecrements SPFor 16-bit values, low-order byte is pushed first, followed by high-order byteHow can we push CCR?

  • PUSH InstructionsPull instructionsPULA, PULB, PULX, PULYIncrements SPLoads data from memory address pointed to by SP

  • Other Stack OperationsOther stack operationsCan modify or read the SPLDSLoad the SPSTSStore the SPINSIncrement SPDESDecrement SPTSXTransfer SP+1 to IXTSYTransfer SP+1 to IYTXSTransfer IX-1 to SPTYSTransfer IY-1 to SP

  • StacksStacksRemember to initialize SP at beginning ofprogramImportant to pull data in reverse order that you pushed itNote that SP points to empty memory location (= location where next value will be stored)

  • Using the StacksUsing the stackPassing parameters to subroutines (more on this later)Temporary storage68HC11 has limited number of registersUse stack to preserve register valuesExample: Multiply ACCA and ACCB, round to 8 bitsPSHB ; save value in ACCBMUL ; ACCD = ACCA*ACCBADCA #$00 ; round to 8 bitsPULB ; restore ACCBCont..

  • Using the StacksUsing the stackYou can also use the stack to save intermediatevaluesExample: (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 $E000BEGIN: LDS #$FF ; initialize SPLDAA $1031 ; get x valueTAB ; square itCont..

  • Using the StacksMULADCA #$00 ; round to 8 bitsPSHA ; save itLDAA $1032 ; get y valueTAB ; square itMULADCA #$00 ; round to 8 bitsPULB ; retrieve first resultABA ; add them

  • Dangers Using the StacksDangers in using the stackOverflowToo many pushesStack grows so large that it overwrites portions of memory that are being used for other purposesExample:ORG $E0FOO RMB 2ORG $E000LDS #$FF ; initialize SPLDAB #$FF ; initialize loop countLOOP:Cont..

  • Dangers Using the StacksPSHA ; push value on stackDECB ; decrement countBNE LOOP ; and repeatUnderflowToo many pullsSP points to address higher than the intended bottom of the stackThe HC11 does not protect you from overflow or underflow!Only way to recover is to reset the systemBe aware of the stack size that your program needs.Cont..

  • Dangers Using the StacksTypical memory layout for EVBU:512 bytes of RAM ($00-$1FF)$00 - $FF used by Buffalo monitorDont use these locations in your programsUser variables should start at $100 ($100-?)Stack starts at $1FF (? - $1FF)More variables = less stack space

  • SubroutineWhy use them?Provides modularity to reduce program complexityCreates many smaller, but more easily developed and tested program unitsMay save on memory space (to store program)Can be reused in different parts of a programCan be placed in a library for use by many programs and applicationsSubroutines should . . .Be small, to ease writing, testing, and modifyingHave a well defined purposeHave a well defined interfaceCont..

  • SubroutineBe well documented (like the rest of the program!) Describe input parametersRegisters, memory locations, values on the stack, etc.Describe output parametersRegisters, memory locations, stack, condition codesDescribe any side effectsRegisters that are changed, condition codes, etc.

  • Example of proper Documentation FormatExample 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;*******************************

  • Calling SubroutinesCalling a subroutineJSR sbrBSR sbrAddress of next instruction (return address) is pushed onto the stackThis is the current value of PCPC is loaded with the starting address of the subroutineNext instruction fetched will be from the subroutine

  • Returning SubroutineReturning from a subroutineRTS instructionMust be the last instruction in subroutinePops return address off the stack, loads it into PCNext instruction fetch will be the instruction following the JSR/BSRIf 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

  • Subroutine Parameter PassingSubroutine parameter passing -- how are the parameters / arguments for the subroutine passed to it?RegistersParameters are placed in predetermined register locationsSimple and fastNumber of parameters is limited by the number of "free" registersCode is not reentrantDedicated memoryA series of (predetermined) memory locations are used to hold the parametersCont..

  • Subroutine Parameter PassingSimple, but added overhead due to memory operationsPossible to pass many parametersCode is not reentrantPointer to memoryPass the subroutine a register value containing the address of the parameters in memoryMore complex, extra overhead for use of the pointerCode is reentrantUse the stackParameters, in addition to the return address, are pushed onto the stack -- the combination is called the stack frameYou must push the parameters before the JSR/BSRCont..

  • Subroutine Parameter PassingRequires care in manipulating the parametersDont forget about the return address!Many parameters can be passedSeparate parameter stack can be created and used in addition to the system stackCode is reentrant

  • ExampleExample:Timing delayWrite 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 codesMain program:LDAB #$0A ; delay for 10 msJSR DELAY

  • ExampleExample: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 valuesLDAB #$A8PSHA ; push them on the stackPSHBJSR MAX ; find the maxPULA ; pull max off stack

  • ExampleExample:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 numbersCont..

  • ExamplePULACBA ; compare themBGT A_IS_MAX ; branch if ACCA > ACCBB_IS_MAX:PSHB ; return the value in ACCBBRA MAX_EXITA_IS_MAX:PSHA ; return the value in ACCAMAX_EXIT:PSHY ; put return address back on stackRTS ; and return

  • ExampleExample:Convert an 8-bit hex number into 2 ASCII charactersFor example, convert $3F into 3 and FThe 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 numberPSHAJSR HEX_TO_ASCII ; convert itPULB ; ACCB = 3 = $33PULA ; ACCA = F = $46

  • ExampleExampleConverting hex digit to 2 ASCII charactersPseudo code:Get hex digit from stackConvert lower nibble to ASCIIPush char on stackConvert upper nibble to ASCIIPush char on stackReturnWell use a second subroutine to convert a nibble to ASCIINote that the ASCII codes for 0-9 are $30-$39, and the codes for A-F are $41-$46Cont..

  • ExamplePseudo code:Add #$30 to nibbleIf (result > $39)Add #$07Return

  • ExampleExample:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 ACCACont..

  • ExampleTPA ; save CCRPSHAADDB #$30 ; convert to ASCIICMPB #$39 ; is nibble > 9?BLS CN_EXIT ; branch if notADDB #$07 ; for A-FCN_EXIT:PULA ; restore CCRTAPPULA ; restore ACCARTS ; return

  • ExampleExample:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 addressCont..

  • ExamplePULA ; get hex numberTAB ; copy it to ACCBANDB #$0F ; get lower nibbleJSR CONVERT_NIBBLEPSHB ; save ASCII on stackTAB ; get hex number againLSRB ; get upper nibbleLSRBLSRBLSRBJSR CONVERT_NIBBLECont..

  • ExamplePSHB ; save ASCII on stackPSHY ; push return addressR