简体   繁体   English

如何在 MASM 32 中计算数字的对数

[英]How to calculate the logarithm of a number in MASM 32

How do I calculate the logarithm of a number in MASM 32?如何计算 MASM 32 中数字的对数?
For example if I have to calculate log(2.5), how will I do this?例如,如果我必须计算 log(2.5),我该怎么做?
I know this will involve fyl2x and I have tried but I couldn't calculate it accurately.我知道这将涉及fyl2x ,我已经尝试过,但无法准确计算。

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:在使用FYL2X指令之前,请阅读手册中的说明:

This instruction calculates (ST(1)*log 2 (ST(0))), stores the result in register ST(1), and pops the FPU register stack.该指令计算 (ST(1)*log 2 (ST(0))),将结果存储在寄存器 ST(1) 中,并弹出 FPU 寄存器堆栈。 The source operand in ST(0) must be a non-zero positive number. ST(0) 中的源操作数必须是非零正数。

The FYL2X instruction is designed with a built-in multiplication to optimize the calculation of logarithms with an arbitrary positive base ( b ). FYL2X指令设计有内置乘法,以优化具有任意正基数 ( b ) 的对数计算。
log b x = (log 2 b) -1 * log 2 x 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 .我们可以很容易地删除它,因为 (log 2 b) -1 = log b 2 然后我们用 10 代替b We therefore need as multiplier log 10 2 which the FPU provides through its FLDLG2 instruction.因此,我们需要 FPU 通过其FLDLG2指令提供的乘数 log 10 2。

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.要计算自然对数(又名“ln”),唯一的变化是使用FLDLN2 (而不是FLDLG2 )来获得乘数 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.要计算二进制对数,唯一的变化是使用FLD1 (而不是FLDLG2 )来获得微不足道的乘数 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)将浮点数乘以 1000(对于 3 位精度)
  • store the product to memory as integer将产品存储到 memory为 integer
  • convert (*) the integer into text (repeated divisions by 10)将 (*) integer 转换为文本(重复除以 10)
  • put a decimal point character between the last 3 digits and all the digits in front of them在最后 3 位数字和前面的所有数字之间放置一个小数点字符
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. (*) 使用 DOS 显示数字解释了如何将 integer 转换为文本。 Look through the 'with DOS' mention and focus on the how and the why of the conversion itself.查看“使用 DOS”的提及,并关注转换本身的方式和原因。

The log conversion formula is log_b(x) = log_d(x)/log_d(b) or alternatively对数转换公式为 log_b(x) = log_d(x)/log_d(b) 或

log_b(x)*log_d(b) = log_d(x) 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)).在你的情况下,我假设 b = 2 和 d = 10。所以你想将 log_10(2) 而不是 log_2(10) 推送到堆栈上,因为 fyl2x 计算 SP(1) * log_2(SP(0))。

The command is FLDLG2 instead of FLDL2T.该命令是 FLDLG2 而不是 FLDL2T。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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