簡體   English   中英

LDR 在 ARM 中的 uint8_t 變量上的行為?

[英]Behavior of LDR on a uint8_t variable in ARM?

我在任何地方都找不到直接的答案。 ARM 的寄存器是 32 位的,我知道 LDRB 將一個字節大小的值加載到一個寄存器中,並將剩余的 3 個字節清零,即使你給它一個大於一個字節的值,它也只會取第一個字節值。

我的程序將 C 與 ARM 匯編相結合。 我在 C 中有一個 extern 變量,它直接加載到寄存器中。

但是,如果我只在這個字節變量上調用 LDR,是否可以保證它只加載字節而不加載其他任何東西,或者它是否會從內存中附近的事物中加載剩余的 3 字節空間中的隨機事物以填充整個 32 位寄存器?

我只是問,因為我做了 LDR R0, =var 並且總是從大約一億次執行中得到正確的值(軟件運行了很長時間並且在這個問題出現在另一個設置上之前經過了徹底的測試/重新編譯了很多次)。

然而,其他具有不同設置的人(不是那么不同,我認為編譯器是相同的版本)成功編譯了代碼,但是加載到 R0 中的值被變量周圍內存中的隨機位污染了。 他們不得不做LDRB來修復它。

這是編譯器的事情嗎? 它可以檢測到這一點並自動將其切換到 LDRB 嗎? 或者我只是幸運,由於一些優化,變量的周圍內存只是零?

作為旁注,編譯器是 ARM GCC 9.2.1

因為我做了LDR R0, =var

你是加載變量的還是地址

通常,指令LDR R0, =var會將變量var的地址寫入寄存器R0而不是值。

並且變量的地址在 32 位 ARM CPU 上始終是 32 位值 - 與數據類型無關。

但是,如果我只在這個字節變量上調用LDR ,...

如果加載變量的(例如使用LDR R1, [R0] ),可能會發生兩件事:

  • 寄存器的高 24 位可能包含一個隨機值,具體取決於內存中變量后面的字節。 如果幸運的話,字節總是為零。
  • 根據確切的 CPU 類型,您可能會因對齊而遇到問題(例如對齊異常甚至完全未定義的行為)

LDR 對您如何聲明變量或它加載的 4 個字節中應該包含的內容一無所知。 這就是為什么像 ARM 這樣的 ISA 首先具有像 LDRB(及其符號擴展等效項)這樣的字節加載。

不,編譯器不會在每個uint8_t之后浪費 3 個字節(零),這樣您就可以在其上使用字加載,這很愚蠢。 sizeof(uint8_t) = 1 = unsigned char, CHAR_BIT = 8, and alignof(uint8_t) = 1

LDR 加載int32_tuint32_t整個單詞。

但正如馬丁指出, LDR r0, =var把地址var到寄存器中。
然后你使用ldrb r1, [r0]

有趣的事實:具有未對齊字加載的早期 ARM CPU(ARMv4 及更早版本)將使用地址的低 2 位作為循環計數(從對齊字加載后)。 https://medium.com/@iLevex/the-curious-case-of-unaligned-access-on-arm-5dd0ebe24965

暫無
暫無

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

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