Search code examples
assemblycompiler-constructionx86x87

Calculating exp(x) in x86 assembly


I am trying to make a compiler for my own simple programming language. It should output Intel-syntax x86 assembly. However, I am struggling to make it produce the correct code for the decimal numbers. Specifically, I am trying to implement the "exp" function to calculate "pow(e,x)", where 'e' is the base of the natural logarithm. Here is an example:

/*Preiously declared the variables 'result' and 'x' as global 32-bit floating-point numbers*/
result=exp(x)

Here is the code the compiler outputs for that example:

finit
fld dword [x]
fldl2e
fmulp st1,st0
fst dword [result]
fld1
fscale
fld1
fld dword [result]
fprem
fxch
f2xm1
fld1
faddp st1,st0
fmulp st1,st0
fstp dword [result]

To my best knowledge of x86 assembly, the code appears correct. However, it appears as though the "result" is, after that code, zero, no matter what 'x' is. Can you find the error in the code? Thanks!


Solution

  • try:

    finit
    fld dword [_x]
    fldl2e
    fmulp st1,st0       ;st0 = x*log2(e) = tmp1
    fld1
    fscale              ;st0 = 2^int(tmp1), st1=tmp1
    fxch
    fld1
    fxch                ;st0 = tmp1, st1=1, st2=2^int(tmp1)
    
    fprem               ;st0 = fract(tmp1) = tmp2
    f2xm1               ;st0 = 2^(tmp2) - 1 = tmp3
    faddp st1,st0       ;st0 = tmp3+1, st1 = 2^int(tmp1)
    fmulp st1,st0       ;st0 = 2^int(tmp1) + 2^fract(tmp1) = 2^(x*log2(e))
    fstp dword [_result]        
    ret
    

    My apologies for not explaining what I changed, but this was really difficult for me to figure out.