要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
*((void (*)( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
*((void (*)())0x100000)();
用typedef可以看得更直观些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
下面是一本关于驱动开发的书上的一段关于绝对地址操作的描述。
目前,大多数嵌入式微控制器如Arm、PowerPC等并不提供I/O空间,而仅存在内存空间。内存空间可以直接通过地址、指针来访问,程序和程序运行中使用的变量和其他数据都存在于内存空间中。
内存地址可以直接有C语言指针操作,例如在186处理器中执行如下代码:
unsigned char *p = (unsigned char*)0xf000ff00;
*p = 11;
以上程序的意义为在绝对地址0xf000+0xff00(186使用16位段地址和16位偏移地址)写入11。而在Arm、PowerPC等未采用段地址的处理器中,p指向的内存空间就是0xf000ff00,而*p=11就是在该地址写入11。
再如,186处理器启动后会在绝对地址0xffff0(对应C语言指针是0xf000ff00,0xf000为段地址,0xfff0为段内偏移)执行,请看下面的代码:
typedef void (*lpFunction)();/*定义一个无参数、无返回类型的函数指针类型*/
lpFunction lpReset = (lpFunction)0xf000fff0;/*定义一个函数指针,指向CPU启动后所执行第一条指令的位置*/
lpReset();/*函数调用*/
在以上程序中,没有定义任何一个函数实体,但是程序中却执行了这样的函数调用:lpReset(),它实际上起到了“软重启”的作用,跳转到CPU启动后第一条要执行的指令的位置。因此,可以通过函数指针调用一个没有函数体的“函数”,本质上只是换一个地址开始执行。