0

在下面的代码中,我设置了 TRIS 寄存器的第一个位,然后是第二位,然后是第三位,最后是第四位。为什么生成的汇编代码……奇怪

很高兴知道:编译代码的微控制器的数据存储器分为几个存储区。位 6 和 7 进入status寄存器的位置 5 和 6,只有位 0-5 存储在操作码中。因此,当访问TRIS位置 0x86 的寄存器时,存储在操作码中的值是6.

具体问题:

  • (134)^080: 这转换为6,这是TRIS特定银行的地址。为什么编译器不只写(6)or (134)?只是为了明确TRIS不在bank 0上,还是有其他原因?
  • +(0/8):0代表位位置,8表示该寄存器中的总位数。在我看来,这个表达式没有任何用途,因为结果总是一个分数,而不是一个整数。因此它对地址计算没有贡献。
  • (0)&7:再次代表位位置,但我一直不清楚(0)二进制与服务的目的。7
  • 命令有什么作用line

代码(从生成的 *.as 文件中提取)

;main.c: 9: TRISB |= 1;
    bsf status, 5   ;RP0=1, select bank1
    bcf status, 6   ;RP1=0, select bank1
    bsf (134)^080h+(0/8),(0)&7  ;volatile
    line    10
;main.c: 10: TRISB |= 2;
    bsf (134)^080h+(1/8),(1)&7  ;volatile
    line    11
;main.c: 11: TRISB |= 4;
    bsf (134)^080h+(2/8),(2)&7  ;volatile
    line    12
;main.c: 12: TRISB |= 8;
    bsf (134)^080h+(3/8),(3)&7  ;volatile
    line    13
4

2 回答 2

0

由于特定的正则表达式,编译器会生成汇编代码,然后将正确的值插入其中。特定的词line不是一个准确的汇编命令。

于 2014-07-27T17:29:44.570 回答
0

不熟悉 XC8 编译器或 PIC 体系结构我不能确定编译器为什么会发出(134)^080,但它应该可以更容易地读取程序集,因为它显示了预期的地址。如果它只是放在6那里,您必须返回程序集并查找status上次修改的位置,以便找出实际地址是什么。

至于你的其他问题,这些更容易回答。对位位置进行恒定除法和屏蔽的原因是,可以使用相同的指令模板来设置大于单个字节的变量中的位。考虑一下您是否正在编写一个 C 函数,该函数打印一条在内存位置设置位的汇编指令。您可以编写它的一种方法是这样的:

void emit_set_bit_insn(char const *addr, int bit) {
     printf("bsf %s+(%d/8),(%d)&7\n", addr, bit, bit);
}

现在考虑emit_set_bit_insn("var16", 10)将输出什么:

bsf var16+(10/8),(10)&7

汇编器将评估为:

bsf var16+1,2

在 的第二个字节中设置第 2 位var16,这与设置 16 位变量的第 10 位相同var16。(嗯......假设小端字节顺序,这显然是 XC8 编译器遵循的约定。)

当然编译器可以自己完成所有的算术运算,但不这样做会使编译器的代码简单得多。无论哪种方式,汇编器都会生成相同的机器代码。

正如基里尔建议的那样,该line指令不是汇编指令。它用于通知汇编器将 C 源代码中的哪一行与以下指令相关联。汇编器将使用此信息生成调试信息,调试器可以使用这些信息来显示程序中给定地址的相关源代码。

于 2014-07-27T22:12:57.237 回答