STM32f105 BLT指令重定位局部变量
STM32f105 BLT instruction relocates a local variable
在 Windows 7 上使用 Keil uVison 4 我有一个用于 stm32f105 的 c 项目,它表现出非常奇怪的行为。我用调试器对其进行了检查,经过几个小时的错误追踪后,我将错误定位为来自其他项目中已经测试过的函数。看起来像这样:
uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
{
CAN_FilterInitTypeDef filt;
/* Empty filter available? */
if(this->filter_len >= 14)
{
return FALSE;
}
/* Select filter number */
if(this->canx == CAN1)
filt.CAN_FilterNumber = this->filter_len + 0;
else
filt.CAN_FilterNumber = this->filter_len + 14;
this->filter_len++;
...
//filt is read
CAN_FilterInit(&filt);
}
这样结构过滤器在任何分配后都不会改变!然后我改了下反汇编,就是下面的(有点长不好意思):
108: uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
0x08001B22 BD70 POP {r4-r6,pc}
109: {
110: CAN_FilterInitTypeDef filt;
111:
112: /* Empty filter available? */
0x08001B24 E92D41FF PUSH {r0-r8,lr}
0x08001B28 4604 MOV r4,r0
0x08001B2A 460D MOV r5,r1
0x08001B2C 4690 MOV r8,r2
0x08001B2E 461E MOV r6,r3
0x08001B30 9F0A LDR r7,[sp,#0x28]
113: if(this->filter_len >= 14)
114: {
0x08001B32 7C20 LDRB r0,[r4,#0x10]
0x08001B34 280E CMP r0,#0x0E
0x08001B36 DB03 BLT 0x08001B40
115: return FALSE;
0x08001B38 2000 MOVS r0,#0x00
151: }
152:
153: /******************************************************************************/
154: void can_clr_filter(can_t* this)
0x08001B3A B004 ADD sp,sp,#0x10
0x08001B3C E8BD81F0 POP {r4-r8,pc}
119: if(this->canx == CAN1)
0x08001B40 4970 LDR r1,[pc,#448] ; @0x08001D04
0x08001B42 6820 LDR r0,[r4,#0x00]
0x08001B44 4288 CMP r0,r1
0x08001B46 D103 BNE 0x08001B50
120: filt.CAN_FilterNumber = this->filter_len + 0;
121: else
0x08001B48 7C20 LDRB r0,[r4,#0x10]
0x08001B4A F88D000A STRB r0,[sp,#0x0A]
0x08001B4E E004 B 0x08001B5A
122: filt.CAN_FilterNumber = this->filter_len + 14;
0x08001B50 7C20 LDRB r0,[r4,#0x10]
0x08001B52 300E ADDS r0,r0,#0x0E
0x08001B54 B2C0 UXTB r0,r0
0x08001B56 F88D000A STRB r0,[sp,#0x0A]
123: this->filter_len++;
124:
125: /* Select mask mode */
0x08001B5A 7C20 LDRB r0,[r4,#0x10]
0x08001B5C 1C40 ADDS r0,r0,#1
0x08001B5E 7420 STRB r0,[r4,#0x10]
我不是汇编专家,也不是 ARM 专家,但我一直在编写一些关于汇编的程序,对我来说它看起来不错。我注意到有点奇怪的是,在两者之间是另一个函数 can_clr_filter 的一部分,因此看起来编译器正在重用一些代码,尽管所有优化都已关闭。有趣的是,当我检查 filt.CAN_FilterNumber
变量的地址时,它在
行之后发生了变化
0x08001B36 DB03 BLT 0x08001B40
从地址 0x20002262 到地址 0x20002252。所以所有的更改都应用在内存中的其他地方!!在我将变量声明为静态变量后问题就消失了,尽管对我来说实际发生了什么是一个谜......局部变量怎么会被指令 BLT 重定位到另一个地址?或者 uVision 调试器可以通过观察 &filt.CAN_FilterNumber?
来显示错误的参考值
因为你没有post这个片段的整个功能我只能猜测:
- 只有对局部变量的赋值,但它没有在您的程序中的任何地方使用,它可能已从生成的代码中删除。
- 不要在编译器中查找错误。它们非常好,但我还没有找到(我是一个非常活跃的编码员)。总是当有人说:"this is disassembly listing, the compiler is wrong" 时,错误是由提问者在某处造成的。调试程序时忘记反汇编。你只是在浪费你的时间。
问题出在 uVision 中:http://www.keil.com/support/docs/2824.htm。
uVision 正在进行一些额外的优化,因此观察局部变量并不可靠。
在 Windows 7 上使用 Keil uVison 4 我有一个用于 stm32f105 的 c 项目,它表现出非常奇怪的行为。我用调试器对其进行了检查,经过几个小时的错误追踪后,我将错误定位为来自其他项目中已经测试过的函数。看起来像这样:
uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
{
CAN_FilterInitTypeDef filt;
/* Empty filter available? */
if(this->filter_len >= 14)
{
return FALSE;
}
/* Select filter number */
if(this->canx == CAN1)
filt.CAN_FilterNumber = this->filter_len + 0;
else
filt.CAN_FilterNumber = this->filter_len + 14;
this->filter_len++;
...
//filt is read
CAN_FilterInit(&filt);
}
这样结构过滤器在任何分配后都不会改变!然后我改了下反汇编,就是下面的(有点长不好意思):
108: uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
0x08001B22 BD70 POP {r4-r6,pc}
109: {
110: CAN_FilterInitTypeDef filt;
111:
112: /* Empty filter available? */
0x08001B24 E92D41FF PUSH {r0-r8,lr}
0x08001B28 4604 MOV r4,r0
0x08001B2A 460D MOV r5,r1
0x08001B2C 4690 MOV r8,r2
0x08001B2E 461E MOV r6,r3
0x08001B30 9F0A LDR r7,[sp,#0x28]
113: if(this->filter_len >= 14)
114: {
0x08001B32 7C20 LDRB r0,[r4,#0x10]
0x08001B34 280E CMP r0,#0x0E
0x08001B36 DB03 BLT 0x08001B40
115: return FALSE;
0x08001B38 2000 MOVS r0,#0x00
151: }
152:
153: /******************************************************************************/
154: void can_clr_filter(can_t* this)
0x08001B3A B004 ADD sp,sp,#0x10
0x08001B3C E8BD81F0 POP {r4-r8,pc}
119: if(this->canx == CAN1)
0x08001B40 4970 LDR r1,[pc,#448] ; @0x08001D04
0x08001B42 6820 LDR r0,[r4,#0x00]
0x08001B44 4288 CMP r0,r1
0x08001B46 D103 BNE 0x08001B50
120: filt.CAN_FilterNumber = this->filter_len + 0;
121: else
0x08001B48 7C20 LDRB r0,[r4,#0x10]
0x08001B4A F88D000A STRB r0,[sp,#0x0A]
0x08001B4E E004 B 0x08001B5A
122: filt.CAN_FilterNumber = this->filter_len + 14;
0x08001B50 7C20 LDRB r0,[r4,#0x10]
0x08001B52 300E ADDS r0,r0,#0x0E
0x08001B54 B2C0 UXTB r0,r0
0x08001B56 F88D000A STRB r0,[sp,#0x0A]
123: this->filter_len++;
124:
125: /* Select mask mode */
0x08001B5A 7C20 LDRB r0,[r4,#0x10]
0x08001B5C 1C40 ADDS r0,r0,#1
0x08001B5E 7420 STRB r0,[r4,#0x10]
我不是汇编专家,也不是 ARM 专家,但我一直在编写一些关于汇编的程序,对我来说它看起来不错。我注意到有点奇怪的是,在两者之间是另一个函数 can_clr_filter 的一部分,因此看起来编译器正在重用一些代码,尽管所有优化都已关闭。有趣的是,当我检查 filt.CAN_FilterNumber
变量的地址时,它在
0x08001B36 DB03 BLT 0x08001B40
从地址 0x20002262 到地址 0x20002252。所以所有的更改都应用在内存中的其他地方!!在我将变量声明为静态变量后问题就消失了,尽管对我来说实际发生了什么是一个谜......局部变量怎么会被指令 BLT 重定位到另一个地址?或者 uVision 调试器可以通过观察 &filt.CAN_FilterNumber?
来显示错误的参考值因为你没有post这个片段的整个功能我只能猜测:
- 只有对局部变量的赋值,但它没有在您的程序中的任何地方使用,它可能已从生成的代码中删除。
- 不要在编译器中查找错误。它们非常好,但我还没有找到(我是一个非常活跃的编码员)。总是当有人说:"this is disassembly listing, the compiler is wrong" 时,错误是由提问者在某处造成的。调试程序时忘记反汇编。你只是在浪费你的时间。
问题出在 uVision 中:http://www.keil.com/support/docs/2824.htm。
uVision 正在进行一些额外的优化,因此观察局部变量并不可靠。