【问题标题】:Reference to a C pointer from Assembler从汇编程序引用 C 指针
【发布时间】:2020-09-11 06:23:51
【问题描述】:

我想在汇编函数中引用一个 c 指针。在 C 中声明如下:

const uint32_t *SERCOM0_SPI_DATA_REG_ADDR = (volatile uint32_t *) &(SERCOM0->SPI.DATA.reg); // uint32_t reg;

在汇编中,指针地址(0x40003028)在调试器中正确显示。使用以下代码,我想将值 0x1f 写入 uint32_t 的 spi 寄存器。

// reg uint32_t sercom spi data
    ldr r0, =SERCOM0_SPI_DATA_REG_ADDR
    ldrb r1,=#0x1f
    str r1, [r0]  

如果我现在查看寄存器 r0,其值不是 0x40003028,而是 0x20000F8C。因此在地址处写入的不是0x1f的值。

在反汇编窗口中:

    44:     ldr r0, =SERCOM0_SPI_DATA_REG_ADDR
00007804   ldr  r0, [pc, #28]        
    45:     ldrb r1,= #0x1f // SERCOM0_SPI_DATA_SYNC_DATA
00007806   mov.w    r1, #31      
    46:     str r1, [r0]  

汇编文件是这样的:

.section .ram
.syntax unified
.cpu cortex-m4
.thumb

.space 0xe4
.data
.text
.align 4

.type SEND_DATA, %function
.global SEND_DATA

VUSB_SEND_DATA:
...
bx lr

【问题讨论】:

    标签: assembly arm gnu-assembler


    【解决方案1】:

    回想一下,汇编中的符号是它们所代表的变量的地址。所以

    ldr r0, =SERCOM0_SPI_DATA_REG_ADDR
    

    SERCOM0_SPI_DATA_REG_ADDR的地址加载r0,大致等于

    r0 = &SERCOM0_SPI_DATA_REG_ADDR;
    

    要加载那个变量的,你需要解引用你刚刚获得的指针:

    ldr r0, =SERCOM0_SPI_DATA_REG_ADDR    @ load address of variable
    ldr r0, [r0]                          @ load value of variable
    

    将此与您剩余的代码结合起来,这应该可以解决您的问题。请注意,为了获得更好的代码大小,我建议在拇指目标上加载小常量时显式使用movs

    ldr r0, =SERCOM0_SPI_DATA_REG_ADDR
    ldr r0, [r0]
    movs r1, #0x1f
    str r1, [r0]
    

    这应该会产生预期的结果。

    【讨论】:

    • Tnx,然后我直接写地址,因为这花了我一个ldr。这是正确的吗?或者我可以做什么,我只需要 3 条指令?
    • 你可以这样做,这会将它减少到三个指令。但同样,为什么不让 C 编译器为你做这件事呢?请注意,如果您在同一地址区域中有多个寄存器,则可以使用索引寻址模式以避免一次又一次地重新加载地址。
    • 是的,好主意,但我不具备这样做的知识。能给我举个例子吗?我希望你不是说我用 C 写的。使用纯 c 我们还有另一个问题。因为优化,我们必须用 asm 写。
    • @makurisan。不,您不需要“因为优化”将其写在 asm 中。优化只会“破坏”您的代码,因为您的代码不正确。如果您编写正确的 C 代码,优化器不会破坏它。显然,您尝试在汇编中编写部分代码时已经过头了。这种方法不会导致任何有用的地方。通过实际修复您的 C 代码使其没有缺陷,您的时间会花得更好。
    • 你现在已经花了三四个问题浪费大家的时间,要求人们修复非常不正确的汇编代码,这些汇编代码可以用非常简单的 C 代码代替。要么学习如何在汇编中编程,要么学习如何编写正确的 C 代码,但你目前的方法行不通。
    猜你喜欢
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 2022-01-11
    • 2021-08-26
    • 2010-12-02
    相关资源
    最近更新 更多