views:

246

answers:

5

I have a .c file with the following

uint8_t buffer[32]

I have a .S file where I want to do the following

cpi r29, buffer+sizeof(buffer)

The second argument for cpi muste be an immediate value, not a location.

But unfortunately sizeof() is a C operator.

Both files are compiled to separate object files and linked together afterwards.

If I do avr-objdump -x file.c, amongst other things, I get the size of the buffer. So it is already available in the object file.

How do I access the size of the buffer in my assembly file at compile time?

+1  A: 
uint8_t buffer[32];
const uint8_t* buf_end;
buf_end = buffer+sizeof(buffer);

then

cpi r29, buf_end
SF.
`buf_end` gives me the adrees where I could read the size, but I need the size as imidiate value during compile time.
johannes
SF.
A: 
uint32_t sizeofbuffer = sizeof(buffer);

then

cpi r29, buffer+sizeofbuffer

This should work.

Pod
`sizeofbuffer` gives me the adrees where I could read the size, but I need the size as imidiate value during compile time
johannes
+2  A: 

Why not simply put the length of the array into a #define -- i.e. just use

#define BUFFER_SIZE 32

in a header file you #include (.include) in both the c and S file.

bluebrother
That seems to be a reasanable workaround. But it does not answer my question.
johannes
+2  A: 

The size of a symbol in another file won't be visible until the linker runs; by this time the assembler is already finished. The only way to get what you want* is by making it a constant, included by both files.

* assuming you need it to be an assembler immediate value.

Eric Seppanen
That seemes to be not entirely true. I can use adresses which are exported as symbols for imidiate values.
johannes
The linker knows how to replace a single symbol with its value - but it doesn't have the smarts to replace a more complex expression (like `buffer + sizeof(buffer)`).
caf
Interesting; I would have thought that because immediate fields are frequently tiny you'd want any truncation warnings to show up at assembly-time.
Eric Seppanen
A: 

If you can tell your C compiler to reliably put some label (or variable) buffer_end immediately after the uint32_t buffer[32];, your assembly language code can just use that buffer_end reference instead of awkwardly having the linker add two values.

It is easy to do something like that if you define your buffer in a .S file, but not so easy in a .c file.

FWIW, it may be possible that .o files contain some size information. I generate a .o file from a with with binary data for one of my systems:

$ avr-objcopy -B avr -I binary -O elf32-avr --readonly-text --rename-section .data=.text,contents,alloc,load,readonly,code foo.bin foo.o

This gives me a foo.o which produces the following after nm foo.o:

00000c00 T _binary_foo_bin_end
00000c00 A _binary_foo_bin_size
00000000 T _binary_foo_bin_start

The type of _binary_foo_bin_size might be useful if it can be adapted to your case - if you do need the size over the buffer_end label after all.

BTW, if you are writing for one of the AVR chips which have more than 256 bytes of SRAM, your code will probably need to make proper use of the lo8/hi8 macros to test all 16 address bits.

ndim