EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Assembler Vs C-Compiler

Started by Tam July 10, 2003
aekalman wrote:
> --- In msp430@msp4..., "Tam"
<embedded1@y...> wrote:
>  > First thing I will say is this. Do you really need a C-compiler? 
> 
>>What's wrong with Assembly?
> 
> 
>>From my newgroup notes:
> 
> ******** BEGIN 
> Message 2 in thread 
> From: Wouter van Ooijen (wf@wf@....)
> Subject: Re: [PIC]: Re: PIC development STINKS! 
> Newsgroups: comp.arch.embedded.piclist
> View this article only 
> Date: 2002-08-01 07:32:19 PST 
>  
> 
> 
>>I honestly don't know whty people in general don't like
assembly.
> 
> 
> 1. It does not eliminate unused (uncalled) code

Don't write it in the first place.

> 2. It does not optimize (like: inline code that is
called only once)

No but I can do it better anyway.

> 3. It does not warn when I exceed 8 (or 9, or 2,
...) stack levels

And? I know how many stack levels my code reaches.

> 4. It does not (automatically) hack around the
stack limit

So it's done manually, damn, where's that next straw to clutch...

> 5. It does not 'share' file registers
used in different pieces of code
> (pseudo-stack)

But it doesn't enforce this where it may be undesirable either., and
I'm 
perfectly capable of doing my own register allocation thank you.

> 6. It is slower to write (general rule: lines/hour
is the sam in each
> langauge, HLL typically produces a few instrutions poer line fo HLL,
> so
> it codes faster, even considering an asm coder would have used
> somewhat
> fewer instructions)

Depends on whose writing it either way, and, although C has libraries, 
my asm libraries are much higher level, therefore bolting them in saves 
more time.

> 7. It is more difficult to read

C can be impossible to read. It depends on whose coding in both cases.

> 8. It is more difficult get target-independence (I
know, even HLL
> won't
> be totally target-independent)

Not of much importance to me, but one of the few reasons I may one day 
be tempted to use it on smaller jobs.

> 9. It does not transparently handle coding/banking
(I know: not all
> HLL's do that either)

Nothing is transparent to assembler, that is the whole point.

> 10. It is more difficult to explain to 14-year old
kids

So it is harder to teach kids to speak English by using English, than it 
is to try and teach them English using Chinese?

Al


Beginning Microcontrollers with the MSP430

Salvo is an RTOS, not a compiler, but can I assume from this that the 
same single distribution tool does all of the mentioned compiles. If not 
you are merely reinforcing my point. You need a different tool for each 
platform. These didn't appear from nowhere, effort had to be exp[ended 
in creating each one.

Al

aekalman wrote:

> --- In msp430@msp4..., onestone
<onestone@b...> wrote:
> 
>>This is another reason I don't currently use one. The much vaunted 
>>'portability' issue doesn't exist. It certainly
doesn't exist
> 
> between 
> 
>>compilers from different vendors, and often doesn't exist between 
>>different platforms from the same vendor.
> 
> 
> Hmmm ... the Salvo RTOS currently compiles under all of these toolsets
> listed below:
> 
> Archelon / Quadravox AQ430
> various gcc compilers
> HI-TECH 8051C
> HI-TECH PICC
> HI-TECH PICC-18
> HI-TECH V8C
> IAR MSP430
> IAR PIC18 C
> ImageCraft ICC11
> ImageCraft ICC430
> ImageCraft ICCAVR
> Keil Cx51
> Metrowerks CodeWarrior (x86)
> Microchip MPLAB-C18
> Rowley Associates CrossStudio430
> TI Code Composer (for 'C24x)
> TI Code Composer Studio (for 'C28x)
> 
> The only files that are common to all Salvo distributions that contain
> compiler-specific preprocessor directives are some of the header files
> (salvo.h and its "extensions").
> 
> The only files in each distribution that are particular to a specific
> compiler are the header file (portXyz.h) and the file containing the
> context-switcher (where applicable), either in assembly or C.
> 
> All four of our currently supported MSP430 compilers use exactly the
> same instructions in the context-switcher Assembly file -- just the
> assembly syntax differs (very slightly). We did IAR first, and the
> rest followed very quickly -- most of the work had to do with creating
> projects, libraries, etc. where things differ appreciably between
> vendors.
> 
> And to add to all this, the Salvo-specific parts of a Salvo MSP430
> application will "cross-compile" to any of the compilers without
a
> single source-code change. That's why we use only a single set of
> common files for all of the tutorials in our distributions. E.g. there
> is only one salvo\tut\tu1\main.c, and it is completely
> compiler-independent. Compiler-specific issues (usually revolving
> around how registers are defined, etc.) are handled in header files
> using the preprocessor.
> 
> The Salvo RTOS was originally written in Assembly for the PIC17C756.
> Wow, now there's a big market! :-) We then rewrote it entirely in C
> for a much wider applicability. This would have been nearly impossible
> in Assembly -- at least, it would have required many, many, many more
> man-hours, and would have yielded few, if any, benefits.
> 
> So not only does C provide a means of real portability across
> compilers from different vendors (e.g. MSP430), and across different
> platforms from the same vendor (e.g. HI-TECH, IAR, ImageCraft), but it
> even provides portability across different targets and compilers (e.g.
> PIC to MSP430 to AVR). 
> 
> The latter requires heavy and judicious use of the
> preprocessor. Of course, as one gets deeper and deeper into the
> target's hardware subsystems, cross-compiler and cross-platform
> portability requires more and more use of C's preprocessor in order to
> pull this off. Even Salvo has to do that, in that most of our ports
> include automatic clearing of the watchdog timer, which is
> hardware-dependent in those targets that do not have native
> watchdog-clearing instructions.
> 
> --Andrew Kalman  aek ... at ... pumpkininc ... dot ... com
> 
> 
> 
> .
> 
>  
> 
> ">http://docs.yahoo.com/info/terms/ 
> 
> 
> 


--- In msp430@msp4..., onestone <onestone@b...> wrote:
> Salvo is an RTOS, not a compiler, but can I assume
from this that
the 
> same single distribution tool does all of the
mentioned compiles. If
not 
> you are merely reinforcing my point. You need a
different tool for
each 
> platform. These didn't appear from nowhere,
effort had to be
exp[ended 
> in creating each one.

I _think_ what you're saying (and correct me if I'm wrong) is that
some non-zero effort had to be expended to create a Salvo distribution
for each target and compiler (i.e. each unique combo) beyond the first
one.

The salient point is that each unique target+compiler combination does
require some unique (non-portable) attention in order to build
successfully.

But, the amount of effort required to port Salvo (in C) from the PIC
family (our first port) to the 8051 family (our second port, IIRC) was
trivial when compared to having to start all over in assembly, had
that been our starting point. As it was, we were in C, and so there
are just a few lines that had to be written for Keil Cx51. 

The largest part of the effort had nothing to do with Salvo's guts or
even the target's architecture per se -- it's mainly dealing with all
sorts of architecture-specific compiler issues, like memory models,
pointer sizes, etc. That's where the ports get truly hairy, because
there are issues that crop up in one unique combo (e.g. PICC's and
PICC-18's banking) that do not crop up in others (e.g. the MSP430's
linear memory addressing). 

Another example would be MPLAB-C18's (sorry about the OT non-MSP430
content) twin architectural models of stack-based or static overlay
parameter passing. This has little to do with C per se -- it's really
an issue that arises because the PIC18 series is not wholly
C-friendly. We chose not to support MPLAB-C18's static overlay model,
because PICC-18 does it already, and very well.

So, from my perspective, cross-platform portability involves several
issues, including put not limited to i) ANSI completeness of the
compiler, ii) architectural limitations of the target processor, iii)
memory models supported by the compiler, iv) command-line tools
capabilities, and several other issues that affect Pumpkin from a
marketing perspective and might affect others, too, like whether the
compiler has a linker and librarian (we currently don't support any
compilers that don't, because without a linker and librarian, we can't
create a Salvo Lite evaluation/demo version).

Believe it or not, I really like writing tight Assembly code. But
after umpteen ports of a moderate amount of C code (4,000 lines or
something -- I haven't counted recently, of which only a few tens of
lines are actually unique to each port) I am of the opinion that doing
it in assembly would have been hopeless. As it turned out, doing it in
C still takes time, but not too much, and only 20% of that time has
anything to do with C portability. That I feel is a reasonable and
eminently manageable cost of using C.

--Andrew Kalman   aek ... at ... pumpkininc ... dot ... com


aekalman wrote:

> --- In msp430@msp4..., onestone
<onestone@b...> wrote:
> 
>>Salvo is an RTOS, not a compiler, but can I assume from this that
> 
> the 
> 
>>same single distribution tool does all of the mentioned compiles. If
> 
> not 
> 
>>you are merely reinforcing my point. You need a different tool for
> 
> each 
> 
>>platform. These didn't appear from nowhere, effort had to be
> 
> exp[ended 
> 
>>in creating each one.
> 
> 
> I _think_ what you're saying (and correct me if I'm wrong) is
that
> some non-zero effort had to be expended to create a Salvo distribution
> for each target and compiler (i.e. each unique combo) beyond the first
> one.
> 
> The salient point is that each unique target+compiler combination does
> require some unique (non-portable) attention in order to build
> successfully.
> 
> But, the amount of effort required to port Salvo (in C) from the PIC
> family (our first port) to the 8051 family (our second port, IIRC) was
> trivial when compared to having to start all over in assembly, had
> that been our starting point. As it was, we were in C, and so there
> are just a few lines that had to be written for Keil Cx51. 

This is not remarkably different from an assembler port. I recently 
ported a Dallas 1-Touch software suite that I originally created for the 
HC05 in 1991 . It took me less than 20 minutes to port that to the PIC 
in 1992, and 30 minutes to port that to the MSP430 and add the overdrive 
mode software.

Simply my point is that the original post from Tam was regarding C and 
assembler. Salvo is neither. From the perspective of the post it is an 
application like any other, and effort was required to port it.

> So, from my perspective, cross-platform
portability involves several
> issues, including put not limited to i) ANSI completeness of the
> compiler, ii) architectural limitations of the target processor, iii)
> memory models supported by the compiler, iv) command-line tools
> capabilities, and several other issues that affect Pumpkin from a
> marketing perspective and might affect others, too, like whether the
> compiler has a linker and librarian (we currently don't support any
> compilers that don't, because without a linker and librarian, we
can't
> create a Salvo Lite evaluation/demo version).
> 
> Believe it or not, I really like writing tight Assembly code. But
> after umpteen ports of a moderate amount of C code (4,000 lines or
> something -- I haven't counted recently, of which only a few tens of
> lines are actually unique to each port) I am of the opinion that doing
> it in assembly would have been hopeless. As it turned out, doing it in
> C still takes time, but not too much, and only 20% of that time has
> anything to do with C portability. That I feel is a reasonable and
> eminently manageable cost of using C.

Salvo itself is NOT an embedded system per se, it generates code on a 
PC, it is an application, hence it makes absolute sense to write it in 
C. Despite appearances to the contrary I like C. I just don't have a use 
for it in the embedded systems I am currently developing. I cannot 
afford the overhead for C, or a conventional OS. If I were to write a PC 
interface I would probably use C to do it.

Al


Hi Al.

To be honest, and despite my best efforts, I really don't understand
your point regarding portability with C and embedded systems.

Salvo is 95% C, 5% Assembly, and is generally linked to a user's
embedded application as a library to be programmed as hex. Since Salvo
rarely consumes more than 25% of a complete application's total ROM
(more like 5-10% is usual), it doesn't even represent the majority of
the programming investment in a typical application.

I don't know any person who can port the Assembly-language equivalent
of 4,000 lines of C, cross-platform, in under 30 minutes. Let alone,
say, 8KB of PIC code.

Perhaps the sorts of applications I envision for Salvo
(loosely-coupled, asynchronous, tolerable of some jitter, etc.) differ
substantially from the work you do (tightly-coupled,
synchronous, intolerant of jitter, etc.)? Or maybe we just have
different ideas of large vs. small effort and application sizes. I
dunno.

--Andrew Kalman   aek ... at ... pumpkininc ... dot ... com


