所以最近我一直想從程序集中調用一些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
的上下文之外的取消引用)。
啊,等一下然後......'__imp__SendMessageW @ 16'是一個函數指針嗎?所以這個問題大概是這個數據駐留在一個不執行的頁面上,這就是爲什麼我得到一個訪問衝突,這是正確的嗎? – 808140
是的,你基本上試圖將只讀數據作爲代碼運行。 –
那麼,後續的問題是:產生這種間接性的邏輯是什麼?稍微的實驗證實我不能直接調用'_SendMessageW'或'SendMessageW',儘管VS調試器將'[dword __imp__SendMessageW @ 16]'的值識別爲'SendMessageW'。我知道Linux系統通過一個表共享庫索引函數,但我想我記得讀過Windows實際上的重定位,即它維護代碼中的偏移量列表並在加載時對其進行修補。我誤解了嗎? – 808140