Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using global variables declared in C, in Arm assembly

Tags:

c

assembly

arm

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?

like image 868
de1337ed Avatar asked Nov 01 '12 16:11

de1337ed


People also ask

Can you declare global variables in C?

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.

What does global do in ARM?

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.

Where are global variables stored in assembly?

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.

Where are global variables declared in C?

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.


1 Answers

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.

like image 160
Ruslan Avatar answered Nov 15 '22 08:11

Ruslan