2012-02-01 66 views
6

我遇到了我徹底不明白的東西。 有一個函數原型:功能指針與海灣合作委員會,分配地址

typedef void (* TMain) (void); 

和功能變量:

TMain myFunc = MyFunc; 
... 
myFunc(); 

這工作得很好,當然。爲什麼不應該。

從MAP文件我知道「MyFunc」位於0x20100位置。 現在有趣的事情。在賦值「myFunc = MyFunc;」之後變量「myFunc」不包含包含值0x20100,而是0x20101!

我的問題是,我需要調用一個函數,我知道表中的地址。所以我想我會那樣做

myFunc = (TMain) myTable [ 5 ]; // that would be 0x20100 
myFunc();       // which produces a proper crash 

但是如果我做

myFunc = (TMain) ((Int8 *) myTable [ 5 ] + 1); 
myFunc(); 

然後它工作。

這裏會發生什麼?我是否總是必須添加1的偏移量,或者這或多或少是偶然的? 還是有更好的(和工作)的方式來完成任務?

非常感謝任何提示。 Walter

+2

不確定,但這可能取決於架構。所以可能想說哪個是目標架構。 – phimuemue 2012-02-01 09:34:35

+1

是'TMain []''類型的myTable'數組嗎?我認爲這不是因爲你在投它。 – 2012-02-01 09:35:36

+1

對你有些問題:你在使用什麼平臺(ARM,x86 ...)?你有沒有用調試器檢查函數的實際地址?你能看到編譯器如何生成間接調用「myFunc()」嗎? – 2012-02-01 09:39:20

回答

3

幾種CPU架構爲特定目的保留函數的第一個字節。 VAXen在那裏有一個保存寄存器掩碼。 CDC Cyber​​將回復地址放在那裏。有些使用「地址」的某些位來表示地址間接(我不記得哪一個,但他們是從20世紀70年代開始的)。

除非你真的知道你在做什麼,否則你不應該編寫那種做指針算術的代碼。爲變量分配函數名稱並用它完成:保證在每個C實現中都能正常工作。

3

我的猜測是你在ARM的目標,你已經建立你的程序在拇指模式? (Thumb是ARM Ubuntu或Linaro的默認設置。)

函數地址的最低位告訴CPU應該在哪個指令集中解釋函數。 0是ARM模式。 1是拇指模式。因此所有的拇指模式函數指針都是奇數。

其他體系結構也以這種或那種方式使用這種習語。通常只需將地址的底部兩位清零(使其4字節對齊)並假定這是該函數的真實位置即可。

相關問題