aekalman wrote:

> Hi Al.
> 
> I have to admit, despite my best efforts, I really don't understand
> your point regarding portability with C and embedded systems. 
> 
> Salvo is 95% C, 5% Assembly, and is generally linked to a user's
> embedded application as a library to be programmed as hex. Since Salvo
> rarely consumes more than 25% of a complete application's total ROM
> (more like 5-10% is usual), it doesn't even represent the majority of
> the programming investment in a typical application.

Sorry if I confused Andrew, and believe me I'm not having a dig at 
Salvo. My point is simple, you used Salvo as an example of C vs 
assembler, but it is a different entity.


> I don't know any person who can port the
Assembly-language equivalent
> of 4,000 lines of C, cross-platform, in under 30 minutes. Let alone,
> say, 8KB of PIC code.

Nor do I, but then the modules I port are typically very small. My 
entire Dallas library runs to under half a k of code. 4000 lines of 
assembler is a lot, unless you are counting all the whitespace etc. 
That's more than a complete system in most cases. I once built a 
complete full function ECU in a PIC12C674, and still had memory left. I 
rarely need to exceed 32K of code these days, I don't deal with monster 
systems.

> 
> Maybe the sorts of applications I envision for Salvo (large,
> loosely-coupled, asynchronous, tolerable of some jitter, etc.) differ
> substantially from the work you do (small, tightly-coupled,
> synchronous, intolerant of jitter ?). 

This is exactly my point. For me assembler isn't a choice, but a 
necessity. There is no other micro than the MSP430 which has the 
peripherals I need, the low power consumption I need, and the 
computational capability. Although that is very borderline, hence my 
interest in overclocking. My three main projects at present are a 
multi-axial navigation and sensory platform , a body worn biomonitoring 
and chemical detection system, and a device that measures, grades, 
sorts, and determines the meat quality of oysters (in their shells)as 
they drop 45cm. All are pushing the MSP430 to extremes, but all, except 
perhaps the last one, have size, power and timing constraints. The 
latter has severe timing constraints. It makes 2560 individual 
measurements for each mm the oyster falls.

Al


On Fri, 11 Jul 2003 16:04:24 +0930, onestone (Al) wrote:

>> Maybe the sorts of applications I envision for
Salvo (large,
>> loosely-coupled, asynchronous, tolerable of some jitter, etc.) differ
>> substantially from the work you do (small, tightly-coupled,
>> synchronous, intolerant of jitter ?). 
>
>This is exactly my point. For me assembler isn't a choice, but a 
>necessity. There is no other micro than the MSP430 which has the 
>peripherals I need, the low power consumption I need, and the 
>computational capability. Although that is very borderline, hence my 
>interest in overclocking. My three main projects at present are a 
>multi-axial navigation and sensory platform , a body worn biomonitoring 
>and chemical detection system, and a device that measures, grades, 
>sorts, and determines the meat quality of oysters (in their shells)as 
>they drop 45cm. All are pushing the MSP430 to extremes, but all, except 
>perhaps the last one, have size, power and timing constraints. The 
>latter has severe timing constraints. It makes 2560 individual 
>measurements for each mm the oyster falls.

Yes, this is much the same kind of thing I've done.  One of them
sounds much like your oyster sorter.  It was a broken glass
sorter for recycling, which separated brown from green from
clear.  Glass rode up a conveyor belt and literally flew across
a gap where a 2000 pixel line-array observed the glass as it
wizzed by.  Six inches after the viewing line, there was an
array of air jets.  These had to be triggered at just the right
time to hit the centroid of the glass and knock it in the right
direction.

Most of my work is in instrumentation and the analog outputs
must correlate tightly (without jitter) to the inputs.  Jitter
is far more serious than phase delay, too.  For example, while
it may be acceptable to update the analog outputs 1.0
milliseconds after the observation window closes, it's *not*
acceptable to update the analog outputs at 0.8 milliseconds or
1.2 milliseconds.  Jitter spreads the spectrum and that's a bad
thing.  But phase delay can be handled, if somewhat difficultly,
in closed loop controls.  Both are important, though.

