C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧 (转)

一、1、方法一
要对绝对地址0x100000赋值,我们可以用
      (unsigned int  * ) 0x100000 = 1234;
      那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
     *((void (*)( ))0x100000 ) ( ); 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

上述有误,应该是( *((void (*)( ))0x100000 ) )() ,令pFunction 为一函数指针(已被赋值一函数名,即函数首地址),则pFunction()或(*pFunction)()均表示调用该函数,而*pFunction()有误

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    首先要将0x100000强制转换成函数指针,即:
     (void (*)())0x100000
     然后再调用它:
   *((void (*)())0x100000)();               //(*((void (*)())0x100000))()
   用typedef可以看得更直观些:
    typedef void(*)() voidFuncPtr;     
   *((voidFuncPtr)0x100000)();        //( *((voidFuncPtr)0x100000))()

/* typedef void(*pFunction)(void);

  * pFunction = (void(*)(void))0x100000;

*/pFunction(); //调用函数


 
又如
如果用 C 语言,可以像下列示例代码这样来调用内核:
void (*theKernel)(int zero, int arch, u32 params_addr)
= (void (*)(int, int, u32))KERNEL_RAM_BASE; 
…… 
theKernel(0, ARCH_NUMBER, (u32) kernel_params_start); 
KERNEL_RAM_BASE 是内核在系统内存中的第一条指令的地址。
2、方法二
C语言使用函数指针跳转到程序固定地址(0x8000)执行程序的方法

使用函数指针,把一个纯数据强制转换为函数指针类型。

int main(void)

{
void (* my_function)(void);
//int *my_address = 0x8000;
my_function =(void (*)())(0x8000);
my_function();
}

其实更简单,不适用中间变量,直接一步到位:

(*(void(*)())0x8000)();
--------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/******************************以下为从《https://blog.csdn.net/ma57457/article/details/64904313》摘录及修改**************************************************/

#define jump(TargetAddr )   (*((void(*)())(TargetAddr)))(void)    //使用((void(*)(void))(TargetAddr))()  也是否也可以??

第一个(( void( * )( void)) ,意思为将一常量TargetAddr强制类型转换为一个无形参,无返回值的函数指针,(*(TargetAddr))()表示跳转到TargetAddr地址执行,但是函数指针变量不能为常数所以要加((void( * )(  )) 进行强制类型转换。最后一个()为执行的意思。

整一条指定的目的是为了跳转到一个绝对地址执行函数。

1、在单片机中可以实现软件复位,比如跳转到0地址。

2、如果程序是由多个程序合并的,跳转到某一个确定的用户程序地址执行,如果flash空间足够大的话,可以实现当多份不相同的代码合并为一份后,在软件上做逻辑跳转,好处是新程序不必为旧程序做大量的兼容工作,通常旧程序含有大量的前人的编程习惯,比如宏定义。
————————————————-------------------------------------------------------------------------------------------------------------------------------------------------------

猜你喜欢

转载自www.cnblogs.com/FightingChen/p/12455022.html