I have a C file which declares a global variables. This file will be compiled together with some ARM assembly files.
int foo;
void call_asm(void);
int main(void) {
call_asm();
return foo;
}
call_asm:
...
I tried using the link from the arm infocenter but the compiler (arm-linux-gnueabi-gcc
) is telling me that "import" is an undefined instruction.
Can I simply do something like:
LDR r0, =GLOBAL_VAR
How can I use the global variables defined in the C file in assembly?
The C compiler recognizes a variable as global, as opposed to local, because its declaration is located outside the scope of any of the functions making up the program. Of course, a global variable can only be used in an executable statement after it has been declared.
Globals in ARM cause an offset to be placed in the calling function's "pool" area. In general, each global needs its own offset. If you do decided to use globals, place them into a single structure so that all the variables can be accessed via a singel pool offset.
Global variables are stored in the data section. Unlike the stack, the data region does not grow or shrink — storage space for globals persists for the entire run of the program.
The global variables get defined outside any function- usually at the very beginning/top of a program. After this, the variables hold their actual values throughout the lifetime of that program, and one can access them inside any function that gets defined for that program.
This becomes quite simple once you ask gcc how to do it. For example, compile the following function with gcc -S -O3
:
extern int foo;
void useFoo()
{
foo=7;
}
You'll see how gcc implements it.
Based on this, I've devised a working example of calling an assembly function from C to set a global C variable:
// test.c
#include <stdio.h>
void setupFoo();
int foo;
int main()
{
setupFoo();
printf("foo=%d\n", foo);
}
# test.s
.text
.global foo
.fooAddr:
.word foo
.global setupFoo
setupFoo:
ldr r0, .fooAddr
mov r1, #123
str r1, [r0]
bx lr
Compilation and running:
$ gcc test.c test.s -o test && ./test
foo=123
Tested on gcc Raspbian 6.3.0-18+rpi1.
That assembly code above was based on the gcc output for the useFoo
example. A simpler way is to use =foo
instead of manually placing the address to a variable:
# test.s
.text
.global foo
.global setupFoo
setupFoo:
ldr r0, =foo
mov r1, #123
str r1, [r0]
bx lr
This will result in the address of foo
being put after the function definition by the assembler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With