📄 floatpoint.asm
字号:
;AVR浮点程序库
;清单62
.ORG $A00 ;THIS FRT.PLB.USE r5--r17&r0&sram $70--$7f和flagT
EXCH: MOV R5,R8 ;两浮点数交换子程序
MOV R8,R12
MOV R12,R5
EXCH1: MOV R5,R9 ;尾数交换
MOV R9,R13
MOV R13,R5
MOV R5,R10 ;双字节交换
MOV R10,R14
MOV R14,R5
MOV R5,R11
MOV R11,R15
MOV R15,R5
RET
DP: ANDI R16,$7F ;处理积/商数符,计算积/商阶码子程序
SBRC R9,7
SUBI R16,$80
SBRC R13,7
SUBI R16,$80 ;积/商符号放在r16,7
ADD R12,R8 ;移码相加(除数阶码已求补)
LDI R17,$80
BRCC DP1
ADD R12,R17 ;移码求和有进位,将和再加上$80,再有进位为溢出
RET
DP1: SUB R12,R17 ;移码求和无进位,将和减去$80,有借位
RET ;或差为0也为溢出
NEG3: COM R15 ;3字节数据求补
COM R14 ;先求反后加1
COM R13
INC3: LDI R17,255
SUB R15,R17 ;以减去-1代替加1
SBC R14,R17
SBC R13,R17
RET
;清单63 ;浮点数比较大小子程序 X1为被减数 X2为减数
FPCP: SBRC R9,7 ;X1为正,跳行
RJMP CP1
SBRC R13,7 ;X2为正,跳行
RJMP CP2 ;X1,X2异号
FPCP1: CP R11,R15 ;X1,X2皆为正,以尾数低位字节,中位字节,高位字节和
CPC R10,R14 ;阶码的顺序(按无符号数)进行比较
CPC R9,R13 ;不等,阶码大者浮点数值也大;只有阶码和尾数对应相等,
CPC R8,R12 ;两浮点数才相等
RET ;比较结果:Z=1时X1=X2,否则C=0时X1>X2,C=1时X1<X2
CP1: SBRC R13,7
RJMP CP3 ;两负数比较,转
CP2: CP R13,R9 ;正数与负数比较,只比较尾数高位字节即可
RET
CP3: CP R15,R11 ;X1,X2皆为负,以尾数低位字节,中位字节,高位字节和
CPC R14,R10 ;阶码的顺序(按无符号数)进行比较
CPC R13,R9 ;但要将X1、X2交换位置后按正数比较过程进行
CPC R12,R8
CP4: RET ;比较结果:Z=1时X1=X2,否则C=0时X1>X2,C=1时X1<X2
;清单64
FPSU: LDI R17,$80 ;浮点减法子程序
SUB R13,R17 ;减数数符求反后作为加数
FPAD: TST R8 ;浮点加法子程序
BREQ DON1 ;被加数为0,加数为和
TST R12
BRNE FPLAD ;加数为0,取被加数为和
SAV0: MOV R12,R8 ;传送被加数取代加数
MOV R13,R9
MOV R14,R10
MOV R15,R11
DON1: RET
FPLAD: ANDI R16,$3f ;清除被加数,加数数符
SBRC R9,7
ORI R16,$80 ;被加数数符取到(R16,7)
SBRC R13,7
ORI R16,$40 ;加数数符取到(R16,6)
LDI R17,$80
OR R9,R17
OR R13,R17 ;恢复尾数最高位
MOV R17,R12
SUB R17,R8 ;计算阶差
BREQ GOON ;两阶相等,转
BRCC NX3
NEG R17 ;不够减求补
CPI R17,24
BRCC EXAD ;|阶差|>24,取被加数为和
NX2A: LSR R13
ROR R14
ROR R15
DEC R17
BRNE NX2A ;加数阶小,右移加数对阶
MOV R12,R8 ;取被加数阶为和之阶
BRCC GOON
RCALL INC3 ;舍入移出位
RJMP GOON
NX3: CPI R17,24
BRCC COM1 ;阶差>24,取加数为和
LOOP: LSR R9
ROR R10
ROR R11
DEC R17
BRNE LOOP ;加数阶大,右移被加数对阶
BRCC GOON
RCALL INC3A ;舍入移出位
GOON: SBRC R16,6
SUBI R16,$80
SBRS R16,7 ;判别两数是否同号
RJMP SAMS ;同号转
SUB R15,R11 ;异号,执行减法,加数为被减数
SBC R14,R10
SBC R13,R9
BRCC NOM ;够减转
SUBI R16,$40 ;否则被减数数符求反为和之数符
RCALL NEG3 ;并将差求补
NOM: MOV R17,R13
OR R17,R14
OR R17,R15
BREQ DON0 ;差为0转
NMLOP: SBRC R13,7
RJMP COM1
LSL R15
ROL R14
ROL R13
DEC R12
BRNE NMLOP ;规格化
OV1: SEV ;阶码变为0,下溢(可取为0,不算溢出)
RET
SAMS: ADD R15,R11
ADC R14,R10
ADC R13,R9 ;两数同号,执行加法
BRCC COM1
ROR R13
ROR R14
ROR R15
INC R12 ;有进位时右规1次
BREQ OV1 ;阶码增1后变为0为上溢
BRNC COM1
RCALL INC3
COM1: SBRC R16,6
RET
COMA: LDI R17,$7f
AND R13,R17 ;正数数符为0
DON: RET
EXAD: RCALL SAV0 ;取被加数为和
SBRS R16,7
RJMP COMA ;配置数符
RET
DON0: CLR R12 ;浮点数为0
RET
;清单65 ;浮点乘法子程序
FPMU: TST R8
BREQ M0 ;被乘数为0,积为0
TST R12
BRNE M1 ;乘数为0,积也为0
M0: RJMP G0
M1: RCALL DP ;处理积符号,计算积之阶码
BRCS OV2
BREQ OV2 ;判断溢出
LDI R17,$80
OR R9,R17
OR R13,R17 ;恢复尾数最高位
MOV R5,R13
MOV R6,R14
MOV R7,R15 ;乘数转入R5,R6,R7
LDI R17,25 ;设右移部分积次数
CLR R13
CLR R14
CLR R15 ;r13r14r15清除,存放积
CLC
LOOP1: BRCC M2
ADD R15,R11
ADC R14,R10
ADC R13,R9 ;乘数右移移出位为1,被乘数加入部分积1次
M2: ROR R13
ROR R14
ROR R15
ROR R5
ROR R6
ROR R7 ;部分积连同乘数右移1位
DEC R17
BRNE LOOP1 ;尾数相乘计算完成?
SBRC R13,7 ;
RJMP M3 ;乘积最高位为1 转
ROL R5
ROL R15
ROL R14
ROL R13 ;乘积最高位为0,高4位字节左移1位
SBRS R5,7
RJMP M5
RCALL INC3 ;末位字节舍入
BRNE M5
SEC ;舍入后R13变为0
ROR R13 ;将其改为$80(即0.5)
RJMP COM2
M5: DEC R12 ;舍入后R13不为0
BRNE COM2 ;阶码减1
OV2: SEV ;变为0为溢出
RET
M3: SBRC R5,7
RCALL INC3 ;乘积低3位字节舍入
COM2: LDI R17,$7f
SBRS R16,7
AND R13,R17 ;正数将符号位请除
DON2: RET
;清单66
FPDI: TST R12 ;浮点除法子程序
BREQ OV3 ;除数为0,溢出
TST R8
BRNE D1
RJMP G0 ;被除数为0,商为0
D1: NEG R12 ;除数阶码求补,以加补码代替减原码
RCALL DP ;处理商符号,计算商之阶码
BRCS OV3
BREQ OV3 ;判断溢出
LDI R17,$80
OR R9,R17
OR R13,R17 ;恢复尾数最高位
FPD3: LDI R17,25 ;左移相减试商25次,最后1次舍入
SUB R11,R15
SBC R10,R14
SBC R9,R13
BRCS D2 ;第一次尾数相减试商
INC R12 ;够减,商阶增1
SEC
BRNE D3 ;商阶增1后不为0,转计商;否则为溢出
OV3: SEV
RET
D2: ADD R11,R15
ADC R10,R14
ADC R9,R13 ;不够减则恢复被除数
LOOP2: LSL R11
ROL R10
ROL R9 ;被除数算术左移
BRCS D4 ;进位位为1,够减,本位商1
SUB R11,R15
SBC R10,R14
SBC R9,R13 ;否则相减试商
BRCS D2A
SEC
RJMP D3 ;够减,本位商1
D2A: ADD R11,R15 ;不够减,恢复被除数
ADC R10,R14
ADC R9,R13
CLC ;本位商0
RJMP D3
D4: SUB R11,R15
SBC R10,R14
SBC R9,R13 ;被除数减去除数
D3: DEC R17
BRNE D5 ;除法未完成,循环
MOV R13,R5
MOV R14,R6
MOV R15,R7 ;取回商
BRCC COM3
RCALL INC3 ;第25位商舍入
COM3: LDI R17,$7f
SBRS R16,7
AND R13,R17 ;配置商数符
DON3: RET
D5: ROL R7 ;在R5,R6,R7中记商(不必预先清除)
ROL R6
ROL R5 ;商数左移1位并记商
RJMP LOOP2
;清单67
FPSQ: ANDI R16,$7F ;模拟手算开平方子程序
SBRC R13,7
ORI R16,$80 ;负数 建虚根标志
FPS0: TST R12
BREQ DON4 ;0的平方根为0
LDI R17,$80
OR R13,R17 ;恢复尾数最高位
LSR R12 ;阶码算术右移1位
BRCC FSQ2
INC R12 ;移出位舍入
RCALL INC3 ;先将位数增1(提前舍入)
BRCS FSQ1 ;C=1,不够减
SEC
ROR R13 ;若尾数变为0将其改为0.5($80-->r13)
RJMP FSQ2
FSQ1: LSR R13
ROR R14
ROR R15 ;否则将为数算术右移
FSQ2: LDI R17,25 ;开出25位根,末位舍入
MOV R8,R17
LDI R17,$40
ADD R12,R17 ;根恢复为移码
CLR R5
CLR R6
CLR R7 ;根扩展区清除
CLR R9
CLR R10
CLR R11 ;根存储区清除
FSQ3: SUB R13,R17
SBC R7,R11
SBC R6,R10
SBC R5,R9 ;试根
BRCS FSQ3A
SEC
RJMP FSQ4 ;够减,本位根1
FSQ3A: ADD R13,R17
ADC R7,R11
ADC R6,R10
ADC R5,R9 ;否则恢复开平方数之尾数
CLC ;本位商0
FSQ4: DEC R8
BRNE FSQ5 ;开出第25位根?
FPDON: MOV R13,R9
MOV R14,R10
MOV R15,R11 ;回送根尾数
BRCC COM4
RCALL INC3 ;第25位根舍入
COM4: LDI R17,$7F
AND R13,R17 ;根尾数为正数
DON4: RET
FSQ5: ROL R11
ROL R10
ROL R9 ;根尾数带进位左移,记根
LSL R15
ROL R14
ROL R13
ROL R7
ROL R6
ROL R5
LSL R15
ROL R14
ROL R13
ROL R7
ROL R6
ROL R5 ;开平方数之尾数连同扩展区左移2位
BRCC FSQ3 ;未产生进位,循环
RJMP FPDON ;否则进位为第25位根(不须试,并结束子程序)!
;清单68 ;牛顿迭代开平方子程序
FSQR: TST R12
BREQ SQRT ;0的平方根为0
ANDI R16,$7E
SBRC R13,7
ORI R16,$80 ;虚根标志
SBRC R12,0
INC R16 ;阶码为奇数
LDI R17,$7F
AND R13,R17 ;尾数变为正数
LSR R12
LDI R17,$40
ADC R12,R17 ;得到根之移码
PUSH R12 ;暂存
LDI R17,$80
MOV R12,R17
SBRC R16,0
INC R12 ;得到X1的阶码(0.5≤X1<2)
RCALL LD1 ;存 X1
LSR R13
ROR R14
ROR R15
LDI R17,$40
SBRS R16,0 ;阶码为奇数时算术右移尾数即得到X1之尾数;否则将其最
;高位字节加上$40
OR R13,R17 ;得到首次根r0=(1+x1)/2
LDI R17,3
MOV R0,R17 ;迭代3次
FSQLP: RCALL LD2
RCALL GET1
RCALL FPDI
RCALL GET2
RCALL FPAD
DEC R12 ;计算r(i+1)=(x1/ri+ri)/2
DEC R0
BRNE FSQLP
POP R12 ;根之阶码
SQRT: RET ;r16,7=1 为虚数根
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -