本文主要是介绍cortex-m4系列绝对地址函数跳转问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、环境:
cortex-m4,IAR,J-LINK。
二、问题:
1)、首先,
我将另一个程序中的函数扣出来,通过j-flash-lite下载到MCU的一个固定地址Flash中。
2)、然后,
声明一个变量为函数指针,同时将这个常量经过强转后赋值给该变量。
3)、接着,
用该变量做函数跳转。
形如:
int (*func)(int,int) = (int (*)(int,int))0x08002000;func();
4)、最后
结果出错Hardfault。
已知,所跳转的函数原码绝对没有问题。
三、分析:
打开IAR,查看Assembly,查看到其它函数调用。
如以前的:
int (*func)(int,int) = add;func();
绝对没有问题。
仔细查看func的值,与Assembly所显示的值,发现还是有区别的。
func = Assembly + 1
将原始代码修改为如下:
//int (*func)(int,int) = (int (*)(int,int))0x08002000;int (*func)(int,int) = (int (*)(int,int))(0x08002000 + 1);func();
程序可以正常运行。
========================================================================
已知cortex-m系使用thumb指令,该指令为16位可变长度。
这样来看的话,再结合大小端的问题,是不是可以理解为PC应该指向最高位,从大地址向小地址读取。因为func的函数就是add(int,int)自加函数,首行机器码为adds为16位指令,所以应该从存储地址的首位,加到最高位,也就是加1位?
四、其它问题:
1)、J-Link单步执行正常
当程序以问题中的地址运行时,0x08002000(没有+1),直接运行出错,但是当执行进入该函数时,反而可以执行。当去掉j-link,直接在板子上执行时,还是会卡死。
2)、函数调用规范
我为什么会做这个实验呢?是因为我想将其它函数放到内存中动态执行。嘿嘿,懂的都懂。
于是我使用了arm-none-eabi-gcc来编译函数。但是当我看到dis反汇编后,傻眼了。函数的传参根本不是r0,r1而是更为复杂的sp。也就是将函数参数从右到左做push,然后在函数内使用这些值。这就涉及到调用约定也就是abi application binary interface了。还有哪些规范呢?__cdecl、__stdcall、__fastcall。
至于为什么我使用了aapcs,也就是cmsis,也没有实现r0传参?以及使用了naked却没有返回bx lr的语句?我是如何解决的?我打算放到下一篇幅来讲解。
这篇关于cortex-m4系列绝对地址函数跳转问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!