例11.11 编写一个子程序,求解一元二次方程的根ax2 + bx + c = 0的根。

解:

;调用参数:方程的系数a、b和c,R1和R2是指向存放根的指针;

;返回参数:返回值存于AX中,其含义:0—有二个根,1—有一个根R1,2—无实根。

Quadratic

PROC USES DS DI SI, AA:DWORD, BB:DWORD, CC:DWORD, R1:PDWORD, R2:PDWORD

LES DI, R1 ;(ES:DI) → 1st Root-R1
LDS SI, R2 ;(DS:SI) → 2nd Root-R2
SUB BX, BX ;用BX来标识方程有根的情况
FLD1 ;栈顶寄存器置1
FADD ST, ST ;栈顶寄存器自加,变成2
FLD ST ;把数值2复制一份到新的栈顶
FMUL AA ;ST = 2A
FTST ;测试ST是否为0,即,考虑A=0的情况
FSTSW AX ;把当前状态寄存器存入AX中
FWAIT ;等待协处理器完成上面操作
SAHF ;AH装入到标志寄存器中
JNZ Notzero ;考虑A = 0的情况
FLD CC ;常数项C进栈
FCHS ;改变栈顶的符号,得到-C
FLD BB ;参数B进栈
FTST ;测试当前栈顶是否为0
FSTSW AX
SAHF
JZ EXIT2 ;考虑B = 0的情况
FDIV ;计算出-C/B
FSTP dword ptr ES:[DI] ;得到一个根,并弹出栈顶
FSTP ST ;弹出多余的堆栈数据
JMP EXIT1 ;返回,并标识有1个根
Notzero:
FMUL ST(1), ST ;ST(1) = 4A
FXCH ;ST和ST(1)交换
FMUL CC ;ST = 4AC
FTST
FSTSW AX
SAHF
JP EXIT2 ;如果状态位C2=1,则4AC是无穷大
FLD BB ;装入参数B
FMUL ST, ST ;ST = B2
FSUBR ;ST = B2 - 4AC
FTST
FSTSW AX
SAHF
JC EXIT2 ;如果C0=1,则B2 < 4AC
JNZ Tworoot ;如果C3=1,则B2 = 4AC
INC BX ;标志有1个根
Tworoot:
FSQRT ;求出B2 - 4AC的平方根
FLD BB
FCHS ;得到-B
FXCH ;ST 和ST(1)交换
FLD ST ;栈顶再复制一份
FADD ST, ST(2) ;ST = -B + SQRT(B2 - 4AC)
FXCH ;ST 和ST(1)交换
FSUBP ST(2), ST ;ST = -B - SQRT(B2 - 4AC)
FDIV ST, ST(2) ;得到一个根ST = ST/(2A)
FSTP dword ptr ES:[DI] ;存储第一个根
FDIVR ;得到另一个根ST = ST/(2A)
FSTP dword ptr DS:[SI] ;存储第二个根
JMP EXIT
EXIT2:
INC BX ;无根时的返回出口
FSTP ST ;清除多余的堆栈数据
EXIT1:
INC BX ;有一个根时的返回出口
FSTP ST ;清除多余的堆栈数据
EXIT:
MOV AX, BX
RET
Quadratic ENDP
END

关 闭