In another case, I wrote a delta queue O/S for a DSP where I
couldn't tolerate variations in the start timing of a process of
more than 400 nanoseconds.  Here, I used a two microsecond
resolution for setting the start timing, but could have accepted
ten microsecond resolution and perhaps even 20.  But I could
still only tolerate 400 nanosecond jitter in hitting the first
instruction of the task.

Measurement systems are often like that -- or should be.  (I've
seen far too many competiting products I could easily trounce in
closed loop control because I *care* about what I'm doing,
measurement wise, and understand what phase delay and jitter
does to control system models -- particularly PID.)

It's one of the reasons I took a great deal of care in crafting
my sleep queue handling.  It's quite precise and repeatable.

Jon


--- In msp430@msp4..., onestone <onestone@b...> wrote:
> Sorry if I confused Andrew, and believe me
I'm not having a dig at 
> Salvo. My point is simple, you used Salvo as an example of C vs 
> assembler, but it is a different entity.


Maybe I need to re-read the earlier posts .. I don't understant why
Salvo is a different entity, in light of the fact that it does a lot
of "work" that would otherwise be done by code the applications
programmer might write him/herself, e.g. timers to run various
processes at different rates.

 
> > I don't know any person who can port the
Assembly-language
equivalent
> > of 4,000 lines of C, cross-platform, in under
30 minutes. Let
alone,
> > say, 8KB of PIC code.
> 
> Nor do I, but then the modules I port are typically very small. My 
> entire Dallas library runs to under half a k of code. 4000 lines of 
> assembler is a lot, unless you are counting all the whitespace etc. 


4k lines of non-whitespace C. Much more in any Assembly, of course.


> > Maybe the sorts of applications I envision
for Salvo (large,
> > loosely-coupled, asynchronous, tolerable of some jitter, etc.)
differ
> > substantially from the work you do (small,
tightly-coupled,
> > synchronous, intolerant of jitter ?). 
> 
> This is exactly my point. For me assembler isn't a choice, but a 
> necessity. There is no other micro than the MSP430 which has the 
> peripherals I need, the low power consumption I need, and the 
> computational capability. Although that is very borderline, hence
my 
> interest in overclocking. My three main projects
at present are a 
> multi-axial navigation and sensory platform , a body worn
biomonitoring 
> and chemical detection system, and a device that
measures, grades, 
> sorts, and determines the meat quality of oysters (in their
shells)as 
> they drop 45cm. All are pushing the MSP430 to
extremes, but all,
except 
> perhaps the last one, have size, power and timing
constraints. The 
> latter has severe timing constraints. It makes 2560 individual 
> measurements for each mm the oyster falls.


Allow me to expound a little on size, power and timing w/regards to
Salvo. I don't expect to make a convert out of you, of course. :-)

Size: We freely admit that below 2k of available ROM on just about any
platform, Salvo may not be the cat's meow. Why? Because it will occupy
too much of the total ROM available, even if you use the smallest
configuration (simple multitasking, no priorities, no delays, no
events, etc.) But once you break the 4k ROM barrier, and start to move
past it, it will often make a lot of sense, as it will handle lots of
functionality that the user might otherwise have to write from
scratch. In a 60k ROM '149, < 2k for the fully-functional Salvo API
means it's costing you under 3% of your ROM to have all of that
functionality (priority-based, event-driven cooperative multitasking,
proper task delays (not delay loops, of course), sems, binsems,
messages, message queues, event flags, waiting with timeouts, etc.).
And Salvo's RAM footprints are miniscule, of course.

Power: Salvo is great with power, because it's event-driven.
Basically, you can make a Salvo application sleep all the time, except
when it wakes up to service an event. In this case, events are
external or internal events that trigger interrupts. Whenever the
application wakes up, the Salvo scheduler re-evaluates whether there
is a task now eleigible to run, and runs it (and any others) until
they've all been serviced, whereupon the target goes back to sleep.
Now, there is some Salvo overhead simply due to the fact that extra
instructions must be executed to perform the scheduling, etc. But
their number is pretty small, and will probably pale in comparison to
the other work being done in the tasks.

