2013-08-16 57 views
3

我有一個地址不是4字節對齊的對象。當存在STR指令保存2個寄存器時,這會在CPU中導致HardFault錯誤。未對齊的訪問會導致ARM Cortex-M4上的錯誤

這是所生成的代碼:

00000000 <_ZN8BaseAreaC1EPcmm>: 
    0: b510   push {r4, lr} 
    2: 4604   mov  r4, r0 
    4: 6042   str  r2, [r0, #4] 
    6: e9c4 3102  strd r3, r1, [r4, #8] 
    a: 2001   movs r0, #1 
    c: 7420   strb r0, [r4, #16] 
    e: b921   cbnz r1, 1a <_ZN8BaseAreaC1EPcmm+0x1a> 

這些寄存器當在線 「4:6042 ...」

R0 08738B82 R8   0 
R1 08738BAE R9   0 
R2   0 R10 082723E0 
R3  2FCC R11   0 
R4 08738B82 R12   0 
R5 20007630 R13 2000CB38 

正如所看到的目標寄存器STR-指令不以4字節對齊。指令STR r2, [r0, #4]執行正常。但它在下一個STRD r3, r1, [r4, #8] HardFault。如果我手動將寄存器R4更改爲08738B80它不會出現硬故障。

這是產生上述ASM C++代碼:

BaseArea::BaseArea(char * const pAddress, unsigned long startOffset, unsigned long endOffset) : 
m_pAddress(pAddress), m_start(startOffset), m_end(endOffset), m_eAreaType(BASE_AREA) { 

而且m_start是在類中的第一變量和具有相同的地址作爲this (08738B82),後m_end如下上0x08738B86

如何獲得4字節對齊的對象? 任何人都有其他解決方案?

+0

你是否實際上在彙編程序設計,或是由例如產生該代碼一個C編譯器? –

+1

@JoachimPileborg:鑑於它明顯地「破壞了C++的名字」,我懷疑它是C++代碼。 –

+0

這是從C++生成的彙編代碼。 – rdrmntn

回答

11

在基於ARM的系統上,無法尋址未對齊到4字節邊界的32位字(正如您的錯誤告訴您的那樣)。在x86上,您可以訪問未對齊的數據,但性能會受到很大影響。

ARM上的邊界錯誤示例(here),TLDR:將指針存儲到unsigned char,然後嘗試將其轉換爲double *(雙指針)。

要解決您的問題,您需要請求一個4字節對齊的內存塊並複製未對齊的字節+用垃圾字節填充以確保它是4字節對齊的(因此執行數據結構手動對齊)。然後,您可以將該對象解釋爲與其新地址對齊的4個字節。

從TurboJ在評論中,明確的錯誤:

Cortex-M3 and M4 allow unaligned access by default. But they do not allow unalinged access with the STRD instruction, hence the fault.

你也可以發現它有助於尋找到this對ARM迫使數據結構對齊。

+0

在x86上,只有當您的訪問跨越64B行邊界(或者 - 上帝禁止 - 頁面邊界)時,纔會影響性能。僅僅在一行內訪問幾個未對齊的字節並不重要,只需要整行緩存即可。 – Leeor

+0

@Leeor,我把我的初步答案作爲一個社區維基,因爲ARM不是我所熟悉的領域(讓其他人爲一個集體,強有力的答案做出貢獻)。我確信有很多細節可以忽略或不說明,因此可以分別編輯原文。 –

+0

對不起,我可能更不熟悉ARM微架構,我在談論x86參考 – Leeor

0

以下爲ARM架構真正至少(覈實皮質M0):

當使用加載和存儲指令,我們訪問必須由我們從試圖訪問的字節數整除的內存/到內存,否則我們會得到一個硬故障異常。

如:

LDR r0, = 0x1001 
LDR r1, [r0] 

在上面的第二行代碼將使硬故障,因爲嘗試讀取4個字節,但如果我們將第二行中的內存地址是不能被4

整除在上面的代碼爲以下從地址

LDRB r1, [r0]; //加載1字節以上線不會產生硬故障,因爲我們試圖訪問1個字節(1字節可以從任何內存位置訪問)

另請注意以下示例;

LDR r0,= 0x1002 
LDRH r1,[r0]; //Load half word from 0x1002 

上述線不會產生硬故障,由於存儲器存取爲2個字節,地址爲整除2.

+1

與LDR和STR指令一樣,Cortex-M3至少與字對齊的地址看起來像支持未對齊的訪問,只有當配置控制寄存器中的UNALIGN_TRP位爲1時纔會產生對齊錯誤。 –

相關問題