Hi, I have a main program that is calling subroutines, however when it has finished with the subroutine I issue the RTS command. In some of my program it works absolutly fine and other times it just returns to a random address. I have then issued a JMP (followed by appropriate address)at the end of my subroutine to return to the main program and it works fine. It becomes a problem when a subroutine calls another subroutine, because then I really need a RTS command. I am using a development kit for this to single step the code and I just cannot work out why this is happening. thanks Bal |
|
subroutine problem
Started by ●November 13, 2004
Reply by ●November 13, 20042004-11-13
In addition, verify that you are maintaining stack integrity with paired pushes and pops in your subroutine. Bill At 11:03 AM 11/13/2004, you wrote: >First things first. You have got to remove any and all JMP instructions >at the end of subroutines. If you attempt to do this it may seem to >work, but it will leave the stack pointing to garbage. Your symptom of >having problems with nested subroutines is a good way to see this: when >the inner subroutine exits the stack will no longer be pointing to the >return address of the outer when it exits, so you will be exiting to the >wring place. > >Cardinal rule: never leave a subroutine using a JMP. > >When you have fixed this, try the program again and see what happens. >If it is still playing up, you need to made sure the stack has enought >space for all the levels of nesting that you are using. > >Regards, >Nigel > >bal_gill21 wrote: > > >Hi, > >I have a main program that is calling subroutines, however when it > >has finished with the subroutine I issue the RTS command. In some of > >my program it works absolutly fine and other times it just returns to > >a random address. I have then issued a JMP (followed by appropriate > >address)at the end of my subroutine to return to the main program and > >it works fine. It becomes a problem when a subroutine calls another > >subroutine, because then I really need a RTS command. I am using a > >development kit for this to single step the code and I just cannot > >work out why this is happening. > > > >thanks > > > >Bal > > > > > > > > > > > > > > > >Yahoo! Groups Links > > > > > > > > > > > > > > > > > > > > > >-- >Nigel Johnson >MCSE, MIEEE >VE3ID/G4AJQ > >If time travel ever will be possible, it already is. Ask me again yesterday > >Yahoo! Groups Links > > |
Reply by ●November 13, 20042004-11-13
Either you did not allow enough space for your stack, or some part of your
program is writing in the stack RAM Dave > > From: "bal_gill21" <> > Date: 2004/11/13 Sat AM 11:40:59 EST > To: > Subject: [m68HC11] subroutine problem > > Hi, > I have a main program that is calling subroutines, however when it > has finished with the subroutine I issue the RTS command. In some of > my program it works absolutly fine and other times it just returns to > a random address. I have then issued a JMP (followed by appropriate > address)at the end of my subroutine to return to the main program and > it works fine. It becomes a problem when a subroutine calls another > subroutine, because then I really need a RTS command. I am using a > development kit for this to single step the code and I just cannot > work out why this is happening. > > thanks > > Bal > > > Yahoo! Groups Links |
Reply by ●November 13, 20042004-11-13
The debugging technique for this kind of problem is to check the stach contents on entry to the subroutine and then just before the RTS. any difference in address is a push, pop or BSR misuse. if the current stack address is the same, but the contents are different you will need to step through the subroutine (or any other potentially concurrent routine or interrupt for that matter) to see what is corrupting the return address in the stack. Jim bal_gill21 wrote: >Hi, >I have a main program that is calling subroutines, however when it >has finished with the subroutine I issue the RTS command. In some of >my program it works absolutly fine and other times it just returns to >a random address. I have then issued a JMP (followed by appropriate >address)at the end of my subroutine to return to the main program and >it works fine. It becomes a problem when a subroutine calls another >subroutine, because then I really need a RTS command. I am using a >development kit for this to single step the code and I just cannot >work out why this is happening. > >thanks > >Bal > > >Yahoo! Groups Links > > |
Reply by ●November 13, 20042004-11-13
--- In , "bal_gill21" <bal_gill21@y...> wrote: > I have a main program that is calling subroutines, however when > it has finished with the subroutine I issue the RTS command. In > some of my program it works absolutly fine and other times it just > returns to a random address. The advice given by both Nigel and William is valid, make sure you follow it! If you are using a monitor program (such as BUFFALO) or a bootstrap- mode debugger (such as PCBug or JBug11), the stack pointer will be pre-initialized to a location where there are at least a few bytes available for (nested) subroutine calls. However, the stack space available - esp. if using PCBug/JBug - is VERY limited! Several levels of nested subroutines might be enough to cause PCBug/JBug to fail, since the values (return addresses) getting pushed onto the stack might wind up corrupting the RAM-based 'talker' that these programs use. If you are using a E-series device, or are working on a target platform that has external RAM, you would be better off initializing the stack pointer explicitly to a location where plenty of free RAM is available. On a E-series device with no external RAM, setting the stack pointer to $01FF would be advisable. If, for example, you have RAM mapped at locations $8000-$9FFF, set the stack pointer to, say, $80FF (and use RAM at $8100+ for variables and other data storage). This will give you a comfortably large 256 bytes of stack space. FYI, a subroutine call (each nesting level) consumes a minimum of 2 bytes of stack space, plus whatever values are getting PSH'd inside the subroutine itself. A interrupt service consumes 9 bytes (2 for return address, 6 for registers, 1 for the status word). Monitor programs such as Buffalo, PCBug and JBug utilize interrupt processing to support breakpoints and single-stepping, so at least 9 bytes of your stack will be consumed no matter what else you do in your program. You can change the value of the stack pointer register in your program using the LDS instruction; e.g.: Stack EQU $01FF ;Stack at end of E-series RAM ... Start LDS #Stack ;Initialize stack pointer You will HAVE to initialize the stack pointer to a valid RAM location/region if you intend on running your program in a 'standalone' mode, without the aid of a monitor program. The HC11 does NOT initialize the stack pointer when it is reset! The value in the stack pointer register will be random following a RESET. |
Reply by ●November 14, 20042004-11-14
Thanks for everyones sound advice. I have single stepped the code and discovered that the program is going wrong in the following area: cmpb #$64 ;compare a/d with 100 decimal bhs devThre ;if a/d is >0 jump to 'devThre' cmpb #$A ;compare a/d with 10 decimal bhi devTwo ;if a/d is >10 jump to 'devTwo' I am branching to an appropriate subroutine follwing the certain conditions. As it happens this is happening before any JSR instructions in the rest of the program, so I assume the stack is not reaching its capacity. Would I need to branch to a seperate part of my program and then use the JSR instruction to go to the subroutine, because it is obviously not recording on the stack where it has come from in the main program with the branch instructions. Thanks Bal |
|
Reply by ●November 14, 20042004-11-14
> -----Original Message----- > From: bal_gill21 [mailto:] > Sent: Sunday, November 14, 2004 5:23 AM > To: > Subject: [m68HC11] Re: subroutine problem > > Thanks for everyones sound advice. I have single stepped the code and > discovered that the program is going wrong in the following area: > > cmpb #$64 ;compare a/d with 100 decimal > bhs devThre ;if a/d is >0 jump to 'devThre' So if this condition is true, the processor goes to devThree. This is NOT a SUBROUTINE call, it is an absolute GOTO. I'd use the opposite logic... Test and skip if LESS than 100, Else (GTE), BSR or JSR to your service subroutine. > cmpb #$A ;compare a/d with 10 decimal > bhi devTwo ;if a/d is >10 jump to 'devTwo' > > I am branching to an appropriate subroutine follwing the certain > conditions. As it happens this is happening before any JSR > instructions in the rest of the program, so I assume the stack is not > reaching its capacity. Would I need to branch to a seperate part of > my program and then use the JSR instruction to go to the subroutine, > because it is obviously not recording on the stack where it has come > from in the main program with the branch instructions. > > Thanks > > Bal > * | __O Thomas C. Sefranek |_-\<,_ Amateur Radio Operator: WA1RHP (*)/ (*) Bicycle mobile on 145.41, PL 74.4 http://hamradio.cmcorp.com/inventory/Inventory.html http://www.harvardrepeater.org |
Reply by ●November 14, 20042004-11-14
--- In , "bal_gill21" <bal_gill21@y...> wrote: > > Thanks for everyones sound advice. I have single stepped the code > and discovered that the program is going wrong in the following > area: > > cmpb #$64 ;compare a/d with 100 decimal > bhs devThre ;if a/d is >0 jump to 'devThre' > cmpb #$A ;compare a/d with 10 decimal > bhi devTwo ;if a/d is >10 jump to 'devTwo' Ahh, the problem (and solution) now become clear! The conditional branch instructions, such as BHS and BHI used above, are *NOT* subroutine calls! They work like the relative (BRA) and absolute (JMP) instructions - they are GOTOs. These instructions do not save a return address on the stack. The HC11 does not, alas, provide any conditional subroutine call instructions. The only instructions that truly act as subroutine calls are BSR (relative) and JSR (absolute). You could rewrite your program as shown below to achieve the desired result: CMPA #100 ;Check ADC return value BLO NoDev3 ;If >= 100: BSR DevThre ; Handle >= 100 case BRA Next ; Skip over >10 check NoDev3 CMPA #10 ;Check ADC value again BLS NoDev2 ;If > 10: BSR DevTwo ; Handle > 10 case BRA Next ; Skip over additional checks NoDev2 ... ;Do more checks if needed Next ... ;Continuation point If you actually wish to perform the >10 check after the subroutine for the >0 check is called, remove the "BRA Next" line(s). You will need to ensure that the subroutine(s) you call preserve the value in the A register if this is the case. Use PSHA near the start of your subroutine to save the value in A, and use PULA just before the subroutine RTS to restore it. Note how the use of "reverse logic" branches were used to acheive the desired result. BLO is the logical inverse of BHS, and BLS is the logical inverse of BHI. Other complimentary pairs include: BLT/BGE, BLE/BGT, BEQ/BNE, BCS/BCC, BMI/BPL, and BVC/BVS. Keep on plugging away at it, it will eventually start to fall into place. -- Mark |
Reply by ●November 14, 20042004-11-14
As other have noted the proble is "clear" (to the experienced eye
that is). I don't think anyone actually stated that the only correct calls to a subroutine are BSR and JSR. Under no circumstances should you Branch or JMP to a piece of code that ends in RTS unless you expect that to be the return from the currently called subroutine. I suspect the stack size issue is still present. The key phrase in your discussion was "I am branching to an appropriate subroutine..." We therefore assume that DevThre and DevTwo are labels with a sequence of instructions that end in RTS. Worth noting is the fact that a program is a "holistic" mechanism. snippets of logic may appear coherent, but fail due to the way they are invoked or implemented. These kinds of details are usually expressed in some form of "software design". many of the most confusing problems stem from failing to establish a clear design but instead just begin programming in the hope that eventually a sequence of instructions that works will occur. In the kindest and most constructive way I can, I suggest you read the HC11 instruction reference for each instructions you are using. Be sure you understand the condition code set by each, and the instruction relationships {such as BSR JSR to RTS vs BRA and JMP). also, do a searh in the reference for the instruction you are about to use to find usage examples there. Those examples are at least generally accepted as good practice. Good luck, and hang in there. Jim bal_gill21 wrote: >Thanks for everyones sound advice. I have single stepped the code and >discovered that the program is going wrong in the following area: > >cmpb #$64 ;compare a/d with 100 decimal >bhs devThre ;if a/d is >0 jump to 'devThre' >cmpb #$A ;compare a/d with 10 decimal >bhi devTwo ;if a/d is >10 jump to 'devTwo' > >I am branching to an appropriate subroutine follwing the certain >conditions. As it happens this is happening before any JSR >instructions in the rest of the program, so I assume the stack is not >reaching its capacity. Would I need to branch to a seperate part of >my program and then use the JSR instruction to go to the subroutine, >because it is obviously not recording on the stack where it has come >from in the main program with the branch instructions. > >Thanks > >Bal > > >Yahoo! Groups Links > > |