紧急求助!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函数里,关于数据指针和长度应该如何获得呢?