【问题标题】:Why Gcc compiles code in a wrong way? [closed]为什么 Gcc 以错误的方式编译代码? [关闭]
【发布时间】:2023-03-14 04:05:01
【问题描述】:

我试图找出为什么我的 AVR ATtiny861A(8 位)程序无法正常工作。现在我才刚刚开始使用 Atmel Studio(之前我使用的是 CodeVision AVR)。

cmets中带有初始C代码的汇编代码如下:

        if(data & 0x8000)
  84:   33 23           and r19, r19
  86:   14 f4           brge    .+4         ; 0x8c <WriteDAC+0x2e>

我无法理解这段代码是如何正常工作的。

Codevision 编译正确:

; 0000 00EE     (data&0x8000) ? (DAC_DIN=1) : (DAC_DIN=0);
    SBRS R17,7
    RJMP _0x10

我只发布了我无法理解的代码部分。

【问题讨论】:

  • 仅仅因为不明白发生了什么,并不一定意味着编译器错了......
  • 我认为问题是:它有效吗?如果确实如此,那么问题出在您身上,而不是编译器。
  • 要理解反汇编,你必须查看这段代码所在的整个函数,而不仅仅是一行。另外,发布使用的编译器选项。另外,这是 8 位 AVR 还是 32 位?
  • 如果不显示DAC_DIN的定义,谁也说不准。这可能是某种硬件寄存器?可能是您正在编译优化的情况,因此不要使用volatile
  • 顺便说一句,您确定您的反汇编程序将 C 行放在 asm 上方而不是下方吗?这两个版本我都看过。

标签: c gcc compilation avr


【解决方案1】:

AND 指令根据结果设置条件码,与输入的值相同。由于您正在测试最高位,因此结果是否定的,因此条件分支可以简单地使用“大于或等于”条件测试此标志并将其用于条件分支,对应于if 语句。

要求codevision编译器根据最高位生成一个0或1的变量(所以你有不同的源代码:一个是if语句,另一个是三元表达式),是通过将位向下移动并用零填充寄存器来完成的,这是通过使用不同类型的条件跳转来完成的。

两者都完全正确。

【讨论】:

    【解决方案2】:

    BRGE 指令执行Branch if Greater or Equal Signed

    由于使用0x8000 执行and 操作等于测试16 位操作数中的符号位,因此它将设置符号位并执行分支。


    SBRS 执行 Skip if Bit in Register is Set

    使用0x8000 执行and 操作等于测试16 位操作数的高字节中的第七位。


    可以管理这些指令以执行相同的结果,因此我假设每个编译器都按照自己的方式进行操作,根据您发布的代码。

    如果他们的行为不同,请发布更多内容,让我们慎重考虑。

    参考资料:

    http://www.atmel.no/webdoc/avrassembler/avrassembler.wb_BRGE.html

    http://www.atmel.no/webdoc/avrassembler/avrassembler.wb_SBRS.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多