在Arm组件中使用C中声明的全局变量

时间:2012-11-01 16:14:47

标签: c assembly arm

我有一个声明全局变量的C文件。此文件将与一些ARM程序集文件一起编译。

int foo;

void call_asm(void);

int main(void) {
    call_asm();
    return foo;
}
call_asm:
    ...

我尝试使用link from the arm infocenter,但编译器(arm-linux-gnueabi-gcc)告诉我“import”是一个未定义的指令。

我可以简单地做一些事情:

LDR    r0, =GLOBAL_VAR

如何在程序集中使用C文件中定义的全局变量?

3 个答案:

答案 0 :(得分:3)

一旦您问gcc怎么做,这将变得非常简单。例如,使用gcc -S -O3编译以下函数:

extern int foo;
void useFoo()
{
    foo=7;
}

您将看到gcc如何实现它。

基于此,我设计了一个工作示例,该示例从C调用汇编函数以设置全局C变量:

// 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

编译并运行:

$ gcc test.c test.s -o test && ./test
foo=123

在gcc Raspbian 6.3.0-18 + rpi1上进行了测试。

上面的汇编代码基于useFoo示例的gcc输出。一种更简单的方法是使用=foo而不是手动将地址放置到变量中:

# test.s
.text
.global foo
.global setupFoo
setupFoo:
    ldr r0, =foo
    mov r1, #123
    str r1, [r0]
    bx lr

这将导致foo的地址被汇编器放置在函数定义之后。

答案 1 :(得分:2)

我认为您需要将指令从ARM汇编程序转换为GNU汇编程序。如果我理解正确,您可以使用.global指令而不是.import来访问任何全局符号。来自Using as页:

  

.global 符号

     

.global使符号对ld可见。如果你在你的中定义了符号   部分程序,其值可用于其他部分程序   与之相关的。否则, symbol 从a获取其属性   来自另一个文件的同名符号链接到同一个文件中   程序

答案 2 :(得分:1)

.extern (symbol)

是你需要的