Timing: This is of course the Holy Grail for some hard-real-time
applications. Achieving 0-instruction jitter in software is very
difficult, and imposes constraints that put a swift end to any notion
of loosely-coupled operation. Tight, deterministic non-interrupted
loops are generally the closest one can get to 0-instruction jitter
timing. And with any level of complexity, these applications are no
fun to maintain and generally not expandable. One advantage of Salvo
over conventional RTOSes is that it does not impose any overhead at
the ISR level. This, coupled with the fact that Salvo Pro can be
configured to disable selective interrupts during critical sections,
instead of global interrupts, means that one can have a "machine
inside a machine" where time-critical interrupts are handled without
any deleterious interaction from the overlying Salvo multitasking
framework. Not quite 0-instruction jitter, but much better than the
nondeterministic jitter that you would get if/when the overlying RTOS
is disabling (global) interrupts in its critical sections at what
amount to random times.

The right tool for the job is what it's all about!

--Andrew Kalman   aek ... at ... pumpkininc ... dot ... com


Firstly an apology to all. I posted the following 3x times yesterday. 
Thought the formating was messed up and deleted. If the formatting is 
still messed up when viewed from the Yahoo-Groups webviewer sorry. 
This is the last time that I post this - honest !

This was meant to highlight how even assembler can be structured and 
clean.

Graham.
 
> > "Tam" <embedded1@y...> wrote:
> > 

> Any programmer can write clean well structured
code, just as any 
> programmer can write garbage code. this has nothing to do with the 
> language, only the skills of the programmer.

> Not true, it is just as easy to use macros etc in
assembler to 
achieve 
> the same thing.

Just to inject something. The following is two assembly code 
fragments, both produce identical binary code. The first one is in 
plain vanilla assembler (from a TI app note). The second is using the 
features of a standard Forth assembler. Notice the labels have gone 
and the code stucture is obvious ( with the if..else..then, begin.. 
until constructs etc). 
This makes assembler code easier to write and less prone to errors. 
Someone mentioned a macro assembler and I wondered if that is 
similar ?

G. 

\ **********************************

Code SampleADC 
         mov &VCC_Cal,R15 
         rra R15 
Pre_ADC  bis.b #DAC_Out,&P2OUT 
C1       bit.b #CAOUT,&CACTL2 
         jz C1 
Test_DAC bit.b #CAOUT,&CACTL2 
         jnc Low1 
High     bic.b #DAC_Out,&P2OUT 
         jmp Meas 
Low1     bis.b #DAC_Out,&P2OUT 
         setc 
Meas     dec R15
jnz      Test_DAC
         bic.b #DAC_Out,&P2OUT
         xor.b #CAEX,&CACTL1
         ret c;

\ ********************************** 

Code SampleADC 
   mov #VCC_Cal,R15 
   rra R15 
   bis.b #DAC_Out,&P2OUT 
      begin
         bit.b #CAOUT,&CACTL2
      0<> until
   begin
      bit.b #CAOUT,&CACTL2
      CS if
            bic.b #DAC_Out,&P2OUT
         else
            bis.b #DAC_Out,&P2OUT
            setc 
            inc R14
         then
      dec R15
   0= until 
   bic.b #DAC_Out,&P2OUT
   xor.b #CAEX,&CACTL1
   ret c;

\ ************************************



Hi,

under http://www.ioccc.org/years.html you can find good examples of C-Code which
can't be understood without the explanation.

One example:

#include <stdio.h>
int l;int main(int o,char **O,
int I){char c,*D=O[1];if(o>0){
for(l=0;D[l              ];D[l
++]-){D   [l++]-0;D[l]-110;while   (!main(0,O,l))D[l]
+=   20;   putchar((D[l]+1032)
/20   )   ;}putchar(10);}else{
c=o+     (D[I]+82)%10-(I>l/2)*
(D[I-l+I]+72)/10-9;D[I]+=I<0?0
:!(o=main(c/10,O,I-1))*((c+999
)%10-(D[I]+92)%10);}return o;}

This program runs normally on any ANSI C compiler and is ASCII dependent.
The source code is nice, compact, and self documenting
as all good programs should be!  :-)

Regards

Rolf F.




The 2024 Embedded Online Conference