寄存器绝对地址操作

嵌入式系統中往往需要讓程序跳到內存的某個地址去執行,比如想讓程序跳轉到絕對地址是0x100000去執行,應該怎麼做?

這樣:

*(( void (*)( void))0x100000)();

即可。

解釋一下,想讓程序跳到某個絕對地址去執行得用函數指針,這或許也是函數指針的一個妙用吧!

語句void(*)(void)聲明了一個返回值是void、無參數的函數的函數指針,這個指針沒有名字但有指向的地址。就是說地址0x100000是一個返回值是void、無參數的函數的起始點,其實就是函數名,這里也印證了函數名就是函數地址。拆開看看:

void (*)( void)0x100000

這個家伙是個指針,函數的實際地址在它指向的地方,所以需要取內容,于是就*(void (*)(void)0x100000)。這樣一來這個表達式就是這個“函數的地址了”,也就是函數名,函數名後面打個括號加上參數就行了,于是最後就是*(void (*)(void)0x100000)()。

也可以這樣理解:

首先要將0x100000強制轉換成函數指針,即:

( void (*)( void))0x100000

然後再調用它:

(( void (*)( void))0x100000)();

用typedef可以看得更直觀些:

typedef  void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();

 

寫到這里我想到了另外一個問題:想要讀寫絕對地址0x00001234處的數據(4個字節)咋辦?

你可能很快就會這樣做:

unsigned  long *p = 0x00001234;
//
int var1 = *p;
//
*p = 0x1111;

這樣不錯,不過你為了讀寫這四個字節的區域聲明了一個指針變量,指針變量本身占4個字節,如果p以後還有很多工作也就罷了,如果它從此就不再使用了,那么這樣做就純屬沒必要,還高的變量多看花了眼,可以這樣:

(*((unsigned  long *)0x00001234))

 

//
int var = ( int)(*(( volatile unsigned  long *)0x00001234));
//
*(( volatile unsigned  long *)0x00001234) = 0x1111;

嵌入式系統中常用的讀寫寄存器的方法就是這樣,比如:

#define REG_1 (*((volatile unsigned long *)0x00001234))

那么就可以隨意的操作寄存器REG_1了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值