Hey guys, back again with another problem. I have the following program: BEGIN_PROG ... JMP NON_WORKING_LOOP ... ... ... NON_WORKING_LOOP PSHA PSHB ... JSR NON_WORKING_SR ... NON_WORKING_SR ... BEQ EXIT_LOOP RTS EXIT_LOOP PULB PULA *JMP WORKING_LOOP ;This point is successfully reached(checked) RTS ;Problem is here WORKING_LOOP ... As you can see, in the beginning of my program, I'm jumping to a loop (NON_WORKING_LOOP) where is save the stack and then jump to another subroutine(NON_WORKING_SR). This SR has a condition BEQ to EXIT_LOOP, otherwise RTS. The problem I'm having(atleast I think this is where the problem occurs) is that when I BEQ to EXIT_LOOP, the RTS in EXIT_LOOP actually returns to NON_WORKING_LOOP rather than BEGIN_PROG(where I thought it should go). Everything in the code works because I've tested it with a JMP WORKING_LOOP statement which is executted successfully. So my question is: Is that what is really going on? Is the RTS from EXIT_LOOP returning to NON_WORKING_LOOP? Or am I doing something else wrong? Here is what I thought is going on: BEGIN_PROG-->NON_WORKING_LOOP-->NON_WORKING_SR--/->NON_WORKING_LOOP \->EXIT_LOOP--------- --->BEGIN_PROG Any ideas on this would be appreciated! Thanks! |
|
RTS problem
Started by ●November 21, 2004
Reply by ●November 21, 20042004-11-21
I think the rule is: if you push n bytes then call a jsr, the jsr must rts,
then the caller must pull n bytes. One must NEVER jump out of a subroutine with items on the stack.... unless you are writing a 'kernel' or 'task switcher' or 'coroutines' or other comp-sci. The stack must grow and shrink symmetrically |
|
Reply by ●November 22, 20042004-11-22
There are actually two things going on, and show that you've missed the fundamental operation of the JSR/RTS pair. When you JSR, the 68hc11 pushes the address of the -next- instruction (the one immediately following the JSR line) onto the stack. That's two bytes. This is called the "return address", since it's where you'll return to. Then, in the subroutine, you can do anything you want with the stack (push,pull)... but when you arrive at an RTS instruction, the stack had better be back to where it was at the start, so that it's pointing at those two bytes pushed by the JSR. What the RTS -does- (pure and simple) is pull the stack's contents into the Program Counter, (PC) and that's it. The 68hc11 then uses the PC to fetch the next instruction it should execute. Since the JSR put the address of the line following the JSR onto the stack, and the RTS pulled that address back into the PC, then the next instruction which will execute will be the one following the JSR. It's perfectly legal (but usually bad practice) to push something onto the stack before doing the JSR, and have the subroutine -reference- it. (not PUL, but merely look at it). Then, when you return from the subroutine, you can pop it to restore the stack to its original state. The buggy program example has two faults: (a) depending upon the path at the BEQ EXIT_LOOP you may or may not do that PUL. (so the stack condition would be messed up on one brach, but not the other. Life in the calling program would therefore become confused) (b) your PUL grabbed one of the JSR'd address bytes, NOT the register you pushed on the stack before the JSR. Advanced programmers sometimes -do- intentionally mess up the stack, but they will take additional steps to handle the situation. One example would be, in the subroutine, to PULY the "return address" into the Y register, do whatever fiddles the subroutine needed to do, and then (instead of an RTS), do a JMP 0,Y as the "return". have fun --dick --- In , "nimish_sudan" <nimish_sudan@y...> wrote: > > Hey guys, back again with another problem. I have the following > program: > BEGIN_PROG ... > JMP NON_WORKING_LOOP > ... > ... > ... > NON_WORKING_LOOP PSHA > PSHB > ... > JSR NON_WORKING_SR > ... > NON_WORKING_SR ... > BEQ EXIT_LOOP > RTS > > EXIT_LOOP PULB > PULA > *JMP WORKING_LOOP ;This point is successfully reached(checked) > RTS ;Problem is here > > WORKING_LOOP ... > As you can see, in the beginning of my program, I'm jumping to a loop > (NON_WORKING_LOOP) where is save the stack and then jump to another > subroutine(NON_WORKING_SR). This SR has a condition BEQ to > EXIT_LOOP, otherwise RTS. The problem I'm having(atleast I think > this is where the problem occurs) is that when I BEQ to EXIT_LOOP, > the RTS in EXIT_LOOP actually returns to NON_WORKING_LOOP rather > than BEGIN_PROG(where I thought it should go). Everything in the > code works because I've tested it with a JMP WORKING_LOOP statement > which is executted successfully. So my question is: Is that what is > really going on? Is the RTS from EXIT_LOOP returning to > NON_WORKING_LOOP? Or am I doing something else wrong? Here is what I > thought is going on: > BEGIN_PROG-->NON_WORKING_LOOP-->NON_WORKING_SR--/->NON_WORKING_LOOP > \->EXIT_LOOP--------- > --->BEGIN_PROG > > Any ideas on this would be appreciated! > Thanks! |
Reply by ●November 23, 20042004-11-23
At 2004-11-21 19:09, wrote: >I think the rule is: if you push n bytes then call a jsr, the jsr must rts, >then the caller must pull n bytes. One must NEVER jump out of a subroutine >with items on the stack.... unless you are writing a 'kernel' or 'task switcher' >or 'coroutines' or other comp-sci. The stack must grow and shrink >symmetrically People that don't understand things like these shouldn't program in assembler but should program in a language like C which will take care of these things. By the way, nobody should have to program in assembler anymore (unless for fun or to write task switchers etc.) It's a complete waste of human energy and especially in the case of the 6811 you can't write much more effective code than a good compiler can (perhaps you can squeeze out 30% better code, but it will be totally unreadable) and ROM is cheap by now. I consider writing in assembler a modern form of torture (often self-torture unfortunately ;-). Greetings, Jaap -- Chip Directory -- http://www.chipdir.biz/ -- http://www.chipdir.info/ -- http://www.chipdir.net/ -- http://www.chipdir.nl/ -- http://www.chipdir.org/ -- And about 30 other mirror sites world-wide. -- -- To subscribe to a free 'chip issues, questions and answers' -- mailing list, send a message to with -- in the body 'subscribe chipdir-L'. About 500 experts are -- willing to think with you about electronics problems etc. |
Reply by ●November 23, 20042004-11-23
----- Original Message ----- From: "Jaap van Ganswijk" <> To: <> Sent: Tuesday, November 23, 2004 10:09 AM Subject: Re: [m68HC11] RTS problem > At 2004-11-21 19:09, wrote: > >I think the rule is: if you push n bytes then call a jsr, the jsr must rts, > >then the caller must pull n bytes. One must NEVER jump out of a subroutine > >with items on the stack.... unless you are writing a 'kernel' or 'task switcher' > >or 'coroutines' or other comp-sci. The stack must grow and shrink > >symmetrically > > People that don't understand things like these > shouldn't program in assembler but should program > in a language like C which will take care of these > things. I'd go further and say people who don't understand such things should not program at all until they learn some more about how CPUs work. The notion that programming in a higher-level language is OK without sufficient knowledge of the underlying CPU is, to me at least, mistaken. Programming, no matter what the language, is still based on a machine, and a programmer must know how that machine works. > By the way, nobody should have to program in > assembler anymore (unless for fun or to write > task switchers etc.) It's a complete waste of > human energy and especially in the case of the > 6811 you can't write much more effective code > than a good compiler can (perhaps you can squeeze > out 30% better code, but it will be totally > unreadable) and ROM is cheap by now. Although most will probably agree with you I think your opinion is subjective. I think it's like driving. Some truck drivers, for example, may find it easier to drive their trucks than their family car because they're on their truck's wheel most of their lives and have acquired a 'natural' feel for that vehicle. Similar with assembly language. If you've been programming in assembly a great deal more than, say, in C, it actually IS easier to program in assembly language because you think the solution directly in terms of *that* language. On the other hand, if you've been programming mostly in C (or other higher-level language), when you get to program in assembly you natually first think in C and try to mentally translate the code to assembly. And that doesn't work very well so it gives the (I believe) misleading impression that assembly programming is harder. > I consider writing in assembler a modern form > of torture (often self-torture unfortunately ;-). I understand you completely. I feel the same about C when it comes to microcontrollers. > Greetings, > Jaap |
|
Reply by ●November 23, 20042004-11-23
I would have to agree with you Tony. When I write the few programs that I do
write, for a microcontroller, I always write them in assembly. Just as you said,
it's just natural. I once took a look at some C-code and I simply could not
figure it out! To me, it wasn't intuitive such as Assembly and Visual Basic
are; it didn't "Flow". I am attempting to learn Assembly for X86
processors, yes, your PC. I have been told that it is more efficient than using
Visual Basic. This should be interesting. Just my thoughts. Salute! LF Tony Papadimitriou <> wrote: ----- Original Message ----- From: "Jaap van Ganswijk" To: Sent: Tuesday, November 23, 2004 10:09 AM Subject: Re: [m68HC11] RTS problem > At 2004-11-21 19:09, wrote: > >I think the rule is: if you push n bytes then call a jsr, the jsr must rts, > >then the caller must pull n bytes. One must NEVER jump out of a subroutine > >with items on the stack.... unless you are writing a 'kernel' or 'task switcher' > >or 'coroutines' or other comp-sci. The stack must grow and shrink > >symmetrically > > People that don't understand things like these > shouldn't program in assembler but should program > in a language like C which will take care of these > things. I'd go further and say people who don't understand such things should not program at all until they learn some more about how CPUs work. The notion that programming in a higher-level language is OK without sufficient knowledge of the underlying CPU is, to me at least, mistaken. Programming, no matter what the language, is still based on a machine, and a programmer must know how that machine works. > By the way, nobody should have to program in > assembler anymore (unless for fun or to write > task switchers etc.) It's a complete waste of > human energy and especially in the case of the > 6811 you can't write much more effective code > than a good compiler can (perhaps you can squeeze > out 30% better code, but it will be totally > unreadable) and ROM is cheap by now. Although most will probably agree with you I think your opinion is subjective. I think it's like driving. Some truck drivers, for example, may find it easier to drive their trucks than their family car because they're on their truck's wheel most of their lives and have acquired a 'natural' feel for that vehicle. Similar with assembly language. If you've been programming in assembly a great deal more than, say, in C, it actually IS easier to program in assembly language because you think the solution directly in terms of *that* language. On the other hand, if you've been programming mostly in C (or other higher-level language), when you get to program in assembly you natually first think in C and try to mentally translate the code to assembly. And that doesn't work very well so it gives the (I believe) misleading impression that assembly programming is harder. > I consider writing in assembler a modern form > of torture (often self-torture unfortunately ;-). I understand you completely. I feel the same about C when it comes to microcontrollers. > Greetings, > Jaap Yahoo! Groups Links --------------------------------- |
|
Reply by ●November 23, 20042004-11-23
On Wed, 2004-11-24 at 02:36, bart homerson wrote: > I would have to agree with you Tony. When I write the few programs that > I do write, for a microcontroller, I always write them in assembly. My sentiments entirely. > I am attempting to learn Assembly for X86 processors, yes, your PC. I > have been told that it is more efficient than using Visual Basic. This > should be interesting. Just my thoughts. Again, you would be in good company FWIW, that of the few people who *actually* know how PCs work, viz. Steve Gibson. I had to chuckle where a previous critique stated: > It's perfectly legal (but usually bad practice) to push something onto > the stack before doing the JSR, and have the subroutine reference it. ... as this is of course, *exactly* how C, Pascal and such function. It went on to say: > Advanced programmers sometimes -do- intentionally mess up the stack, > but they will take additional steps to handle the situation. ... such as, by using such a language. However, I wonder whether (many of) those who malign the use of assembler, understand or recognise the distinction between "raw" and *macro* assembler, which latter is I hope, our point of reference and the use of which begins to resemble "C"? -- Cheers, Paul B. |
|
Reply by ●November 23, 20042004-11-23
--- In , "Tony Papadimitriou" <tonyp@m...> wrote: >> I consider writing in assembler a modern form >> of torture (often self-torture unfortunately ;-). > I understand you completely. I feel the same about C when it comes > to microcontrollers. Ahh, the classic "C vs. asm" argument that tends to pop up in groups like this periodically. FWIW, my own personal preference is to do smaller and/or more cost- critical, resource-constrained applications in assembly language. Even the best C compiler cannot produce code to match expertly hand- optimized assembly code. Some C-only proponents often use as an argument that asm is cryptic, whereas C tends to be more "self documenting". I could not DISAGREE more. The sad tendency of your typical C programmer to write gawd- awful constructs like this: if (ch=getch()=='\n') { drives me nuts. And this is just a simple example (intended to be comprehensible while still making my point) of much more complex assignments-within-expressions-within-evaluations that I see all too often in "professionally developed" C source. When I write programs in C, I try to avoid complex expressions, or at least break them up into multiple lines, assembly-language-style. Ok, I'm ranting here, so let me get to my point: I am of the opinion that the language is not as important as is the style in which one writes code in any language. A properly commented, intelligently structured C program can be a joy to behold - just as a properly aligned, well structured assembly program with good label/variable names can be. Organization, clarity, and consistency in style are the keys to readability in ANY language. One last comment on C in embedded/microcontroller systems - one of the things I dislike most about your typical C compiler is the complex (and usually poorly documented) procedure one has to figure out to get the various memory regions and areas, or even individual variables, mapped to where you want them to go. The C language standard does not do a good job of allowing one to attach attributes to variables indicating where in memory they should go. This task usually falls to the linker, and of course there is no standard for linker control 'languages' which means that it differs for every compiler. This issue has been the single greatest obstacle that I've encountered in my attempts to utilize the GNU HC11/12 toolset for my own projects based on these parts. -- Mark |
|
Reply by ●November 23, 20042004-11-23
--- In , "Paul B. Webster" <paulb@m...> wrote: > ... > However, I wonder whether (many of) those who malign the use of > assembler, understand or recognise the distinction between "raw" and > *macro* assembler, which latter is I hope, our point of reference > and the use of which begins to resemble "C"? Yes, macros can be awfully handy in a asm environment, as as Paul implies, can go a long way to making asm source more 'readable' - not to mention much easier to 'retarget' if the hardware changes. It is regrettable that Tony P's otherwise outstanding ASM11 does not have any support for user-defined macros (hint, hint ;) -- Mark |
Reply by ●November 23, 20042004-11-23
> FWIW, my own personal preference is to do smaller and/or more cost- > critical, resource-constrained applications in assembly language. > Even the best C compiler cannot produce code to match expertly hand- > optimized assembly code. Quite true. Over the years the technique I've found most useful is to keep asm routines small and C-callable (and before C, FORTRAN callable). By making them C-callable, 1) I can use a quick 'n dirty C mainline to test them, 2) it forces a uniform organization for passing arguments, stack useage, and saving registers (which saves frustration/self-cursing/sanity/...). Also, whenever I start to write an asm routine I find there is a temptation to keeping add more to the routine, which can lead to a monstrosity that is difficult to debug/test, and has limited reusability. Regards, Donald E Haselwood |
|