ARM-GCC对于函数指针调用的编译有错误?【已经找到原因】

发布者:zuiquan最新更新时间:2021-09-15 来源: eefocus关键字:ARM-GCC  编译 手机看文章 扫描二维码
随时随地手机看文章

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


static void test()

{

    puts("testn");

}


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  "test1200"

    .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()----------1200"

    .text

    .align  2

.LC1:

    .ascii  "-------hello from main()----------1200"

    .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  编译 引用地址:ARM-GCC对于函数指针调用的编译有错误?【已经找到原因】

上一篇:从NAND Flash读取数据,把代码搬运到SDRAM运行
下一篇:GNU Freestanding(Naked)C ARM交叉开发环境创建与测试

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved