assembly - armv7-m 裸机 ldr/str 符号内存

标签 assembly arm armv7

所以我知道关于arm上的ldr/str的问题是无数的。也许这是另一个转折(不太可能),或者我只是错过了一些东西(更有可能。)

所以这是裸机,我想在内存中加载/存储一些变量。因为我坚持要给它一个名字。天真地我可以写:

.section .bss
var: .word 0

.section .text
str r0, var 

(有一个自定义链接器脚本,将 .bss 放入 RAM 并将 .text 放入 Flash)

当然,这不起作用,因为指令是 32 位的,并且只能容纳一些较小的立即数。我所说的指令位于闪存中,即 0x8000000+x,变量将存储在内存中,即 0x20000000+y 中的某个位置。

手动我知道很多方法来解决这个问题:

  • 将变量地址存储在常量中(varaddr: .word 0x2001234; ldr r1, [pc,#varaddr]; str r0, [r1])
  • 将 ram-base 加载到寄存器中并相对寻址 (ldr r1, #0x20000000; str r0, [r1,#varoffset])
  • 通过算术构造地址(mov r1, #0x2000000; add r1, #offset/orr/movw/movt Something)
  • 当然还有更多

这些变体中的每一个都有效,但是这些变体都不允许我使用我真正想要使用的标签。

那么我在这里缺少什么。我对链接器脚本和标签的想法是假的吗?是否有一些我没有看到的汇编器功能?完全不同的东西?

最佳答案

在静态存储中使用变量符号名称的一种方法是为变量定义一个结构。这允许您将结构的基地址加载到寄存器中,然后使用相对于基地址的符号名称访问结构成员。例如,您可以这样做:

        .struct 0          @ start a new structure
foo:    .skip 4            @ length of foo
bar:    .skip 4            @ length of bar
baz:    .skip 4            @ length of baz
len:                       @ total length of the structure

        .section .bss      @ switch to the BSS (uninitialised data) section
        .balign 4          @ align to 4 bytes
variables:
        .space len         @ reserve space for your variables

        .section .text     @ switch to the text (code) section

        ...
        ldr r0, =variables @ load r0 with the base address of your variables
        ldr r1, [r0+#foo]  @ access foo
        str r2, [r0+#bar]  @ access bar
        ldr r3, [r0+#baz]  @ access baz

这几乎是静态存储中变量最接近的符号名称。如果变量位于堆栈上,则可以使用类似的方法,使用帧指针(或堆栈指针)作为基地址。 .struct 的操作数是结构的基地址,您可以为其选择任何您喜欢的值。

至于movwmovt。与 ldr ..., =... 相比,它们在某些微架构上提供了微小的性能优势,因为它们不需要将数据提取到文本部分。据我所知,这对 armv7-m 目标没有影响;此外,与使用 = 操作数的 ldr 相比,movwmovt 多消耗两个字节。因此,我建议您坚持使用 ldr= 操作数。 movwmovt的用法是这样的:

        movw r0, :lower16:foo  @ load lower 16 bit of foo's address into r0
        movt r0, :upper16:foo  @ or higher 16 bit of foo's address into r0

这两个必须按特定顺序发出,因为 movw 会清除高 16 位。前缀 :lower16::upper16: 选择适当的重定位类型,仅引用符号地址的低位和高位 16 位。您可以创建一个宏以使其更易于键入:

        .macro addr reg, sym
        movw \reg, :lower16:\sym
        movt \reg, :upper16:\sym
        .endm

这允许你写

        addr r0, foo

生成上述movwmovt对。

关于assembly - armv7-m 裸机 ldr/str 符号内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60626117/

相关文章:

java - 有哪些 JVM 汇编程序?

c - 如何从操作码/机器码中获取汇编指令或助记符?

assembly - 在 NASM 汇编中对数字进行平方而不进行乘法

gcc - 从 Winarm 迁移到 Yagarto

macos - 对 Apple Silicon 的 SSE/neon 支持

linker - 移动到 iOS6 我收到了几乎所有外部包的链接器错误

macos - Segmentation Fault 11链接OS X 32位汇编器

c - 如何使 ARM Eclipse for DS-5 识别编译器预定义宏?

ios - XCODE 6.4 - 架构 armv7 错误的 undefined symbol

ios - i386/armv7 架构的 undefined symbol [cocoapods]