原创 非常好的 SN 单片机的比较指令 cmprs (汇编语言)

2013-10-18 15:42 2886 11 11 分类: 消费电子

 

非常好的 SN 单片机的比较指令 cmprs (汇编语言)
SN 汇编指令里有一条比较指令, CMPRS ,它总是拿 A 去与立即数或某个 RAM 做比较.--------必须是 A 在前面!
指令形式为:
CMPRS      A,I  ;ZF,C←A-I, 如果 A=I, 则跳过下一指令 (1+S)【C * Z】
CMPRS     A,M   ;ZF,C←A-M, 如果 A=M, 则跳过下一指令 (1+S)【C * Z】
执行完这个指令,会有 3 种结果:
1. A=M    ( 或 I ----下面相同,不再注明).
2.A>M
3.A<M
这 3 种结果中, A=M 会跳过下一指令,(PC+2),自然就知道 A=M 了!
如果 A 不等于 M 时,可以根据 FC 来判断大小:
A>M   则  C=1 .;不相等就看 FC
A<M   则  C=0 .;不相等就看 FC
A=M    则  Z=1  ;相等就看 FZ
无论 > 或 < 或 = ,作为比较定性是非常方便的.
示例:
CMPRS A,M
JMP   @F   ;不相等
;相等,这里往下执行
;..........................
RET
@@:  ;// 不相等到这里
BTS1 FC ;看看谁大
JMP @F
;A > M 到这里
;..........................
RET
@@:    ;// A < M 到这里
;..........................
RET
一条指令的效率,就可以知道三种可能结果的结果!----确实很好用!
同样地,可以应用到多字节比较:
示例:
EH,EL 与 M_H,M_L 比较
MOV A,EH     ;必须通过 A
CMPRS A,M_H   ;先与高字节比较
JMP @F
;高字节相等则继续比较低字节
MOV A,EL     ;必须通过 A
CMPRS A,M_L   ;先与高字节比较
JMP @F
;双字节相等到这里
;..................................
RET
@@:   ;不相等到这里
BTS1 FC ;看看谁大?
JMP @F ;EH,EL < M_H,M_L 跳走
; ;EH,EL > M_H,M_L 到这里
;..................................
RET
@@:
;..................................
RET
;************************************************************
  这个比较指令 cmprs 恐怕会被许多人误以为仅仅是比较 2 个寄存器内数值大小的指令,实则不是的!
单片机程序里,经常需要知道 2 个数的大小,有时候,还不希望影响被比较的 2 个原始寄存器的内容,比较之前与比较之后,参与比较的寄存器丝毫没有影响!
又由于日常 8位 单片机的数据里,一个字节的 8 位=255  实在不够用,这样,基本上大多数时候处理的就是双字节=16 位数值. 最大=65535! 这个数基本上涵盖了日常仪器仪表,物理量,化学量等等领域的大部分要求!------下面就以双字节的基本数据再说一下 CMPRS 指令的应用问题!
一句话: CMPRS  指令不仅仅可以比较出 2 组数是否相等,而且可以比较出 2 组数据的大小!
例如: 比较 M0H_M0L 与 M1H_M1L 是否相等?谁大:? 谁小? .而且不能破坏它们本身的数值.
     我们最容易想到的就是使用减法:
     如:
     MOV A,M0L
     SUB A,M1L
     MOV R,A ;注意这个指令,不影响任何标志! ------下面解释为什么添加这个指令.
     MOV A,M0H
     SBC A,M1H
     此时,只要看看 FC 就知道谁大谁小了!-----而是否相等呢?  看不出来! 因为 FC 仅仅可以知道 ≥ 和 < ,不能知道是否 = .
    这就是为什么上面添加一条 " MOV R,A " 的用途了 !
    在 SBC A,M1H   之后,如果 A=0 则 FZ=1 ,再 R = 0 的话,来一次 MOV   A,R 就知道 FZ 了. 这两步 FZ 如果都是=1,说明结果是 0 ,则是相等了! ------ 这样处理,是不是有点罗嗦和麻烦 ?
   再看看使用 CMPRS 指令会如何?
MOV A,M0H ;与使用减法不同,使用 CMPRS 要从高字节开始.有可能省去比较下一次的比较!--- 如果 M0H≠M1H  一步就知道大小!
COMPRS A,M1H
JMP Z_FC   ;  M0H≠M1H   跳走,一步就知道大小!
MOV   A,M0L
COMPRS A,M1L
JMP Z_FC   ;  M0L≠M1L   跳走,二步知道大小!
JMP Z_FZ   ;上面完全相等,跳走到这里! M0=M1 !
Z_FC :
BTS1 FC
JMP Z_M0X ;FC=0 , M0<M1
JMP Z_M0D ;FC=1 ,M0DD>M1
这一段干净利落!三种结果非常分明!丝毫没有影响 M0,M1 2 组数据的内容!
说白了,就是 CMPRS 会根据比较结果影响标志 FZ 和 FC ,而且 FZ 是隐含的自动判断!相等跳过是也!
原理解释: CMPRS 能够比较出 > ,= ,< 来! 
例如:
设: M0=M1 ,此时使用 CMPRS 后, FZ=1 ,C=1.
设: M0>M1 ,此时使用 CMPRS 后, FZ=0, C=1,
设: M0<M1 ,此时使用 CMPRS 后, FZ=0, C=0,
看看 FZ 与 C ,三种结果是非常分明的! ----- 不妨自己去体验试一下.
恰好, 51 也有这条指令,效果相似,非常好用!它不仅仅不会影响原来的寄存器内容!而且可以节省许多指令.
仅供参考!
附:有朋友问:还有两个命令 cja 和 cjb。这在 SONIX 指令集中没有啊,但是我在很多程序中都看到有用不知道是什么意思,还有有的资料上说松翰没有PUSH和POP这两个命令,但是我看到也有很多资料上还有书上用PUSH和POP。这是怎么一回事?
回答: cja 和 cjb,这在 SONIX 指令集中是没有,但是,在编译器的安装目录里有,查阅一下 SN 编译器里的系统默认宏指令 *****.h 文件,里面就有解释.

文章评论0条评论)

登录后参与讨论
我要评论
0
11
关闭 站长推荐上一条 /2 下一条