历史上的今天

今天是:2024年09月15日(星期日)

2021年09月15日 | ARM-GCC对于函数指针调用的编译有错误?【已经找到原因】

发布者:zuiquan 来源: 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交叉开发环境创建与测试

推荐阅读

   9月12日消息,据国外媒体报道,研究机构预计华为智能手机今年的出货量将接近2亿部,较去年1.53亿部的出货量增长30%。  预测华为智能手机今年出货量接近2亿部的,是市场研究机构Strategy Analytics,其预计华为智能手机在今年出货1.994亿部。  而华为此前发布的2017年年报显示,华为与荣耀双品牌并驾齐驱,智能手机全年发货1.53亿部。Strategy ...
9月15日,美国对华为的禁令正式生效,届时使用到美方技术的芯片企业将不得在未经允许的情况下向华为供货。自从8月美国政府宣布对华为颁布出口管制禁令以来,索尼、全球第2大NAND Flash厂铠侠(Kioxia)等日本半导体厂商纷纷加入停供华为行列。美国追加禁令防堵华为,并通过“迂回”策略(透过第三方业者采购)规避5月时公布的禁令内容,将所有涉及美国技...
今日上午,荣耀宣布将于9月22日上午举办Magic3系列影像技术发布会,宣传语为“当镜头,彼此交流”。荣耀终端有限公司产品线副总裁熊军民表示,荣耀Magic3 系列的影像力收到很多消费者的好评,多主摄计算摄影确实强大,而在发布会之后的Magic3将会强上加强”。据悉,荣耀Magic3搭载50MP主摄、64MP黑白摄像头和13MP超广角三摄组合,加入了Flicker传感器以及...

史海拾趣

小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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