Re: What micros do you actually hate to work with?



On Thu, 12 Oct 2006 05:13:17 GMT, Neil <NeilKurzm@xxxxxxxxxxxxxxxx>
wrote:

Jonathan Kirwan wrote:
On Wed, 11 Oct 2006 09:42:20 +0200, "Frank Bemelman"
<f.bemelmanq@xxxxxxxxxxxxxxxxx> wrote:

"Jim Granville" <no.spam@xxxxxxxxxxxxxxxxxxxxxx> schreef in bericht
news:452c35c9$1@xxxxxxxxxxxxxxx
Frank Bemelman wrote:
"Joerg" <notthisjoergsch@xxxxxxxxxxxxxxxxxxxxx> schreef in bericht
news:IlVWg.21517$Ij.7449@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Generally speaking, asm is dead. Generally, using C will produce
better code in less time. Generally, with less than tiny asm
projects, a C version will give you a smaller footprint.
Generally, using asm is a waste of time and energy and
produces lower quality code.

Not dead at all. There are cases where you must be sure to control
something in x machine cycles plus/minus zero. But that would be more
like using the uC as a logic chip.

Generally speaking, my dear. I know about cases where a 74HCT74
beats every processor no matter how clever you program it.

Hey, I shouted *years* ago on this newsgroup "asm is dead". Seems
there is a little bit more concensus now.

Now I could start shouting about C is dead, use C++ instead,
but I think that is too much for today.
I wouldn't call ASM dead - Walter's example shows that it has got
more accessible : another usefull choice, as well as InLine ASM ...
I said 'generally', several times.

All uC HLL users certainly should KNOW assembler.
In C versus ASM, the ASM camp always throw in those examples
where a very speedy/tight piece of software is needed. Such are
more a matter of being smart rather than the language you use.
In most cases (if not all) it is only a very small portion of
your project. When writing that portion of software, and only
when the compiled result is not satifying, it is time to have
a look at the compiled result. And you have to know a little
bit about what you are working with. Using 32 bit longs on a
8 bit uP results in long and slow code. Since it is such a
hassle to work with 32 bit longs in assembler for an 8 bit uP,
such mistakes are not made in ASM. In ASM you are more aware of
that. Once you are familiar with you compiler and target, you
don't have to check that often anymore.

I've only had exactly one case in my entire professional life where I
was permitted to implement the exact same application, from top to
bottom, in both assembly and C. It was on a PIC processor using
Microchip's C compiler tools and their assembly under MPLAB. I was
the only programmer on the project and the first implementation was in
assembly and had to fit into a processor with 4k of code space. The
second implementation was to be placed into the then newer PIC18 with
32k of code space with an eye to start adding features, once it was
exactly ported into C at the start.

This kind of real-life application test doesn't happen that often.

We'd first decided upon the assembly route in the earlier incarnation
because of some tests we did with the earlier C compiler and the very
limited code space we had available to us in the available PICs that
were appropriate to the design. At that time, the PIC18 line of parts
was 'very new' and we still hadn't even been able to get samples. So
there was no way to consider it, seriously. We kept our eye on them,
though.

In this case, also, I was the only programmer. I've been using C
since 1978 and I've actually written a toy C compiler on my own, so I
hope you can accept the fact that I do know a little about how to use
it. I knew the application well from having written it already in the
first place. So going into the C incarnation, it was probably the
best of possible circumstances for the C side -- I knew all the
details of various functions needed. Similarly, the assembly had fit
into just 2k. After writing a nicely designed equivalent in C, the
footprint was just over 12k, by comparison. Data footprint wasn't
that much different, to be honest.

The time I had available for writing both the assembly version and the
C version was also similar, by the way -- four months or so. One of
the time-wasters in writing the C had to do with the compiler's use of
static compiler temporaries. This was bad news for interrupt events
calling C, because the compiler's live variable analysis was not able
to cover that circumstance. And it cost me time to track that down
and design a work-around for the case. Others just had to do with
learning all the #pragma's needed to deal with variable placement,
etc.

Now, I'm a very experienced assembly code writer, too. I would put
myself against any C compiler on small or large programs without any
anticipation worries that I wouldn't be able to beat the output on any
measure enough so that anyone else looking at it from the outside
would agree that it was enough better to be worth having, and on a
similar schedule.

