为什么Microchip XC8编写.as文件那么复杂?



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

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

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

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

;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

不熟悉XC8编译器或PIC架构,我不能确切地说为什么编译器会发出(134)^080,但它应该使阅读汇编更容易,因为它显示了预期的地址。如果它只是把6放在那里,你必须回到程序集,寻找status最后被修改的地方,以找出实际的地址是什么。

至于你的其他问题,那些比较容易回答。对位位置进行常量分割和屏蔽的原因是,可以使用相同的指令模板来设置大于单个字节的变量中的位。考虑一下,如果您正在编写一个C函数,该函数打印一个在内存位置中设置位的汇编指令。你可以这样写:
void emit_set_bit_insn(char const *addr, int bit) {
     printf("bsf %s+(%d/8),(%d)&7n", addr, bit, bit);
}

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

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

,汇编程序将其计算为:

bsf var16+1,2

设置var16第二个字节的第2位,这与设置16位变量var16的第10位是一样的。(好吧…假设字节顺序为小端序,这显然是XC8编译器遵循的约定。)

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

作为kirill建议line指令不是一个汇编指令。它用于通知汇编程序C源代码中的哪一行与下面的指令相关联。汇编程序将使用这些信息来生成调试信息,调试器可以使用这些信息来显示程序中给定地址的相关源代码。

编译器根据特定的正则表达式生成汇编代码,然后将正确的值插入其中。具体的单词line不是一个实际的汇编命令。

相关内容

  • 没有找到相关文章

最新更新