; math_exponents.asm ; ; Assembly language source for the 2**x, ; e**x, 10**x, and y**x functions: include math.inc include aoalib.inc ; TwoToX(x)- Computes 2**x. ; It does this by using the algebraic identity: ; ; 2**x = 2**int(x) * 2**frac(x). ; We can easily compute 2**int(x) with fscale and ; 2**frac(x) using f2xm1. ; ; This routine requires three free registers. .code math_twoTox proc SaveCW textequ <[rsp+0]> MaskedCW textequ <[rsp+2]> sub rsp, 8 ;Room for local vars fstcw SaveCW ; Modify the control word to truncate when rounding. fstcw MaskedCW or byte ptr MaskedCW[1], 1100b fldcw MaskedCW fld st(0) ;Duplicate tos. frndint ;Compute integer portion. fxch ;Swap whole and int values. fsub st(0), st(1) ;Compute frac part. f2xm1 ;Compute 2**frac(x)-1. fld1 faddp ;Compute 2**frac(x). fxch ;Get integer portion. fld1 ;Compute 1*2**int(x). fscale fstp st(1) ;Remove st(1) (which is 1). fmulp ;2**int(x) * 2**frac(x). fldcw SaveCW ;Restore rounding mode. add rsp, 8 ;Remove local vars ret math_twoTox endp ; exp(x)- Computes e**x. ; This routine requires three free registers. ; ; exp(x) = 2**(x * lg(e)) math_exp proc fldl2e ;Put lg(e) onto the stack. fmulp ;Compute x*lg(e). call math_twoTox ;Compute 2**(x * lg(e)) ret math_exp endp ; TenToX(x)- Computes 10**x. ; ; This routine requires three free registers. ; ; TenToX(x) = 2**(x * lg(10)) math_tenTox proc fldl2t ; Put lg(10) onto the stack fmulp ; Compute x*lg(10) call math_twoTox ;Compute 2**(x * lg(10)). ret math_tenTox endp ; YtoX(y,x)- Computes y**x (y=st(1), x=st(0)). ; This routine requires three free registers. ; ; Y must be greater than zero. ; ; YtoX(y,x) = 2 ** (x * lg(y)) math_yTox proc ; Note: y = st1, x=st0. fxch ;Compute lg(y). fld1 fxch fyl2x fmulp ;Compute x*lg(y). call math_twoTox ;Compute 2**(x*lg(y)). ret math_yTox endp end