Object code from AVR studio and calling C functin from asm

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I am new to MCUs, and I want to ask two questions about basically mixing C and ASM code.

First, I know that calling asm functin from C is simple, but you need your asm compiler to create object file instead of hex. My problem is, that I like somehow avr studio IDE and preprocessor better than avr-gcc. Is there any way to generate avr-gcc compatible object code from it?

And second, I need to call function written in C from ASM code. I used google, but most topics relate only how to call asm function from C code. So, I presume, if I in the asm code just include rjmp to my function name (function accepts no variables) and generate object file, will the linker know what I am trying to do? Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pokevitek wrote:
So, I presume, if I in the asm code just include rjmp to my function name
You presume incorrectly unless you're manually pushing a return address before the jump. The called routine in all likelihood ends with ret so there needs to be a return address on the stack. The most common way to do this is to use call or rcall.

One other thing is that before calling the C routine you must save any of the "call used" registers that your asm routine is using. These are documented in the avr-libc FAQ. Moreover, assuming that your asm routine is called from C, it must avoid modifying any of the "call saved" registers.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, thanks. I mainly wanted to know if avr-gcc linker can deal with it and link it together this way. Well, I dont actually need to preserve anything, I am writing very simple monochrome PAL output, so I just want to have as much code as possible in C, and the timing critical stuff in asm, so I basically need to first call asm code, than return, but if there is exception during asm code I need to call function which will be written in C, just to simplify it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To answer your original question - the Atmel assembler is a non-inking assembler and does not create intermediate, relocatable, linkable object files. To use Asm code with an avr-gcc C program you need to take the source you have in Atmel format and convert it to avr-as format and add this to the list of files to be built in your GCC project. The mnemonics are (almost entirely) the same, it's just the directives that need to be converted to the avr-as format.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you. It get strange for me, becouse anytime I wanted to use asm in x86 PC, I just used inline, since I was just playing with some basic stuff. But when I searched for some information about linking together asm and C, I found that evenfully compiled files are sometimes called object files, which was strange for me, since I thought that object files are precompiled, but with referencies for linking.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A linking compiling/assembler takes the source code for each file (.c or .S) and converts this into ELF format object files (.o). These files are not finalised because any place they call a function in another file or access one of it's variables the destination address is 0x0000 but there's other information in the file that says "0x0000 at offset 0xNNNN needs to filled in with the address of variable/function XXXXX". When all the .o files have been created they are then all passed to the linker and it goes through the code and "fixes up" all these cross references and finally outputs a version (again in ELF format) that contains the finalised code that can be run (together with things like debug references to source files/lines)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for explanation. There is one more thing I realised might need to face. When I have written my own asm functions, in which I need to use some variables, how to ensure I wont rewrite any C code variables? For example by rewrite chunk of memory used for stack? Or any static variables? Or global ones?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

in which I need to use some variables, how to ensure I wont rewrite any C code variables?

But your Asm would not use absolute SRAM addresses. You'd use named variables just like you do in C. In fact syntactically it's easier to declare the variables in the C part of the code then simply access them from the Asm by name.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, pardon me, I didnt know this is possible. I thought that you can link only functions. So I can define variable in C, and than use it is asm code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a simple example:

main.c

#include 

void asm_func(void);
void c_func(void);

unsigned int cvar;

int main(void) { 
	DDRB = 0xFF;
	DDRC = 0xFF;
	while(1) {
		c_func();
		asm_func();
		cvar++;
	}
} 

second.c

#include 

extern unsigned int cvar;

void c_func(void) {
	PORTB = cvar & 0xFF;
	PORTC = cvar >> 8;
}

asm.S

#define _SFR_ASM_COMPAT 1 
#define __SFR_OFFSET 0 
#include  


	.global asm_func

asm_func: 
    lds r24, cvar
	out PORTB, r24
	lds r24, cvar+1
	out PORTC, r24
	ret 

And just for interest sake (and partly why I included a C version) this is the Asm the C compiler generated:

.global	c_func
	.type	c_func, @function
c_func:
.LFB2:
.LM1:
/* prologue: function */
/* frame size = 0 */
.LM2:
	lds r24,cvar	 ;  cvar.0, cvar
	lds r25,cvar+1	 ;  cvar.0, cvar
	out 56-32,r24	 ; ,, cvar.0
.LM3:
	out 53-32,r25	 ; ,, cvar.0
/* epilogue start */
.LM4:
	ret
.LFE2:
	.size	c_func, .-c_func

So the C compiler's code seems as good as I came up with (and most of the time this will be equally true).

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

in which I need to use some variables, how to ensure I wont rewrite any C code variables?

But your Asm would not use absolute SRAM addresses. You'd use named variables just like you do in C. In fact syntactically it's easier to declare the variables in the C part of the code then simply access them from the Asm by name.
That is for globals.
Strictly speaking, it doesn't even work for globals.
The variables to be defined.
@OP: In gnu assembly,
a name not otherwise defined is made into an external reference.
A typo will usually not show up until link time.

avr-gcc makes room for locals on the stack.
avr-gcc edits SP and copies the result to Y.
You can do the same.

Putting local variables on the stack is SOP
for most compilers with a stack available.
It's not restricted to gnu.

Moderation in all things. -- ancient proverb