avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] C<->asm docs/examples?


From: Erik Christiansen
Subject: Re: [avr-gcc-list] C<->asm docs/examples?
Date: Wed, 28 Feb 2007 13:06:02 +1100
User-agent: Mutt/1.5.9i

On Tue, Feb 27, 2007 at 10:11:41AM +1300, David McNab wrote:
> Hi,
> 
> Can anyone please point me to some resources for learning about
> interfacing C and assembler modules in gcc-avr?

Not finding any, a few years ago, I just played it by ear, and it worked
out fine. :-) 

> I've been looking at the asmdemo code from avr-libc, but it only goes
> part way with overall explanation.
> 
> I'm especially needing to learn how to write assembler (.S) modules
> containing C-callable functions, and how to handle issues like:
> 
>  - how to access the arguments passed in by the calling C function

I made these notes back when doing this more actively. hopefully little has 
changed:

AVR ABI:
--------
GCC: (From file:///usr/local/src/avr/avr-libc-user-manual/FAQ.html#faq_reg_ ):
   r0          Volatile
   r1          Assumed to be zero. (clr r1 on return)
   r2-r17      Preserved across function calls
   r18-r27     Volatile
   r28-r29     (Y Register) = Data Stack Pointer
   r30-r31     Volatile

   Function call conventions:
      Arguments - allocated left to right, r25 to r8. All arguments are aligned
to start in even-numbered registers (odd-sized arguments, including char, have
one free register above them). This allows making better use of the movw
instruction on the enhanced core.

      If too many, those that don't fit are passed on the stack.

      Return values: 8-bit in r24 (not r25!), 16-bit in r25:r24, up to 32 bits
in r22-r25, up to 64 bits in r18-r25. 8-bit return values are
zero/sign-extended to 16 bits by the caller (unsigned char is more efficient
than signed char - just clr r25). Arguments to functions with variable argument
lists (printf etc.) are all passed on stack, and char is extended to int.

A quick look at the assembler code in a .lst file or objdump shows which
registers gcc is passing paramters in for you. I haven't passed so many
to assembler functions, that some had to go onto the stack.

>  - how to safely procure registers for temporary storage, without
>    breaking (or being broken by) any neighbouring C code

When you write complete assembler functions, it is only necessary to
observe the ABI, and avoid preserved registers. i.e. just use the
volatile ones, if you don't want to waste time and code pushing and
popping.

>  - how to allocate and access global variables, and make these
>    available to C code

   .global foobar,foo,foo1    # Make assembler symbols global.

   .section .text,"ax"

foobar: ldi r16,2       # If this is the start of our function, 'C' code
                        # can now call foobar().

   .section .bss,"aw"
foo:    .space 1        # Global zero-initialised char.

   .section .text,"aw"
foo1:    .space 1       # Global unitialised char.



>  - how to access C global variables

Just use them as if they'd been made global in assembler..
To the linker, globals are globals, and source code is history.

>  - how to return values to the C caller

Again, a quick look at the assembler code in a .lst file or objdump that
gcc has produced, to see whether gcc puts them where you expect,
confirms whether you're on the right track.

>  - how to call C functions - how to pass arguments and retrieve
>    the return value

A quick "nm -s test1.o" reminds me that my main() and foobar() symbols
are not modified by gcc. Any linked assembler file can then use these
global scope symbols freely.

Arguments and return values just require familiarity with the ABI. For
something more up to date than my notes,
http://www.nongnu.org/avr-libc/user-manual/ should still have a brief
list of register usage somewhere.

> I'd much rather steer away from using inline assembler inside C
> functions. The syntax is not to my taste, to say the least.

Amen. ;-)

I cheerfully port an assembler RTOS from 68K to PPC, then V850; write a
small RTOS and multi threaded call cantrol software in AVR assembler,
but in-line assembler sends me cross-eyed.

> Back in my Z80 and 8086 C/assembler hacking days, it was way simple. All
> C funcs/vars were just prefixed with an underscore, arguments were
> pushed onto the return stack along with the return address, and returned
> values were passed back through clearly-defined registers.

I don't have at the front of my mind which symbols receive underscores.
IIRC, it's those low-level ones which 'C' considers to be part of the
"implementation". Anyway, it doesn't include your globals.

> The code in /doc/examples/asmdemo in the avr-libc tree is only limited
> value, because all the assembler code seems to be just ISRs, with no
> calling between C and assembler.
> 
> Can anyone point me to some simple examples?

Quickest is to compile "Hello World", and read the listing, I suspect.

> Or should I just trawl through the lower layers of avr-libc source and
> pick it up by osmosis?

Oh no, I didn't find it necessary to go so far as digging in avr-libc.
;-)

> Thanks in advance for any help.

You're most welcome. (Just holler if omissions or errors in my
shamefully hurried braindump lead to confusion.

Erik




reply via email to

[Prev in Thread] Current Thread [Next in Thread]