例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 |