定点数开方只能得到结果的整数部分,如代入FFFFH和FF10H的开方结果都是一样的,为FFH。如果想要得到比较精确的结果,可以先对被开方数乘以一个系数,待得到结果后,再除以相应的系数。如果被开方数太大,则不能使用此法,若想得到比较精确的结果,可以采用后面介绍的“浮点数开方”。
以下为定点数开方的程序清单(其中包含校验程序部分)。该程序中包含定点数加法程序和定点数除法程序。
LIST p=16f877
INCLUDE p16f877.inc
;****************************************
;此子程序是求16位二进制数平方根的子程序,需要调用16/16位除法子程序和
;加法子程序,虽然前面有了,但标号有些不同,为了易于阅读和理解,也把它列在后面。
;入口条件:16位二进制数存放在NUMHI和NUMLO单元中。
;出口条件:8位二进制数存放在SQRTLO单元中。
;迭代次数由LUPCNT的地址值决定。
;用指令CALL SQRT实现定点数开方程序调用
;****************************************
ACCALO EQU 0X20
ACCAHI EQU ACCALO+1
EXPA EQU ACCALO+2
ACCBLO EQU ACCALO+3
ACCBHI EQU ACCALO+4
EXPB EQU ACCALO+5
ACCCLO EQU ACCALO+6
ACCCHI EQU ACCALO+7
ACCDLO EQU ACCALO+8
ACCDHI EQU ACCALO+9
TEMP EQU ACCDHI+1
SIGN EQU ACCDHI+2
SQRTLO EQU ACCALO
SQRTHI EQU ACCAHI
NUMLO EQU ACCDHI+4
NUMHI EQU ACCDHI+5
COUNT EQU ACCDHI+6 ;此方法定义的数据块为连续层断,只要
;将第一行改变,就可以将数据整块搬动到
;新的地方,为调试带来方便,是比较推
;崇的一种寄存器定义方法
LUPCNT EQU .10
;****************************************
ORG 0X00
GOTO MAIN
ORG 0X10
;****************************************
INIT MOVLW LUPCNT
MOVWF COUNT
MOVF NUMHI,0
MOVWF SQRTHI
MOVF NUMLO,0
MOVWF SQRTLO
BCF STATUS,C
RRF SQRTHI,1
RRF SQRTLO,1
RETLW 0
;***************16×16位定点数右移子程序***************
DIV2 BCF STATUS,C
RRF ACCBHI,0
MOVWF SQRTHI
RRF ACCBLO,0
MOVWF SQRTLO
RETLW 0
;*********16×16位定点数开方子程序**********
SQRT CALL INIT
SLOOP MOVF NUMLO,0
MOVWF ACCBLO
MOVF NUMHI,0
MOVWF ACCBHI
CALL D_DIVS
CALL D_ADD
CALL DIV2
DECFSZ COUNT,1
GOTO SLOOP
RETURN
;***********16×16位定点整数除法子程序*********
D_DIVS CALL SETUP
CLRF ACCCHI
CLRF ACCCLO
DLOOP BCF STATUS,C
RLF ACCDLO
RLF ACCDHI
RLF ACCCLO
RLF ACCCHI
MOVF ACCAHI,0
SUBWF ACCCHI,0
BTFSS STATUS,Z
GOTO NOCHK
MOVF ACCALO,0
SUBWF ACCCLO,0
NOCHK BTFSS STATUS,C
GOTO NOGO
MOVF ACCALO,0
SUBWF ACCCLO,1
BTFSS STATUS,C
DECF ACCCHI,1
MOVF ACCAHI,0
SUBWF ACCCHI,1
BSF STATUS,C
NOGO RLF ACCBLO
RLF ACCBHI
DECFSZ TEMP
GOTO DLOOP
RETLW 0
;****************************************
SETUP MOVLW .16
MOVWF TEMP
MOVF ACCBHI,0
MOVWF ACCDHI
MOVF ACCBLO,0
MOVWF ACCDLO
CLRF ACCBHI
CLRF ACCBLO
RETLW 0
;**********16×16位定点数取补子程序**************
NEG_A COMF ACCALO,1
INCF ACCALO,1
BTFSC STATUS,Z
DECF ACCAHI,1
COMF ACCAHI,1
RETLW 0
;*************16×16位定点数加法子程序**************
D_ADD MOVF ACCALO,0
ADDWF ACCBLO,1
BTFSC STATUS,C
INCF ACCBHI,1
MOVF ACCAHI,0
ADDWF ACCBHI,1
RETLW 0
;****************************************
【校验举例】 被开方数2910H(十六进制)
10512(十进制)
求得平方根:66H(十六进制)
102(十进制)
MAIN NOP
MOVLW 0X29
MOVWF NUMHI
MOVL7W 0X10
MOVWF NUMLO ;被开方数赋值
CALL SQRT ;调用开方子程序
NOP ;开方完毕
END