This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Understand The 8051's Capabilities and C51 Assembly Output.

One of THE worst things you can do in C51 code is to haphazardly use integers where unsigned chars (bytes) will suffice. Particularly when indexing arrays.

While this may seem obvious to some, in my years of changing diapers (i.e. working on code written by other's who are now off destroying some other company's software department) I have run across this mistake countless times, where the non-obvious result is at least over-bloated code and/or, at worst randomly dysfunctional code.

Does ANYONE in this industry bother taking the time to inspect the assembly code resulting from a compile? Does anyone even care? ...or is 95% of the industry filled with hacks who verify their code by functional "appearance" alone? My experience suggest the latter.

The Moral:
Keil C51 is without question top notch, but its not magic. Thus, do your career and your company a favor an make an effort to understand the 8051 indepth and understand what is and what isn't good C51 programming techniques.

[end rant]

  • "Does ANYONE in this industry bother taking the time to inspect the assembly code resulting from a compile?"

    I always do, but my experiences is that most do not.

    "Thus, do your career and your company a favor an make an effort to understand the 8051 indepth and understand what is and what isn't good C51 programming techniques."

    That goes for virtually all microcontrollers.

  • Do not forget to make sure integer promotion is turned off

  • Robert, I am sure you have seen from my posts that I wholehardedly support your opinion.

    More and more often we see posts "I wrote in C, why does it not work" from individuals that code the '51 as a "mini PC".

    C can be written as "who cares where it is to run" or "architecture friendly". No one can write "architecture friendly" if they refuse to get even an inkling how the processor works.

    The '51 is (I love it) MEAN to those that will not take the time to familiarize themselves with the architecture.

    As to "checking the generated assembly" I hope you refer to doing so when problems arise, not on a total basis. It is amazing how easy it is to find a C error when looking at the generated assy whereas checking a whole program seems busywork.

    Have fun,

    Erik

  • I found it well worth while when I started my project to examine the assembler listing, as well as re-write the same routine in different ways to observe the changes. Once I got a good feel for what the code generator was going to do in various circumstances, and what the limitations are, I could write C without having to worry about the output in most cases.

    I continue to go back and check routines when the change in size or speed seems contrary to my expectation, as well as checking important routines or common access patterns.

    I'd recommend anyone starting on an 8051 project do the same thing to educate themselves on how to make the architecture work for you. The 8051 is quirky, and the compiler adds some quirks of its own. Those quirks can make your life miserable if you don't keep them in mind.

  • I'd recommend anyone starting on an 8051 project do the same thing to educate themselves on how to make the architecture work for you. The 8051 is quirky, and the compiler adds some quirks of its own. Those quirks can make your life miserable if you don't keep them in mind.

    Absolutely. Take the time to experiment and learn what C language constructs bottleneck the resulting assembly code. Play with it and learn. In the end, it will save you time...granted, time that can't be tabulated on a quarterly report, so it will probably never be allocated, thus do it on your own time if you have to.

  • To be honest I find that checking the assembly is largely a waste of time at optimisation level 9 with linker code packing. One can spend time tweaking the 'C' to help the optimiser save a few bytes, then add or change a bit of code elsewhere in the project only to discover that this completely undoes any benefit derived from all that tweaking. Reversing the tweaks may then show a reduction in code size...

    Using the smallest integer size possible is such an obvious source level optimisation that I doubt anyone incapable of seeing this would be able to understand an assembly listing anyway.

  • To be honest I find that checking the assembly is largely a waste of time
    absolutely for an experienced Keil '51 programmer. However, if you are just starting out doing some peeks can yeld extremely valuable information about what the compiler "likes" and "dislikes".
    One example if you have a look at the difference between xdata treated as
    = pointer[index]
    index++
    vs
    = *pointer
    pointer++

    it will be educational.

    Erik

  • as
    = pointer[index]
    index++
    vs
    = *pointer
    pointer++


    Excellent example and is precisely what instigated my rant in the first place.

    Not only did the original hack (uh..author) index arrays like your top example, he used a signed integer to do it...and the array is only 64 elements long. To make matters worse, this was done numerous times within a repetative timer interrupt with an interval as low as 625uS. Comparing the execution time of the resulting assembly to this interval yeiled an overrun by anywhere from 8 to 108 machine cycles.

    Yet, somehow this code made it through review and QA...which only serves to reconfirm my belief that software QA is little more than a "feel good" regulatory appeasment.

  • "Not only did the original hack (uh..author) index arrays like your top example..."

    Oh no, not that old chestnut again: It is not a foregone conclusion that pointers are inherently better than array indexing!

    See: http://www.keil.com/forum/docs/thread1156.asp

    "...he used a signed integer to do it...and the array is only 64 elements long."

    Not that is unforgiveable!

  • I agree. There's a time and place for both indexing and pointer access to arrays.

    In this case, however, the pointer would have been much better and at least, considering the timing constraints, the assembly should have been inspected.

  • "the assembly should have been inspected"

    Yes, that's the one sure way to settle it!

  • considering the timing constraints, the assembly should have been inspected

    There's the real chestnut: if, and only if timing constraints apply, should the assembly output by the compiler routinely be inspected (or the relevant piece be written in assembly right away). As D.E. Knuth so famously put it, "Premature optimization is the root of all evil."

  • "There's the real chestnut: if, and only if timing constraints apply, should the assembly output by the compiler routinely be inspected" (my emphasis)

    True - since the whole point of writing in 'C' is to improve programmer efficiency.

    However, I think the point of the original rant was as a training excercise, rather than a routine for experienced C51 developers?

  • However, I think the point of the original rant was as a training excercise, rather than a routine for experienced C51 developers

    My 'rant' is that so many just whack the code in and the come here to whine "it does not fit" or "I get this error". Then when we reply "did you read the manual" or "did you take the many memory areas into consideration" back comes "you stupid idiots, I need an answer, not reading" and even worse "I know that when writing in C there is no need to understand the processor"

    This comes back to the subject of this thread, "to code C for the '51 you need to understand the '51" or as my brother in law would say "it ain't no PC"

    Erik

  • For the most part I'd agree with all of these posts. While you won't see me digging through the assembler listings for everything I write, there is a lot to be learned by examining the compiler output. The only way to write fast, efficient code in a high level language is to know what the compiler produces as a result of your code. This isn't specific to the 8051 at all - it applies to every compiler for every processor. If you're interested in speed and efficency you have to know what the compiler generates - period.

    In defence of some of the silly questions, there are lots of good reasons for them. If you're like me you get handed projects that need to be completed in what is often an unreasonable timeframe. You do a quick search through manuals and PDF files but don't find the answer, so you ask here. Often the answer is in the documentation somewhere - if you can find it, and you have the time to find it. If it's a simple thing, and you KNOW someone out there has the answer right in their head, then it's more cost effective to just ask. I had one guy working for me who was determined to figure out a problem by himself even after I told him to call tech support (which we paid for). He bugged me about it so I took a quick look and told him I thought he had mis-configured the address mapping (ST10F269) but to call support if he didn't resolve it in a day. He screwed with it for three weeks before he called support. They got back to him the next day and told him how to configure the linker. I don't need to tell you he doesn't work here after that episode.

    The moral - don't *** at these guys or give insulting answers. Help them (give them the answer if you have it - not the manual section) and nicely point out where they might have found it - next time they'll look. Being a mentor means you help people - not ridicule them. It's a lot better to be a hero than an A-hole.