简体   繁体   中英

How to calculate the logarithm of a number in MASM 32

How do I calculate the logarithm of a number in MASM 32?
For example if I have to calculate log(2.5), how will I do this?
I know this will involve fyl2x and I have tried but I couldn't calculate it accurately.

This is what I tried but it prints no result.

INCLUDE Irvine32.inc

; .data is used for declaring and defining variables
.data
num     real8 3.324          ; the data I want to convert
res     real8 ?              

   .code
   main PROC

    fldl2t               ; st: log2(10)
    fld num              ; st: log2(10) num
    fyl2x                ; st: log10(num)
    fstp res             ; store to out and pop


    call    CrLf
    call    CrLf

exit    
main ENDP
END main

I see that you have copied the code from an existing answer . Sadly, that answer contains errors!

Before using the FYL2X instruction, read the description in the manual:

This instruction calculates (ST(1)*log 2 (ST(0))), stores the result in register ST(1), and pops the FPU register stack. The source operand in ST(0) must be a non-zero positive number.

The FYL2X instruction is designed with a built-in multiplication to optimize the calculation of logarithms with an arbitrary positive base ( b ).
log b x = (log 2 b) -1 * log 2 x

The error stems from not noticing that the multiplier is a reciprocal. We can easily remove it because (log 2 b) -1 = log b 2 and then we substitute 10 for b . We therefore need as multiplier log 10 2 which the FPU provides through its FLDLG2 instruction.

num     REAL8 3.324
res     REAL8 ?

        ...

        FLDLG2           ; ST0 = log10(2)
        FLD     num      ; ST1 = log10(2), ST0 = num
        FYL2X            ; ST0 = log10(num)
        FSTP    res

To calculate the natural logarithm (aka 'ln'), the only change would be to use FLDLN2 (instead of FLDLG2 ) to obtain the multiplier log e 2.

To calculate the binary logarithm, the only change would be to use FLD1 (instead of FLDLG2 ) to obtain the trivial multiplier 1.


An algorithm that converts a floating point number into its textual representation is not all that simple, but maybe next fixed-point trick is all that you need:

  • multiply the floating point number by 1000 (for a 3-digit precision)
  • store the product to memory as integer
  • convert (*) the integer into text (repeated divisions by 10)
  • put a decimal point character between the last 3 digits and all the digits in front of them
num     REAL8 3.324
quad    dq ?
kilo    dw 1000

        ...

        FLDLG2           ; ST0 = log10(2)
        FLD     num      ; ST1 = log10(2), ST0 = num
        FYL2X            ; ST0 = log10(num)
        FIMUL   kilo     ; ST0 = 1000 * log10(num)
        FISTP   quad
        ...

(*) Displaying numbers with DOS explains how converting an integer to text works. Look through the 'with DOS' mention and focus on the how and the why of the conversion itself.

The log conversion formula is log_b(x) = log_d(x)/log_d(b) or alternatively

log_b(x)*log_d(b) = log_d(x)

In your case I assume b = 2 and d = 10. So you want to push log_10(2) instead of log_2(10) onto the stack, since fyl2x compute SP(1) * log_2(SP(0)).

The command is FLDLG2 instead of FLDL2T.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM