I know it is easy in java to count log by Math.log but how that works since in assembly no ready function like that ?
-
1There is `FYL2X` actually, but that's x87. Could you specify more clearly what sort of thing you want? – harold Oct 06 '18 at 15:57
-
Are you programming in 32 bit mode or in 64 bit mode? Would you like to have an easy solution or a fast one? – fuz Oct 06 '18 at 16:02
-
64 , easy solution – mariano Oct 06 '18 at 16:05
-
See [Efficient implementation of log2(\_\_m256d) in AVX2](https://stackoverflow.com/q/45770089) for how to do it efficiently. An SSE2 version of that (for x86-64) should be easy. (Look at compiler output to get asm from the C intrinsics). See also [Logarithm in C++ and assembly](https://stackoverflow.com/q/45785705) for a simplistic / slow `fyl2x` version. – Peter Cordes Oct 06 '18 at 18:36
-
Possible duplicate of [Logarithm in C++ and assembly](https://stackoverflow.com/questions/45785705/logarithm-in-c-and-assembly) – fuz Oct 06 '18 at 19:10
1 Answers
To compute logarithms easily, use the x87 FPU's FYL2X
instruction. This instruction computes st1 * log2(st0)
and then pops the register stack. Since this is a dual logarithm, you need to push a suitable conversion factor first. Luckily, suitable conversion factors are built into the FPU's ROM accessible through special instructions:
num real8 1.234 ; the datum you want to convert
out real8 ? ; the memory location where you want to place the result
...
; dual logarithm (base 2)
fld1 ; st: 1
fld num ; st: 1 num
fyl2x ; st: log2(num)
fstp out ; store to out and pop
; decadic logarithm (base 10)
fldlg2 ; st: log10(2)
fld num ; st: log10(2) num
fyl2x ; st: log10(num)
fstp out ; store to out and pop
; natural logarithm (base e)
fldln2 ; st: ln(2)
fld num ; st: ln(2) num
fyl2x ; st: ln(num)
fstp out ; store to out and pop
Note that SSE or AVX do not have similar instructions; if you do not want to use the x87 FPU you have to manually compute the logarithm by means of a numerical approximation. This is usually faster than using fyl2x
directly though.
It is possible to use this code in a program that otherwise uses SSE to do floating point math; just move your data to the x87 FPU to compute the logarithm. Since there is no way to move from an SSE register to the x87 FPU directly, you have to go through the stack:
sub rsp, 8 ; allocate stack space
; SSE -> x87
movsd real8 ptr [rsp], xmm0
fld real8 ptr [rsp]
; x87 -> SSE with pop
fstp real8 ptr [rsp] ; store and pop
movsd xmm0, real8 ptr [rsp]
; x87 -> SSE without pop
fst real8 ptr [rsp] ; just store
movsd xmm0, real8 ptr [rsp]

- 90
- 9

- 88,405
- 25
- 200
- 352
-
This is nearly a duplicate of [Logarithm in C++ and assembly](https://stackoverflow.com/q/45785705), but you add the different log bases. – Peter Cordes Oct 06 '18 at 18:37
-
1
-
Note that "decadic logarithm" and "natural logarithm" are using wrong constants: it should be FLDLG2 and FLDLN2 respectively. – Serpent7776 Jan 23 '23 at 11:24
-
@Serpent7776 Please go ahead and edit the answer so it holds the correct constants. I am sorry for the mistake. – fuz Jan 23 '23 at 11:38