簡體   English   中英

在ARM內聯匯編中修改sp

[英]Modifying sp in ARM inline assembly

我知道在x86中有一些規則來管理堆棧指針的修改:

RSP當前地址以外的所有內存均被視為易失性:OS或調試器可能會在用戶調試會話或中斷處理程序期間覆蓋此內存。 因此,在嘗試向堆棧幀讀取或寫入值之前,必須始終設置RSP。

我的問題是,ARM的規則是什么? 我正在看這段代碼(請參見下面的摘錄),看起來它違反了x86規則(修改內存然后更改了堆棧指針),但是在ARM上有問題嗎?

mov r4, sp
sub r4, r4, #128

...

mov r3, #116
1: ldr r7, [r2]
add r2, r2, #4
str r7, [r4]
dd r4, r4, #4
sub r3, r3, #4
cmp r3, #0
ne 1b

sub sp, sp, #128

我曾嘗試使用谷歌搜索,但要找到一個規范來描述如何在嵌入式asm中修改ARM堆棧是一項挑戰。 有一些關於ARM編譯器和修改堆棧的文檔,但是gcc的規則似乎有所不同。

您所說的“規則”有點詳盡和具體。 但是“規則”適用於幾乎所有使用一個堆棧進行所有處理的處理器。

通常,您應該首先移動堆棧指針以“分配”所需的堆棧空間,這是防止下一件事物被破壞的方式。 然后將其移回去分配。

對於ARM,可能是您鏈接的代碼。 您已經將寄存器存放在架構參考手冊中的第一章之一中(需要在分析或編寫匯編語言之前閱讀其中的內容,尤其是寄存器上的一幅圖)。 如圖所示的異常模式都有各自的堆棧指針。 因此,例如在發生中斷時,將使用其他一些堆棧指針來保存狀態,因此不會破壞您的數據。

用戶和系統共享一個堆棧指針,但這是為了使內核等代碼可以訪問而不會陷入用戶模式。 系統不用於異常,因此您的代碼不會只是停止並切換狀態並破壞堆棧。

現在,ARM與其他任何品牌的福特一樣。 他們使大型卡車變成小型卡車,SUV,小型車,爺爺車等。ARM擁有廣泛的處理器內核。 cortex-m適用於微控制器和其他狹小空間。 它只有一個堆棧,當發生異常時,它將為您保存堆棧中的狀態,從而破壞您的數據。 因此,您指出的代碼會很糟糕,因為您為什么要在cortex-m上使用printf?

可以將編譯器配置為使用第二個堆棧指針,也可以不使用第二個堆棧指針,x86世界已習慣於這種想法(sp和bsp),但這不是必需的。 為了使(數據)堆棧有用,需要有一個堆棧指針和用於引用堆棧指針相關尋址的已使用堆棧部分的指令。 在某些平台上,您可以訪問堆棧指針,並使用另一個寄存器(進行復制)訪問堆棧幀,從而使堆棧指針可以自由漫游。 通常,有或沒有,在內聯匯編中觸摸堆棧指針都是一個非常糟糕的主意,您需要了解您的工具鏈,並且這樣的代碼將需要不斷的維護,編譯器的每個新版本或編譯該代碼的每個新系統然后,您必須手動檢查產生的輸出,以確保操作安全。 如果要達到這個水平,為什么要使用內聯匯編並燒掉所有這些工時(工作安全性?),那么您會第一次使用匯編並制造安全可靠的東西。 如果只想為該函數提供更多數據,只需創建一個局部變量,它就會更改sp的減法,完成。 無需內聯匯編。 如果您希望超越堆棧的末端,請使用匯編而不是內聯匯編。 如果您要修改堆棧指針或出於某種原因快速分配而不使用局部變量,請再次使用匯編程序,並將堆棧指針移到必須避免此數據損壞的系統上。

除了使系統崩潰之外,在內聯匯編中弄亂堆棧指針也沒有多大意義。 與arm或x86無關,或填寫空白。

他們在那里所做的就是使用內聯匯編在匯編中編寫整個功能。 這可能只是他們選擇的構建系統的一種情況,您可以將程序集送入gnu C編譯器(如果使用內聯程序集,則無論如何都必須編寫特定於編譯器的代碼,這樣您就已經知道要使用的編譯器)並產生一個對象,就像您可以使用C。他們還有其他方法可以做到這一點,但並不那么難看。 不幸的是,看到這種解決方案並不罕見。 如果在非cortex-m上運行,那么該代碼是安全的,您不能在其中途添加函數調用,因為這將破壞數據,它們確實在調用之前而不是向上移動堆棧指針前面像一個正常的解決方案。 必須追蹤作者,問“他們為什么這樣做”的問題。

ARM沒有這樣的規則。 CPU(至少是Cortex-A / R CPU)不會在發生中斷時自動堆棧寄存器,即使對於Cortex-M,也可以保證保持順序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM