c - ARM 中 uint8_t 变量上的 LDR 行为?

标签 c gcc assembly arm gnu

我在任何地方都找不到这个问题的直接答案。 ARM的寄存器是32位的,我知道LDRB将一个字节大小的值加载到寄存器中,并将剩余的3个字节清零,即使你给它提供一个大于一个字节的值,它也只会取第一个字节的值。

我的程序将 C 与 ARM 汇编相结合。我在 C 中有一个外部变量,它直接加载到寄存器中。

但是,如果我在这个字节变量上只调用 LDR,是否可以保证它加载该字节而不加载其他内容,或者它会从内存中附近的内容加载剩余 3 个字节空间中的随机内容以填充整个 32-位寄存器?

我只是问,因为我执行了 LDR R0, =var 并且总是从大约一亿次执行中得到正确的值(软件运行了很长时间,并且在提出此问题之前经过了多次彻底测试/重新编译)在另一个设置上)。

然而,其他人使用不同的设置(没那么不同,我认为编译器是同一版本)成功编译了代码,但是加载到 R0 中的值被变量周围内存中的随机位污染了。他们必须使用 LDRB 来修复它。

这是编译器的事情吗?它能检测到这一点并自动切换到 LDRB 吗?或者我只是幸运的是,由于某些优化,变量的周围内存只是零?

顺便说明一下,编译器是 ARM GCC 9.2.1

最佳答案

because I did LDR R0, =var

您正在加载变量的还是地址

通常,指令LDR R0, =var会将变量var的地址写入寄存器R0,而不是值。

在 32 位 ARM CPU 上,变量的地址始终是 32 位值 - 与数据类型无关。

However if I call just LDR on this byte variable, ...

如果加载变量的(例如使用LDR R1, [R0]),可能会发生两种情况:

  • 寄存器的高 24 位可能包含随机值,具体取决于内存中变量后面的字节。如果幸运的话,字节始终为零。
  • 根据具体的 CPU 类型,您可能会因对齐而遇到问题(例如对齐异常,甚至完全未定义的行为)

关于c - ARM 中 uint8_t 变量上的 LDR 行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59915224/

相关文章:

c - 精确的多重 scanf 输入

C 程序无法识别全局变量

c++ - gcc 内联 asm 跳转到带有交叉抛出异常的标签

assembly - 8 位寄存器中的 0FBh 加 5 如何设置零标志?

c - 重新分配数组索引

c - 8 位 MCU 中的 32 位变量移位

c - 空或终止金丝雀

linux - GNU C 库 (glibc) 编译期间出错

iphone - 如何在 Xcode LLVM 中编写关于 LOOP 的内联汇编代码?

assembly - 如何在程序集 x86-64 中保存字符串临时变量