Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C STM32f105 BLT指令重新定位局部变量_C_Assembly_Arm_Embedded_Stm32 - Fatal编程技术网

C STM32f105 BLT指令重新定位局部变量

C STM32f105 BLT指令重新定位局部变量,c,assembly,arm,embedded,stm32,C,Assembly,Arm,Embedded,Stm32,在Windows7上使用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_FilterIn

在Windows7上使用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);
}
这样,在任何分配之后,结构过滤器都不会改变!然后我更改了disassembly,如下所示(很抱歉,它有点长):

我不是汇编专家,也不是ARM专家,但我一直在汇编编程,对我来说它看起来不错。我注意到有点奇怪的是,中间是另一个函数can_clr_filter的一部分,所以看起来编译器在重用一些代码,尽管任何优化都被关闭了。有趣的是,当我检查
filt.CAN\u FilterNumber
变量的地址时,它在行之后发生了变化

0x08001B36 DB03      BLT      0x08001B40

从地址0x20002262到地址0x20002252。所以所有的更改都只应用于内存中的其他地方!!在我将变量声明为静态后,问题就消失了,尽管我对实际发生的情况还不清楚。。。指令BLT如何将局部变量重新定位到另一个地址?或者uVision调试器会通过查看&filt.CAN\u FilterNumber显示错误的引用值吗?

因为您没有从这个片段发布整个函数,我只能猜测:

  • 只有局部变量的赋值,但它不会在程序中的任何地方使用,并且可能会从生成的代码中删除
  • 不要在编译器中查找错误。他们是相当好的,我没有发现任何(我是一个非常活跃的编码)。当有人说:“这是反汇编清单,编译器错了”时,错误总是由询问者在某个地方犯的。在调试程序时,请忘记反汇编。你只是在浪费时间

  • 问题出在uVision:


    uVision正在进行一些额外的优化,因此监视局部变量是不可靠的。

    您是否检查了
    一开始是非
    NULL
    ,并指向有效地址?是否存在堆栈溢出的风险,即您在当前任务的堆栈中的位置以及是否有空闲空间
    BLT
    本身不应该使用堆栈,但如果您已经外出,则可能会发生奇怪的事情。@unwind,我这样做了。{this}不是'NULL',因为'this->canx'与全局变量CAN2具有相同的地址-这意味着'this'已经成功初始化。这个堆栈有1KB大。这当然可能是问题所在。如何找到它?@judoka_acl为了排除堆栈溢出,您可以在分配的堆栈内存底部放置一个金丝雀值,比如一些
    0xdeadf00d
    word,然后在一些主循环中不断检查金丝雀是否活动(即该内存仍然包含初始值)。一旦堆栈超出分配的空间,它也将覆盖金丝雀值(很难找到原点:/)。有些编译器为调试生成提供了类似/更好的技术,甚至在每次函数调用时都会检查堆栈的有效性,但即使对于生产生成,您的简单手动操作也可能足够快。@Ped7g编译过程中没有计算堆栈大小吗?当所需的堆栈大小大于分配的堆栈大小时,编译器不会输出错误或警告吗?@judoka_acl对此不确定,但我认为可以像图灵机器一样将任何代码转换为完全基于堆栈的,那么如果您能够在P(n)时间内计算出确切的堆栈使用率,你基本上可以解决停车问题。。。这被称为NP完全。我不知道有哪种编译器能够在编译过程中进行任何深度堆栈分析,通常程序员会设置堆栈大小(编译器选项或链接器脚本),或者像windows这样的操作系统会在应用程序用完最初保留的空间时动态增长堆栈大小。可以进行小尺寸检查。请确保已读取筛选器,我将更新我的问题。谢谢你的提示。我没有在编译器中寻找任何错误,奈特,我是说编译器错了。我试图定位错误,并询问有关奇怪行为的问题。@judoka_acl发布完整的函数调用。如果函数在某些情况下工作,并不意味着它将在另一种情况下工作。错误往往更复杂,无法揭穿。错误完全在我发布的代码中定位。如果你坚持,我可以亲自分享给你,但我有1000%的把握,问题不在函数的其余部分。我现在考虑的想法是调试器显示了错误的地址,问题根本不在代码中。
    0x08001B36 DB03      BLT      0x08001B40