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

Posted fightingchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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空间足够大的话,可以实现当多份不相同的代码合并为一份后,在软件上做逻辑跳转,好处是新程序不必为旧程序做大量的兼容工作,通常旧程序含有大量的前人的编程习惯,比如宏定义。
————————————————-------------------------------------------------------------------------------------------------------------------------------------------------------

以上是关于C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧 (转)的主要内容,如果未能解决你的问题,请参考以下文章

C 语言一级指针 易犯错误 模型 ( 判定指针合法性 | 数组越界 | 不断修改指针变量值 | 函数中将栈内存数组返回 | 函数间接赋值形参操作 | 指针取值与自增操作 )

OC(C语言特性函数,指针)

C语言 如何给指针数组划分动态存储空间

C语言中,memset函数都可以给啥类型的数组清零?

从c语言函数调用看程序的栈机制

编写一个C语言的内存拷贝函数,把源地址的指定长度的数据拷贝到目标地址,考虑8,16,32位数据位宽