紧急求助!ARM-GCC对于函数指针调用的编译有错误?已经找到原因

Posted smstong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了紧急求助!ARM-GCC对于函数指针调用的编译有错误?已经找到原因相关的知识,希望对你有一定的参考价值。

函数指针是实现回调函数的基础,回调函数是C程序架构的基础。所以函数指针的重要性不言而喻。然而最近在ARM开发板上测试程序时,发现函数指针虽然能编译通过,但是运行时确总是报错。如下是一个最简单的测试程序源码。

static void test()

    puts("test\\n");


static void(*f)() = test;
void Main(void)

    led_init();
    key_init();
    io_init(0);

    f();

    while(1)
        puts("-------hello from main()----------\\n");
        delay(100000);
    

使用gcc -S编译得到的汇编代码如下:

    .cpu arm10tdmi
    .eabi_attribute 20, 1
    .eabi_attribute 21, 1
    .eabi_attribute 23, 3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 2
    .eabi_attribute 30, 6
    .eabi_attribute 34, 0
    .eabi_attribute 18, 4
    .file   "main.c"
    .section    .rodata
    .align  2
.LC0:
    .ascii  "test\\012\\000"
    .text
    .align  2
    .syntax unified
    .arm
    .fpu softvfp
    .type   test, %function
test:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 1, uses_anonymous_args = 0
    push    fp, lr
    add fp, sp, #4
    ldr r0, .L2
    bl  puts
    nop
    pop fp, pc
.L3:
    .align  2
.L2:
    .word   .LC0
    .size   test, .-test
    .data
    .align  2
    .type   f, %object
    .size   f, 4
f:
    .word   test
    .section    .rodata
    .align  2
.LC1:
    .ascii  "-------hello from main()----------\\012\\000"
    .text
    .align  2
.LC1:
    .ascii  "-------hello from main()----------\\012\\000"
    .text
    .align  2
    .global Main
    .syntax unified
    .arm
    .fpu softvfp
    .type   Main, %function
Main:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 1, uses_anonymous_args = 0
    push    fp, lr
    add fp, sp, #4
    bl  led_init
    bl  key_init
    mov r0, #0
    bl  io_init
    ldr r3, .L6
    ldr r3, [r3]
    blx r3
.L5:
    ldr r0, .L6+4
    bl  puts
    ldr r0, .L6+8
    bl  delay
    b   .L5
.L7:
    .align  2
.L6:
    .word   f
    .word   .LC1
    .word   100000
    .size   Main, .-Main
    .ident  "GCC: (GNU) 6.2.0"
    .section    .note.GNU-stack,"",%progbits

可见函数指针调用时,被编译成了BLX指令。这个指令是跳转并且换运行状态(ARM和THUMB切换)。显然这样编译是错误的,还请高手帮忙分析一下,到底是哪里出了问题?

是需要特殊的编译参数吗?

头疼!!!

2016-12-20 更新:

已经找到原因,关键点如下:

  • GCC把绝对地址调用(包括函数指针调用)编译为BLX Rn指令。BX,BLX指令用于绝对跳转(B,BL则用于跳转),转到Rn中包含的地址。总之,其中的X有两个意思:(1)表示根据Rn的最低位是否为0,确定是否进行ARM/Thum切换。(2)可以绝对地址跳转。

  • S3C2440A的指令集中没有BLX,只有BX。故运行时会无效指令错误。

解决思路:
(1)给GCC适当的参数运行,来避免生成BLX指令。目前尚不清楚需要什么参数选项。
(2)利用Undefined异常处理程序来模拟BLX指令。这个看起来复杂,实现起来其实非常简单,已经在v0.9中实现。

以上是关于紧急求助!ARM-GCC对于函数指针调用的编译有错误?已经找到原因的主要内容,如果未能解决你的问题,请参考以下文章

紧急求助,请问如何在android 系统中通过ndk内嵌c版bullet物理引擎???主要是如何编译bullet源代码?...

求助python调用dll函数里,关于数据指针和长度应该如何获得呢?

求助!C语言用指针函数实现十进制转,十六进制,八进制,二进制

紧急求助,关于arm版本下QWT库移植出现的错误

static函数如何调用虚函数

[2016-05-13][C++若干问题]