Assembly 为什么我需要在LDR指令中从标签中减去1?

Assembly 为什么我需要在LDR指令中从标签中减去1?,assembly,arm,cortex-m,iar,Assembly,Arm,Cortex M,Iar,我正在使用IAR Embedded Workbench开发ARM Cortex-M4处理器。当主堆栈溢出时,我得到一个总线故障。因此,我在汇编中编写了一个小函数,用于检查总线故障是否由堆栈溢出引起,设置堆栈指针并调用专用的堆栈溢出处理程序 下面的代码显示了该函数,它工作正常。我的问题是,我不得不从两个LDR指令中的标签中减去1,我不明白为什么 StackBegin: DC32 SFB(CSTACK) ; Start of main stack StackEnd:

我正在使用IAR Embedded Workbench开发ARM Cortex-M4处理器。当主堆栈溢出时,我得到一个总线故障。因此,我在汇编中编写了一个小函数,用于检查总线故障是否由堆栈溢出引起,设置堆栈指针并调用专用的堆栈溢出处理程序

下面的代码显示了该函数,它工作正常。我的问题是,我不得不从两个LDR指令中的标签中减去1,我不明白为什么

StackBegin:     DC32        SFB(CSTACK) ; Start of main stack
StackEnd:       DC32        SFE(CSTACK) ; End of main stack
BusFault_Handler:
                LDR         R0, StackBegin-1 ; No idea why we need to subtract 1
                CMP         SP, R0
                IT  GT
                BGT         BusFault_Post_Handler   ; Call if SP is OK
                LDR         SP, StackEnd-1          ; On stack overflow, set SP to top of main stack; No idea why we need to subtract 1
                B           MainStackOverflow_Handler
如果不减去1,LDR指令将在标签后加载一个字节的数据。StackEnd包含值0x20000400,但SP加载0x5F200004,除非我从标签中减去1。0x5F是BUSU处理程序中的第一个字节


有人能解释为什么我需要减去1吗。我的配置有问题吗。我已经检查了数据是否是字(4字节)对齐的。

当在thumb模式下为定义的标签计算地址时,汇编程序将自动设置最低有效位,因为它假定代码标签是分支目标,而不是其他目标。因此,当
StackBegin
StackEnd
标签被定义为代码的一部分时,它们将设置LSB

为避免此问题,请确保在定义
StackBegin
StackEnd
标签时,汇编器处于数据模式

        THUMB
BusFault_Handler:
        LDR         R0, StackBegin
        CMP         SP, R0
        IT  GT
        BGT         BusFault_Post_Handler   ; Call if SP is OK
        LDR         SP, StackEnd            ; On stack overflow, set SP to top of main stack;
        B           MainStackOverflow_Handler

        DATA
StackBegin:     DC32        SFB(CSTACK) ; Start of main stack
StackEnd:       DC32        SFE(CSTACK) ; End of main stack
        THUMB

程序内存中的两个常量可能没有正确对齐。尝试在两个
DC32
指令之前添加
ALIGN 2
。此外,您还需要
IT HS
(“unsigned higher or same”),因为指针是无符号的,最低堆栈地址
SFB(CSTACK)
是一个有效地址。可能
CSTACK
部分没有按4对齐?在这两种情况下生成了什么asm代码?StackEnd包含值0x20000400您是如何发现的?可能是汇编程序在标签地址中添加了1,因为标签在thumb模式下位于文本部分。@fuz-很好的观点。根据:“在使用DC8、DC16或DC32定义Thumb代码部分中的数据时,始终使用DATA指令,否则数据上的标签将设置位0。”。实现该目标的一个更简单的方法是执行
LDR R0,=(SFB(CSTACK))
您最好清除位0(
bic address,address,#1
),而不是减去1。非常感谢。我不知道LSB是为代码段中的标签设置的。将其放在数据部分可以解决这个问题。