2012-04-02 46 views
2

我正在嘗試使用android NDK爲android平臺編譯和運行本機代碼。 在代碼中的很多地方,我試圖將一個短整型指針指向一個整型指針,因此它具有內存對齊問題,儘管它可以與X86一起正常工作。我正在用拇指模式編譯代碼,因爲正如我上面所說的那樣,代碼是由於未對齊的訪問而進行的。但是如果我在ARM模式下編譯代碼,它不會崩潰並正常工作。Android原生代碼在拇指模式下崩潰,但沒有在手臂模式下

我的疑惑是爲什麼代碼在arm模式編譯時沒有崩潰,雖然它有內存對齊問題。

我對ARM和THUMB指令集知之甚少。我知道ARM指令集是32位寬,拇指是16位寬。但是,關於未對齊訪問,它是如何產生影響的?

回答

2

我不認爲崩潰是由指令編碼長度造成的。 ARM和Thumb模式應該具有從對齊或未對齊的地址加載數據的相同能力。

首先,你使用真正的ARMv5硬件,真的不允許未對齊的32位負載?由於更新的ARM芯片(例如運行Android爲ARMv5TE編譯的ARMv6(ARM11)芯片)可以執行未對齊的32位加載並且不會崩潰。當然,如果您的清單聲明它是針對ARMv5TE編譯的,那麼運行在真實ARMv5硬件上的Android設備將會愉快地安裝並崩潰 - 您有責任確保您的應用程序與其聲稱的內容真正兼容。

的Qemu(包括在Android SDK捆綁模擬器)不正確地模擬對未對齊的32位的負載崩潰時,它模擬一個arm926ej-s(用於ARMv5TEJ)芯片。你不能依靠模擬器來捕捉這個。在這方面,它的確對Java開發非常有用。

你能在gdb中看到崩潰嗎?你可以顯示寄存器轉儲並查看來自未對齊地址的負載嗎?你確定編譯器不會改變你的代碼的含義嗎(以一種允許的方式)?

對於超出x86的可移植性,您實際上不應執行從uint16_t*uint32_t*的強制轉換。 C語言不保證它們能夠工作。從技術上講,你的代碼總是「錯誤的」。在野外查看可移植代碼:它使用預處理器宏或靜態內聯函數來抽象概念,如「get_unaligned_le32」或x86上依賴未對齊訪問的整個函數。

+0

非常感謝您的回覆, – user1161240 2012-04-02 14:59:17

0

Thumb指令每個長16位,而ARM指令長32位。

這意味着在ARM模式下,可以保證代碼中的數據部分是4字節對齊的,但不是在Thumb模式下。

您可能會嘗試對齊指令。對齊語法因編譯器/彙編程序而異。

某些庫中的一些(依賴於硬件的)例程假定數據是4byte對齊的,而不管數據類型如何。 如果沒有滿足這個條件,它會崩潰或性能嚴重受損。另外,如果考慮到高速緩存,無論如何明智地調整性能關鍵數據是明智的。緩存友好的對齊取決於SoC,但通常是32byte到ARM11,64byte的Coretex。

+0

感謝您的回覆, – user1161240 2012-04-03 03:53:39

+0

我也懷疑崩潰是否總是定義misslligned內存訪問的結果或者它可能不會崩潰?由於在我的代碼中有很多指針有錯誤的地址,但代碼崩潰只有幾個指針不是全部,所以請讓我知道你對此的評論。 – user1161240 2012-04-03 03:57:43

+0

在拇指模式下,數據有4個字節對齊的可能性爲50%。這解釋了不一致。 – 2012-04-03 05:17:09

相關問題