2011-08-19 42 views
1

所以最近我一直想從程序集中調用一些win32調用,並且我一直在使用NASM作爲我的外部彙編程序。我在我的代碼在以下方法調用SendMessage立即調用與dword addr附近的調用dword

call [email protected] 

這被組裝成一個相對跳轉(0xE8操作碼),結果是訪問衝突。在調試器中,計算出的跳轉偏移似乎是正確的(因爲[email protected]確實似乎在那裏),但它仍然不起作用。當我從C++調用函數時,檢查由Visual Studio生成的程序集時,我注意到它不是它正在使用的相對直接跳轉,而是(用MASM語言)call dword ptr [[email protected]],對應於0xFF15操作碼。經過一番爭論之後,我發現NASM的語法編碼爲call dword near [dword [email protected]],並且讓我的代碼突然變得有效。

我的問題是,爲什麼一個人工作,而不是另一個?是否存在一些代碼重定位,導致相對的立即調用跳到不友好的地方?我從來沒有成爲程序員,但我的印象是總是這兩個調用應該做同樣的事情,主要區別在於一個是位置獨立的,另一個不是(假設他們將IP移到同一個地方)。代碼理論的重新定位是有道理的,但是你怎麼解釋顯示正確地址的調試器呢?

另請參見:此調用中[]語法背後的邏輯是什麼?偏移量仍然是一個立即數(只是在0xFF15之後立即編碼的小端),除了取指令之外,我還沒有進行存儲器訪問(我傾向於認爲[]lea的上下文之外的取消引用)。

回答

1
call dword[[email protected]] 

_ 小鬼 _SendMessageW @ 16是一個地址到包含API函數的地址,你的導入部分。你用方括號來尊重(叫這個地址存儲的地址)

+0

啊,等一下然後......'__imp__SendMessageW @ 16'是一個函數指針嗎?所以這個問題大概是這個數據駐留在一個不執行的頁面上,這就是爲什麼我得到一個訪問衝突,這是正確的嗎? – 808140

+0

是的,你基本上試圖將只讀數據作爲代碼運行。 –

+0

那麼,後續的問題是:產生這種間接性的邏輯是什麼?稍微的實驗證實我不能直接調用'_SendMessageW'或'SendMessageW',儘管VS調試器將'[dword __imp__SendMessageW @ 16]'的值識別爲'SendMessageW'。我知道Linux系統通過一個表共享庫索引函數,但我想我記得讀過Windows實際上的重定位,即它維護代碼中的偏移量列表並在加載時對其進行修補。我誤解了嗎? – 808140