arm處理器下的對齊異常1 簡介

2021-09-30 01:21:23 字數 3035 閱讀 1972

什麼是對齊異常呢,為什麼arm處理器下會有對齊異常?這個要先從arm 32位處理器下的兩條指令ldr與str說起。作為a32指令集的兩條最基本指令,str/ldr 可以用於暫存器與記憶體之間的資料交換,ldr是將記憶體中的數載入到暫存器,str是將暫存器中的數載入記憶體。a32下ldr與str一次操作4個位元組,例如如下匯程式設計序:

ldr     r1, 0xe0000000
該指令將0xe0000000位址的內容(4個位元組)載入到r1暫存器,這個0xe0000000位址顯然是4的倍數,也就是對齊的,當這個位址為0xe0000001/0xe0000002/0xe0000003時,就是非對齊的。在arm 32位處理器下,某些指令對記憶體位址進行非對齊的訪問,就會觸發對齊異常,比如vldr/vstr、ldrd/strd、vldm/vstrm、ldm/stm指令等,在arm64位處理器下,除了執行同樣32位的非對齊指令外,也有些指令會觸發對齊異常,比如device mem下的ldr/str相關指令。

該系列部落格會選用多個arm架構下處理器平台進行對齊異常的驗證、分析,並**出對應異常處理的解決方案,以下是示例平台:

arm32平台

imx6quad處理器:cortex-a9,4核,1.2ghz,執行32位linux系統,核心版本位3.14

樹莓派4-bcm2411處理器:cortex-a72,4核,1.5ghz,執行32位linux系統,核心版本為4.19

arm64平台

某國產處理器:armv8相容架構,4核,1.5ghz,執行64位linux系統,核心版本為4.4

…下面先用vldr指令對齊異常做個舉例介紹,通過執行資訊及核心日誌,對異常有個初步的認識。

首先是一段異常簡單的**,這段**中定義了乙個浮點指標,然後更改了它的位址為乙個未對齊的位址,給它賦值然後列印出來。

#include void main()

; float *flap = (float *)(buff+1);

*flap = 0.12345;

printf("float addr is %p\n", flap);

printf("float at &buff[1] is %f\n", *flap);

}

接下來編譯,並執行。

imx6下:

樹莓派下:

arm64下:

從上一節看出,只有arm64平台下面vldr程式可以正常執行。從應用程式列印資訊看,在arm32平台下,由於是32位定址空間,flap指標的位址,分別對應為0x7edf79e1和0xbee0b541,在arm64平台下,flap指標的位址為0x7fdc5b8c61(超過32位)。在執行程式出現異常後,通過dmesg命令查得異常資訊如下。

imx6:

root@imx6q-sbc:~/alignment# dmesg | tail

...[ 4594.164653] alignment trap: not handling instruction edd37a00 at [<00010410>]

[ 4594.170503] unhandled fault: alignment exception (0x011) at 0x7edf79e1

樹莓派:

pi@raspberrypi:~/alignment $ dmesg | tail

...[ 9688.413139] alignment trap: not handling instruction edd37a00 at [<0001045c>]

[ 9688.413155] unhandled fault: alignment exception (0x221) at 0xbee0b541

[ 9688.413177] pgd = 36a06f3e

[ 9688.413193] [bee0b541] *pgd=19bd2003, *pmd=7fd3c003

從核心日誌中可以看出,在0x7edf79e1位址與0xbee0b541分別產生了對齊異常,異常指令均為edd37a00 。然而,同樣的程式,arm64平台並沒有產生異常,接下來對比與arm32平台下的指令差異。

首先,用objdump工具對vldr程式進行反彙編,然後用compare工具對arm32平台(樹莓派)和arm64平台下彙編**進行對比分析。

可以看出,arm32平台下,用了vldr s15, [r3]指令,。其中s15為arm架構處理器下浮點暫存器,vldr指令為將r3暫存器中對應位址儲存的資料取出,放到浮點暫存器s15中。根據上面程式分析,r3暫存器儲存的位址為0xbee0b541,通過vldr指令取該位址的資料時,因為位址未對齊,產生了異常。

而在arm64平台下,因為編譯器的不同,編譯生成的是用ldr s0, [x0]指令,則沒有這個問題。假如在arm64平台下,執行同樣的非對齊vldr指令,是否會產生異常呢?實測是跟arm32情況一致,同樣產生異常。如下圖所示,用32位編譯器編譯同樣**後,在arm64平台下執行,同樣報bus error

對應dmesg資訊如下。

root@armv8:~/alignment# dmesg | tail

...[ 6594.336469] unhandled fault: alignment fault (0x92000021) at 0x00000000ffc50e81

文章中如有錯誤,請指正。

ARM處理器異常返回位址

在arm處理器中一條指令的執行分為取指 解碼 執行三個階段,由於指令流水線的存在造成當前執行的指令的位址是pc 8 arm指令集 那麼當前執行指令的下一條指令的位址應該是pc 4,所以在異常產生時處理器會將pc 4的值儲存到對應模式的lr暫存器中,但是該返回位址是否能夠被使用還要看具體產生的異常的種...

ARM微處理器系列簡介

嵌入式系統是當前最熱門 最有發展前途的it應用領城之一。隨著需求的增加,在嵌入式領域,8 位處理器已經不能勝任一些複雜的應用,例如gui tcpip filesystem 等,而arm 晶元憑藉強大的處理能力和極低的功耗,非常適合這些場合,所以現在越來越多的公司在產品選型時候考慮到使用arm 處理器...

ARM下的對齊處理

from dui0067d ads1 2 complib 3.13 type qulifiers 有部分摘自arm編譯器文件對齊部分 對齊的使用 1.align num 這個用於修改最高端別物件的位元組邊界。在彙編中使用ldrd或者strd時 就要用到此命令 align 8 進行修飾限制。來保證資料...