这一段时间,研究在Microchip的PIC单片机上用汇编语言编写的检测算法。估计脑细胞耗死了一大堆,发际线说不定也上移了不少,最让人折腾的是PIC单片机程序page和rambank的魔性处理,程序地址和内存地址还需要结合status的标志位分析,以及大量的调用call和跳转goto指令,看上几行就被绕得云里雾里,还有大量用位移操作实现的大数加、减、乘、除函数,还需要看着一大堆杂乱的汇编代码逐条语句猜测、分析、验证功能。
1、单片机系统指令的控制转移指令一、无条件转移指令AJMPaddrll(2字节指令)2K(地址211)字节范围内的无条件跳转指令。64K程序存储器空间分为32个区,每区2K字节,转移的目标地址必须与AJMP下一条指令的地址高5位地址码A15A11相同。指令执行时,先PC加2,然后把addrll送入PC.10~PC.0,PC.15~PC.11保持不变,程序转移到目标地址。
二、长跳转指令LJMPaddr16(3字节指令)64K字节范围内的无条件跳转指令。指令执行时,把指令的第二和第三字节分别装入PC的高位和低位字节中,无条件地转向addr16指出的目标地址。目标地址可以在64K程序存储器地址空间的任何位置。注意:短跳转、长跳转指令中addrll、addr16直接写上要转向的目标地址标号(即符号地址)就可以。
2、单片机中断返回指令程序结构错误。MOVTH0,#(6553650000)/256;定时50毫秒MOVTL0,#(6553650000)/256MOVIE,#82HSETBTR0--主程序,到这,就没有了,这那行?TIMER:;--下面就是:定时器中断服务程序MOVTH0,#(6553650000)/256;初脉冲50msMOVTL0,#(6553650000)/256INCR6;脉冲加1MOVA,
3、单片机跳转指令这是因为调用LCALL后压栈操作所致。堆栈寄存器SP的值在单片机启动后缺省为07H,也就是说07H+108H开始的内部RAM是堆栈区。在你调用LCALLQ11F1后,为了保证执行完Q11F1子程序后程序回到LCALLQ11F1的下一句,单片机会执行压栈操作:下一句指令Q11F1:MOVA,09H在程序中地址是010BH,所以:压栈前:SP07H第一次压栈:SP+108H:将0BH保存到08H第二次压栈:SP+109H:将01H保存到09H这就改变了09H的内容成了01H了。
所以再往下执行会有问题:调用LCALL后,通过RET返回,没有问题;但紧跟着又执行Q11F1,又执行了一个RET,此时07H和06H的内容决定了下一条指令从何处开始执行,这是不对的。子程序Q11F1必须经过CALL类调用指令来执行,否则会有问题,本例中LCALLQ11F1执行完后要么回到前面某句循环,要么原地等待。