为什么LDR指令中的label要减1?
Why do I need to subtract 1 from label in LDR instruction?
我正在使用 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 MainWhosebug_Handler
如果我不减 1,LDR 指令会在标签后一字节加载数据。 StackEnd 包含值 0x20000400,但 SP 加载了 0x5F200004,除非我从标签中减去 1。 0x5F 是 BusFault_Handler 中的第一个字节。
任何人都可以解释为什么我需要减去 1。我配置错了吗?我检查过数据是字(4 字节)对齐的。
当计算在拇指模式下定义的标签的地址时,汇编程序将自动设置最低有效位,因为它假定代码标签是分支目标,没有别的。因此,当 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 MainWhosebug_Handler
DATA
StackBegin: DC32 SFB(CSTACK) ; Start of main stack
StackEnd: DC32 SFE(CSTACK) ; End of main stack
THUMB
我正在使用 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 MainWhosebug_Handler
如果我不减 1,LDR 指令会在标签后一字节加载数据。 StackEnd 包含值 0x20000400,但 SP 加载了 0x5F200004,除非我从标签中减去 1。 0x5F 是 BusFault_Handler 中的第一个字节。
任何人都可以解释为什么我需要减去 1。我配置错了吗?我检查过数据是字(4 字节)对齐的。
当计算在拇指模式下定义的标签的地址时,汇编程序将自动设置最低有效位,因为它假定代码标签是分支目标,没有别的。因此,当 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 MainWhosebug_Handler
DATA
StackBegin: DC32 SFB(CSTACK) ; Start of main stack
StackEnd: DC32 SFE(CSTACK) ; End of main stack
THUMB