Re: mixing C and assembly



Chris H wrote:
In message <fulm9l$r16$02$1@xxxxxxxxxxxxxxxxx>, Hans-Bernhard Bröker <HBBroeker@xxxxxxxxxxx> writes
Lax wrote:
Are there any situations where programming an embedded processor
"requires" at least some assembly code?

Yes. Somebody, somewhere, some time, will have to write some assembly code. Startup code, low-level support routines for the C compiler, task switching support, ... that kind of thing.

It depends on just about every partner in the process (from chip designer to application customer) whether "somebody" includes you, the embedded software engineer.

How about for AVR, MSP430, 68HC11, 8051(Atmel)?
Can these 4 microcontrollers be programmed fully in C without touching
assembly (even interrupts and etc.)?

That depends entirely on what one still considers to be "in" C, and how the tool makers chose to handle those features of an embedded controller that strictly pure standard C can't handle. E.g., ISRs could be mapped to the signal() mechanism of standard C. But hardly anyone ever actually does that. Instead, there are compiler extensions or assembly wrappers that link C functions to interrupts.


I agree... if you go to comp.lang.c you will find that Gcc is NOT C... it is a "C like language" as it is not a full C implementation and has Gcc extensions quite apart from extensions for the target


gcc supports at least as high a proportion of C99 as the great majority of commercial compilers, and I don't know off-hand of any pre-C99 language issues. Just like all commercial compilers I am familiar with (I've used a few over the years), gcc has extensions which can be enabled or disabled. Some of these extensions are target-specific (such as for interrupt handling), others are target-independent (such as allowing certain C++ constructs in C, and vice-versa).

Since gcc has barely been mentioned in this thread, you must have good reason for bringing it up - surely it was not merely for gratuitous and unsubstantiated bashing (and surely it was not trolling for my reply, to re-establish our relationship after too many recent agreements :-)

Since you hang out gcc for not being "a full C implementation", and for having "extensions quite apart from extensions for the target", can you give me some examples of other available compilers that *are* "full C implementations" (along with an explanation of exactly what you mean by that phrase), which have *no* compiler extensions, and which are targeted at embedded systems?

Beyond the obsessive gcc-bashing, I pretty much agree with your post.

Also most compilers for embedded targets have many "assembler like" extensions eg where you can put hex directly into registers and peripherals. The "C" function to set up the UART on an 8051 with a Keil compiler looks almost the same as assembler!

Embedded toolchains are pretty much useless unless you can get low-level access beyond what can be written in standard C with standard libraries, so there are normally either extensions to the compiler, or extra library functions (often just wrappers around embedded assembly).


As has already been mentioned the start up code has to be in assembler as it sets up the memory for the stack etc however if you use the standard one that comes with the compiler you will never need to see it.
It is usually automatically pulled in as an object file.


Although the compiler and its libraries will often handle this sort of thing, it is sometimes useful to write it yourself. Sometimes you want to use different memory layouts from the standard ones, and sometimes you need board-specific low-level code at the start. For example, I have a card with external sdram - I needed to initialise the sdram before copying the program over from flash to sdram and running it there. I also have two separate sets of .bss and .data - one in the sdram, and one in fast internal ram. So I had a specific startup routine to handle that copying.

Depending on your tools, however, this sort of thing can often be written in C - even though your real C environment is not yet ready (for example, initialised data are not yet initialised, and for C++ your global objects are not yet constructed). I find that my assembly can often be reduced to two or three op-codes at the very start (if the toolchains standard startup code is not suitable), along with some embedded assembly macros or function wrappers for things like interrupt control, or accessing cpu-space registers on some targets.

That said you can program most of these micros in pure C with no extensions (compiler or targets) BUT it is usually very inefficient code and no one is likely to employ you if you do that.


You usually need to use your compiler's target extensions (for interrupts, if nothing else), unless you have a ready-made OS layer that handles that sort of thing for you.

For "general" C programming, it is rare that you can write significantly smaller or faster code using assembly than a good compiler will generate. This is especially true for big processors where manually tracking things like register allocations, pipelining, and instruction overlap will drive you up the wall - the compiler does this quickly and easily, and thus will generate better code than all but the most dedicated assembly programmers. Similarly, for very small and limited cpus, modern compilers can optimise things like bank switching and data placement better than a human can while still writing legible and maintainable code.

Compilers often have other extensions which *can* make a big difference, however. Extensions giving hints to the compiler ("inline" is often available as an extension when compiling for older C standards) can make the generated code smaller and/or faster. Extensions for source code, such as unnamed structs and unions, or flexible array types, can lead to clearer and neater source code. Obviously you must be aware of when such extensions make your code non-portable between targets and/or compilers - it's a tradeoff you have to evaluate.

The one place where compiler assembly-like extensions and/or real assembly can make a big difference is for dsp programming. Compilers are getting better at turning C loops into optimal dsp code, but in many cases you have to write something horrendous involving all sorts of compiler/target-specific pseudo-functions to end up with optimal assembly - writing in pure assembly is often clearer and neater.


.



Relevant Pages

  • Re: Writing an ANS Forth
    ... I just wish there was more literature to be found on the inner workings of a cross target compiler. ... only included in the $1295 Professional SwiftX versions of the compiler, I'm afraid that is way beyond what I can justify for hobby use. ... The major missing component for doing a new target is the assembler, but designing a new assembler is a lot smaller task than designing a whole new cross-compiler. ...
    (comp.lang.forth)
  • Re: ASM vs HLL : absurd war
    ... platform dependent. ... may generate intermediate assembler source code for a second pass assembly. ... assembler language A has a single target; ... would be a compiler, or .Net. ...
    (alt.lang.asm)
  • Re: Results of the memswap() smackdown from the thread "Sorting" assignment
    ... With your fondness for rolling your own languages, and assembler it ... code that does the heavy lifting making new compiler creation ... a low cost back end and a new language a parser for the ... a particular target then re target to a similar target and possibly ...
    (comp.programming)
  • Re: Writing an ANS Forth
    ... I just wish there was more literature to be found on the inner workings of a cross target compiler. ... only included in the $1295 Professional SwiftX versions of the compiler, I'm afraid that is way beyond what I can justify for hobby use. ... The major missing component for doing a new target is the assembler, but designing a new assembler is a lot smaller task than designing a whole new cross-compiler. ...
    (comp.lang.forth)
  • Re: mixing C and assembly
    ... there are compiler extensions or assembly wrappers that link C functions to interrupts. ... Also most compilers for embedded targets have many "assembler like" extensions eg where you can put hex directly into registers and peripherals. ... That said you can program most of these micros in pure C with no extensions (compiler or targets) BUT it is usually very inefficient code and no one is likely to employ you if you do that. ...
    (comp.arch.embedded)