EmbeddedRelated.com
Forums
Memfault Beyond the Launch

mixing C and assembly

Started by Lax April 22, 2008

Mark Borgerson wrote:

> > register_sp SP; > > > > SP = int_value; > > > I must be using the wrong compilers! ;-) > > Imagecraft for the MSP430, IAR for the ARM, IAR for > the MSP430 and Codewarrior for M68K systems all seem > to use an assembly-language routine for initial setup.
Mark, Actually Byte Craft compilers are a little more complex. The compiler / linker keeps track of the things that architecturally need to be initialized and generates code for this after reset. This usually initializes the stack from either default, declared values in the application or linker information. There are other architectural dependent things in some processor families like clock options default ISA's, memory map tables. These choices are selected with application pragma's. The function called __STARTUP if it exists in the application gets executed as soon as the processor is stable but before the variables are initialized. __STARTUP is used to support user initialization and is the way many embedded products trap a maintenance startup mode. (Maintenance modes are user defined often ground a output pin when processor is reset, jump or call maintenance software in the application) __STARTUP is written like any C function. When it is called no variables have been initialized so if it goes into a maintenance mode the variables have their values pre-reset. After __STARTUP returns the remaining compiler generated initialization is executed and then there is a jump to main(..). The compiler/linker in the simplest case just ties the reset vector to main (default stack) in the most complex goes through the steps outlined above. Regards, -- Walter Banks Byte Craft Limited Tel. (519) 888-6911 http://www.bytecraft.com walter@bytecraft.com
On Apr 24, 12:43=C2=A0am, David Brown
<david.br...@hesbynett.removethisbit.no> wrote:
> cbarn24...@aol.com wrote: > > On Apr 23, 10:03 pm, David Brown > > <david.br...@hesbynett.removethisbit.no> wrote: > >> cbarn24...@aol.com wrote: > >>> On Apr 23, 7:27=EF=BF=BDpm, Walter Banks <wal...@bytecraft.com> wrote:=
> >>>> Stefan Reuther wrote: > >>>>>> register_sp SP; > >>>>>> SP =3D int_value; > >>>>> What you're doing here is writing assembly with C syntax. It relies =
upon
> >>>>> a heavily non-standard language extension, and makes assumptions abo=
ut
> >>>>> how the compiler behaves (you don't want the compiler to use the sta=
ck
> >>>>> before your SP assignment, do you?). So instead of writing assembly =
in
> >>>>> C, I prefer using the real thing. > >>> Yes, thats what he always does! He can then claim his compiler can > >>> beat assembler for speed,code size ect. To Walter if it looks Cish, > >>> ends in a semicolon and his compiler can change it into machine code > >>> then its C. > >>>> I actually agree with you it is very low level C. The purpose of ISO/=
IEC
> >>>> 18037 was to define the low level syntax. Most start up code is very =
processor
> >>>> family specific. =EF=BF=BDWritting start up code in C makes good use =
of C's
> >>>> optimization like the branch/jump to main. > >>> Whats to optimise? Why bother optimising a one time instruction? > >>> Sometimes I think you'll say anything to sell a compiler. > >> Why would you bother optimising a traditional call to main into a jump?=
> >> =C2=A0 On some targets (in particular, several that Bytecraft target), =
the
> >> saved stack space is significant - and even the couple of saved flash > >> bytes is worth doing (given the negligible cost of the compiler's effor=
t).
> > > If it is on your project you are allready are allready up a certain > > creek without a paddle. In any event you wouldnt use a "traditional" > > ie a C type call to main from startup so stack saveing would be > > minimal. > > First off, Walter writes compilers and their associated libraries - > saving a few bytes of stack space there means savings for all his users. > =C2=A0 We are not talking about individual projects here.
No we're talking about startup code, do try to keep up.
> > Secondly, some processors have small fixed-size hardware stacks (small > PIC's and AVR Tiny's are examples). =C2=A0For such devices, a single > unnecessary "call" can waste a third of your stack resources.- Hide quoted=
text - Firstly you would be mad to try running C of these chips. Secondly you would not put call returns on the hardware stack unless you have some kind of death wish, you keep that space for the ISRs.
> > - Show quoted text -
"David Brown" <david@westcontrol.removethisbit.com> wrote in message 
news:48102f95$0$23838$8404b019@news.wineasy.se...
> Bill Leary wrote: >> "Walter Banks" <walter@bytecraft.com> wrote in message >> news:480FAC36.E382E22B@bytecraft.com... >>>> Why would you bother optimising a traditional call to main into a jump? >>> >>> When C runs on embedded systems processors that are not hosted main >>> should never return. >> >> Usually, no. But it's a good idea to make sure the system does something >> reasonable if it does. > > Why should the system do something reasonable if the programmer > does something unreasonable?
Because programmers WILL do something unreasonable and helping them to discover what that is, beyond the system going bye-bye, is good engineering. A bit of work here can potentially save a pile of work later on.
> In my gcc programs, main is tagged with a "noreturn" attribute > - attempting to return from main will produce at least a warning > message, possibly an error (I can't remember off-hand).
OK. So you DID do the "something reasonable," using a feature provided by your development package.
> I'm sure Walter's compilers are able to enforce no return from > main equally well.
- Bill
On Apr 24, 12:13=EF=BF=BDam, CBFalconer <cbfalco...@yahoo.com> wrote:
> Walter Banks wrote: > > >> Why would you bother optimising a traditional call to main into > >> a jump? > > > When C runs on embedded systems processors that are not hosted > > main should never return. > > What if the programmer puts (as he should) a return into main? > This means you have to stack an address for that return (possibly > the address of main).
Indeed you do but it's not usually more than 2 bytes, you cant get much more optimal than that.
> > -- > =EF=BF=BD[mail]: Chuck F (cbfalconer at maineline dot net) > =EF=BF=BD[page]: <http://cbfalconer.home.att.net> > =EF=BF=BD =EF=BF=BD =EF=BF=BD =EF=BF=BD =EF=BF=BD =EF=BF=BD Try the downlo=
ad section.
> > ** Posted fromhttp://www.teranews.com**
On Apr 24, 8:18=EF=BF=BDam, David Brown <da...@westcontrol.removethisbit.com=
>
wrote:
> Bill Leary wrote: > > "Walter Banks" <wal...@bytecraft.com> wrote in message > >news:480FAC36.E382E22B@bytecraft.com... > >>> Why would you bother optimising a traditional call to main into a jump=
?
> > >> When C runs on embedded systems processors that are not hosted main > >> should never return. > > > Usually, no. =EF=BF=BDBut it's a good idea to make sure the system does > > something reasonable if it does. > > Why should the system do something reasonable if the programmer does > something unreasonable? =EF=BF=BDIn my gcc programs, main is tagged with a=
> "noreturn" attribute - attempting to return from main will produce at > least a warning message, possibly an error (I can't remember off-hand). > =EF=BF=BD I'm sure Walter's compilers are able to enforce no return from m=
ain
> equally well.
Anything can upset a program, you need some kind of error code, also needs to be in assembly, to make the system safe.
cbarn24050@aol.com wrote:
> On Apr 24, 12:43 am, David Brown > <david.br...@hesbynett.removethisbit.no> wrote: >> cbarn24...@aol.com wrote: >>> On Apr 23, 10:03 pm, David Brown >>> <david.br...@hesbynett.removethisbit.no> wrote: >>>> cbarn24...@aol.com wrote:
<snip>
>>>> Why would you bother optimising a traditional call to main into a jump? >>>> On some targets (in particular, several that Bytecraft target), the >>>> saved stack space is significant - and even the couple of saved flash >>>> bytes is worth doing (given the negligible cost of the compiler's effort). >>> If it is on your project you are allready are allready up a certain >>> creek without a paddle. In any event you wouldnt use a "traditional" >>> ie a C type call to main from startup so stack saveing would be >>> minimal. >> First off, Walter writes compilers and their associated libraries - >> saving a few bytes of stack space there means savings for all his users. >> We are not talking about individual projects here. > > No we're talking about startup code, do try to keep up. >
Walter writes compilers for a living, so his comments are based at least partly on that - and I was commenting on your comments on his comments, if you see what I mean. But we are also talking about project-specific startup code. When you are writing your own startup code, as is appropriate for some projects, I can't really see why you would intentionally and knowingly want to waste some ram, flash and run-time by specifically choosing a call when a jump will do the job. If the source code is neater or clearer, or faster to write, then that is obviously the decider. But all other factors being equal, a jump will do the same thing. In fact, if you are using a compiler that does some sort of whole-program optimisation, and you write your startup code in C, you can expect that you will get neither a call to main, nor a jump to main - the entire main() function will be inlined within the startup code.
>> Secondly, some processors have small fixed-size hardware stacks (small >> PIC's and AVR Tiny's are examples). For such devices, a single >> unnecessary "call" can waste a third of your stack resources.- Hide quoted text - > > Firstly you would be mad to try running C of these chips. Secondly you > would not put call returns on the hardware stack unless you have some > kind of death wish, you keep that space for the ISRs. >
Firstly, you must then call me mad, along with all the customers for PIC C compilers targeted at the smallest PICs, and ImageCraft's dedicated AVR Tiny C compiler. I've only used a Tiny once, but I wrote that program in C (using gcc - with a bit of arm-twisting to make it work without RAM). I studied the generated assembly - it is unlikely that I could have improved on it more than a few percent if I had hand-write the assembly. Secondly, the AVR Tiny has no ram beyond its 32 cpu registers. I find it hard to imagine that you could write a program that needed more than 3 levels of calls (including interrupts) and have space in those registers to make a software call stack. These are devices aimed at small and simple programs - three levels of call stack is often sufficient.

cbarn24050@aol.com wrote:

> > What if the programmer puts (as he should) a return into main? > > This means you have to stack an address for that return (possibly > > the address of main). > > Indeed you do but it's not usually more than 2 bytes, you cant get > much more optimal than that.
A layer of a stack on a PIC with only 8 levels (In one case 2 levels) has a big impact the available subroutine return stack. w..
Walter Banks wrote:
> cbarn24050@aol.com wrote: >> cbfalconer wrote: >> >>> What if the programmer puts (as he should) a return into main? >>> This means you have to stack an address for that return (possibly >>> the address of main). >> >> Indeed you do but it's not usually more than 2 bytes, you cant get >> much more optimal than that. > > A layer of a stack on a PIC with only 8 levels (In one case 2 > levels) has a big impact the available subroutine return stack.
But the 8 level pic, at least, simply overwrites the eldest stack return address if overused. This puts you back to the condition where you didn't stack anything, because the stack is used modulo 8. Of course the only way to stack that return is to call in the first place. :-( -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. ** Posted from http://www.teranews.com **

David Brown wrote:

> Walter writes compilers for a living, so his comments are based at least > partly on that
Even the good intelligent people sometimes fall into the belief of their own hype :-)
> When you are writing your own startup code, as is appropriate for some > projects, I can't really see why you would intentionally and knowingly > want to waste some ram, flash and run-time by specifically choosing a > call when a jump will do the job.
Not too long ago I have burned up with the C startup code in C: it called the intrinsic function. Initially, that function was inlined; however after the new bugs in the CPU were discovered, that intrinsics had to be implemented as a walkaround function in the C library. So the startup called the library function before the library was intialized, and it caused all sorts of weird problems. It was quite difficult to find the cause. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
On Apr 22, 4:50=A0am, Lax <Lax.Cla...@gmail.com> wrote:
> Are there any situations where programming an embedded processor > "requires" at least some assembly code? >
The new Cortex M3 is advertised by ARM not to require any assembly code, even boot up or ISR's. http://www.arm.com/pdfs/Cortex_M3_DS.pdf http://www.arm.com/pdfs/IntroToCortex-M3.pdf "The Cortex-M3 processor includes many features that enable faster software development, with developers not required to write any assembler code or have a deep knowledge of the processor and its register set." "By handling the stack operations in hardware, the Cortex-M3 processor removes the need to write assembler wrappers that are required to perform stack manipulation for traditional C-based interrupt service routines, making application development significantly easier." "Traditionally ISRs require an assembler wrapper to handle stack manipulation before and after the main C-based routine is called and during start-up boot code. The Cortex-M3 processor handles all stack manipulation in hardware, removing the need for the assembler and enabling the developer to program just in C and without having to learn exactly how the processor and all of the register banks operate."

Memfault Beyond the Launch