One of the advantages in writing assembly is that your semantic
options are wider. All tools are two-edged swords. C's advantages
are also its disadvantages. Same for assembly. But assembly does
unarguably have wider semantic options, whether we are talking about
extremely miniscule details such as access to applying status bits in
ways that C cannot directly support (and if you imagine I mean
clearing or setting some status bit you have no clue what I'm talking
about here), to mid-level semantic choices such as exact timing
regardless of code edge taken, or large-scale semantic choices such as
the fixed and varying assignment of registers and value passing modes,
mixing various styles of function prologues/epilogues, or coroutine
semantics (simply unavailable in C.) Whether or not these mean as
much to your application as some of the benefits of C is another
matter.

And none of any of this means one must use either C or use assembly.
Most of my applications use both, to be honest. So for me, it's an
amalgam that works more often. But one of the really big reasons for
using C, is that other programmers for C are easier to find. And that
can be very important.

But there are times and places for assembly code. And some
applications are so competitive that the nickels and dimes are
important, or the power consumption is important, or the die size is
important, or... and assembly can at times make the difference.

My hope is that everyone be proficient at both.

I don't know if anyone else here can say that they actually were put
in a position of doing the exact same project twice -- once in
assembly and once in C -- that they had excellent experience in using
both and were competent at both and can then make a real comparison of
a real world case. But I have had that experience once. And there
was a remarkable difference in code side (not data size.)

I've also challenged myself in writing code snippets in both. I
suppose a lot of us may have done that. I'd be happy to provide one
such example here and let anyone try their compilers on it and see
what I did in assembly, by comparison. But others will legitimately
argue this proves nothing and I'd agree with them. Still, it may open
an eye or two.

Meanwhile, C is a very good choice for many if not most applications,
where a good C tool is available.

Jon

2K to 12K? what went wrong?

Where did the compiler go wrong? I have hear the Microchip compiler is
not the tightest, but 6 times bigger?

Yes. Partly because I was able to use special idioms for a state
machine in assembly that depended on exact, fixed-sized short bits of
code. In C, of course, they weren't able to be controlled in that way
and secondly the mechanism I used simply wasn't within the capability
of the compiler using switch() statements. I could provide more
detail, but that was one of the larger parts of the problem. There
actually are many others, though. It was interesting to look them
over.

The PIC16 reports in Words, the PIC18 in bytes, but that still puts you
at 3 times bigger.

my 8051 experience, while I was learning C was maybe 20% more. The code
still fit into the original space. With that kind of hit I would have
given up on C long ago.

I think C is great, actually. And in a lot of cases, it does darned
good. And I have no qualms about using it. I just provided the only
case I had, where I actually had an experience. It's likely that if I
had other experiences like this on a variety of different micros, that
some of them (probably most of them) wouldn't be so bad. This PIC
case had some areas in my assembly code that no C compiler could
consider approaching well, because (1) the PIC16 is a nasty *** as
far as C compilers go and (2) because I was able to imagine how to
take advantage of some of its weird paging mechanisms (actually, a few
of the ideas were already pointed out in Microchip examples I'd read)
in ways that no C compiler could productively use without a lot of
effort by the writer(s).

Also keep in mind that I came from a time, almost 35 years ago, when I
was involved in writing an entire timesharing operating system for 32
users, providing 10k space for each user, complete floating point
including transcendentals using Cheby-methods, a bevy of commands
(save, run, etc.) and including a form of both pseudo-compilation and
interpretation for BASIC and general assembly support. This on 16k
with user response times to commands typically about as fast as you
could enter them.

This means one learns whole new ways of thinking and imagining about
how an application is put together and I'm just about dead certain
that it would have been impossible to use a C compiler on that system
-- partly because C didn't exist then, but even if Walter himself were
to do one for this CPU and if some of the better C coders got together
on this I'm pretty sure it couldn't have been done anywhere close to
the limitations we faced there.

But if you are interested, I'd be happy to post that very short C
routine for folks to try their compilers on and to then explain why no
C compiler around can possibly turn the routine around as a human can
in order to achieve much better, by hand. It makes a clear case.
However, as I'm sure others will point out, it won't represent the
typical usage across an entire application -- the expression of some
things are pretty much the same whether coded in assembly or C on most
micros. I'd use switch() case as a good example of this kind of thing
where C is pretty darned good, except that the PIC16 actually does
provide an assembly-only mechanism for it that C cannot easily reach,
so it would be true for many, but not all processors. I'm not sure if
there are any cases true always, where C and assembly would always be
neck and neck. But I believe that broadly speaking it is true for
many practical things.

Like a lot of things, C compilers provide a floor of code generation
below which programmers cannot sink. And it's a pretty decent, high
level floor. You can pretty much rely on good results, most of the
time, using commercial C compiler tools and GNU. And as Walter points
out, there are some things that a compiler can do for you (it has
perfect memory with near-instant, flawless recall and can do the same
thing over and over and over with just the same fidelity the last time
as the first time) that even the better assembly programmers struggle
to achieve. No question.

One thing that is difficult in writing assembly is expression
optimization. I may have coded some expression and associated
subexpressions in assembly, found common factors and extracted them,
etc., and then suddenly find that I have to recode them in some
significant way because there's been a change that, in C, would be
considered "no big deal." A C compiler will eat expressions and
easily walk around finding subexpressions, promoting them out of
loops, tracking down useful strength reductions and so on, like a
bulldozer that never stops. Nice. And that's only one minor thing --
there are many, many others that are difficult that some C compilers
sporting good global analysis (stuff beyond basic blocks and DAGs)
techniques that are hard to reach for us humans.

There are lots of excellent reasons for compilers. I mean, heck, if
there weren't I don't suppose compilers would ever have been written
at all. In fact, quite the opposite is true -- there were a lot of
driving reasons for developing languages and compilers for them and
even when memory and CPU time was orders of magnitude scarcer than it
is today, they still were very useful tools. That fact is made plain
and manifest just by all the different non-assembly languages in the
world and the number of truly great applications written in them. It
couldn't have been done without them. I am deeply indebted to them
and to those who helped bring them to the rest of us.

On the other hand, I can look at an algorithm and see ways to invert,
turn inside out, or otherwise find nifty new topologies that a C
compiler would never see. And I don't mean comparing apples and
oranges, where I chose some better topology for assembly just to make
a point. I'm talking about cases where the obvious and correct way to
write the code in C has a non-obvious but equivalent assembly coding
that is much better when you look at it and where you would have a
hard time (read: impossible) expressing that new form in C even after
you see it.

C compilers have a great deal of power, but to gain that power they
also set up paradigms they must live within. And commercial C
compiler writers spend a lot of their time doing things _other_ than
writing crafty C compiler code generators -- they have to deal with
fonts, colors, print previews, docking toolbars, wizards, and gosh
knows what else. That stuff sells, but it takes the hogs' share of
their coding efforts these days. There are techniques well documented
in detail in old compiler books I have on my shelves going back into
the 1970's that still are only found in rare compiler efforts, if at
all. Most compiler writers do the same kinds of time vs value
balancing act that all of us do and the result is that C compilers
today do very little today that wasn't already mainstream stuff in
compilers existing 25 years ago. Despite the fact that there have
been a lot of nifty Ph.D. theses since then with all manner of good
ideas yet to be implemented. People don't demand them. But they do
demand better IDEs. So guess where the time goes.

So C compilers provide a very good floor. And that's enough for most
folks. It's enough for me, too, most of the time these days. I use
assembly coding mixed with C a lot. (Rarely just C only, except for
trivial programs, as there are usually at least a few places where
assembly is warranted.) But I also do use assembly only once in a
while where the application demands it for some reason or another.

I write on this simply because I think embedded programmers, some of
the better folks out there in the programming world, shouldn't shun
assembly completely. It's an important side-arm of sorts. And I
wouldn't be without good experience and training using it. Recognizing
that there is a place and time for assembly, though, takes nothing
away from those using C. However, some in this discussion appear to
imagine that in order to build up C, they have to undermine assembly
and climb on top of its dead body to gain extra height and importance.
And that is really going too far, I think, and worse it is beneath
them. C is great enough and doesn't need to denigrate other
approaches in order to raise its own stature. Too bad I have to see
folks who feel that need, off and on, here.

Jon
.