Author Topic: Calculating Logarithm  (Read 18762 times)

Offline Z12

  • Jr. Member
  • *
  • Posts: 2
Calculating Logarithm
« on: January 17, 2013, 03:25:36 PM »
Hello, My first post here  :D
I'm quite new to assembly and nasm.
I want to calculate log (x) Y
I did some research and found out that it's quite possible to calculate log (2) X and Log (2) Y then Get log (x) Y By calculating log (2) Y / log (2) X
X & Y are inputs from user. But i can't seem to produce a code that does that. A sample code is really appreciated.

Also, i wanted to produce some pseudo random numbers but what can i use as seed to produce more than 10,000 Random numbers?
I'm using Windows. Thank you
« Last Edit: January 17, 2013, 03:41:55 PM by Z12 »

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Calculating Logarithm
« Reply #1 on: January 17, 2013, 04:42:17 PM »
Hello and welcome to the forums.  Before we can provide help you need to show us where you're stuck.
When you reply click the # button located above the input field and paste your code in between the tags.  That will make it easier for us to help you.

Offline Z12

  • Jr. Member
  • *
  • Posts: 2
Re: Calculating Logarithm
« Reply #2 on: January 18, 2013, 02:46:40 PM »
Hello rob.
The problem is, I don't have any code to show. I don't know where to start with.
Based on what i have read on wikipedia First i need to find integer part of lb (x)
which is possible by shifting the number left until carry flag gets set. Then 32 - the number of times the number was shifted will be the integer part.
Code: [Select]
clc
xor ecx,ecx
loop: shl dword [x], 1
inc ecx
jnc loop
mov eax, 32
sub eax, ecx

Now i have the integer part of log (2) X in eax
but i don't know what to do to get the fractional value?
And then i would have to do the same to get log (2) Y to calculate log (x) Y as my goal.
Isn't there any simpler way?
thanks
« Last Edit: January 18, 2013, 02:51:12 PM by Z12 »

Offline Mathi

  • Jr. Member
  • *
  • Posts: 82
  • Country: in
    • Win32NASM
Re: Calculating Logarithm
« Reply #3 on: January 18, 2013, 06:00:07 PM »
Hi Z12,

By repeated division or multiplication it is difficult to find the fractional part of the logarithm.

     If you are ready to use the FPU registers/instructions , you can check the following instructions.

FYL2X  -  can be used to calculate log2(X) indirectly.

http://home.myfairpoint.net/fbkotler/nasmdocc.html#section-A.4.114

when st1 register is loaded with 1
then this instruction would calculate log2(st0)

you can then use fdiv instruction to find  Log2(Y)/Log2(X)  to get LogX(Y)
http://home.myfairpoint.net/fbkotler/nasmdocc.html#section-A.4.77

Once you get the final result, i guess we can use the printf function of the c library by passing "%f" along with the result.

Other instructions you might need will be
fild or fld -  load FPU register from memory location.
fst - store FPU register to memory location.  (search in the same page for documentation).

Check also instruction 'finit'   . It should be called before performing any FPU operation.

Also if X and Y are really really large then LogX(Y) is approximately (no_of_digits(Y) -1) / (no_of_digits(X) - 1)    :)

Let us know how it goes :)

Thanks,
Mathi.
« Last Edit: January 19, 2013, 03:03:11 AM by Mathi »

Offline Mathi

  • Jr. Member
  • *
  • Posts: 82
  • Country: in
    • Win32NASM
Re: Calculating Logarithm
« Reply #4 on: January 19, 2013, 07:13:20 AM »
I am not sure for which OS you are trying to do this.
For 32 bit linux this should help.


Code: [Select]
;;Assemble and link with
;nasm -felf32 log.asm
;gcc -o logtest log.o

global main
extern scanf
extern printf     

SECTION .data
    message1: db "Enter the first number(X): ", 0
    message2: db "Enter the second number(Y): ", 0
    formatin: db "%f", 0
    formatout: db "Result -  Logx(Y) = %f",10, 0
    number1: dd 0 ;
    number2: dd 0 ;
    constantone : dd 1.0     ;; Beware 'dd 1.0' is different from 'dd 1'

section .text

main:

   push message1
   call printf
   add esp, 4

   push number1 ; address of number1 (second parameter)
   push formatin ; arguments are pushed right to left (first parameter)
   call scanf
   add esp, 8

   push message2
   call printf
   add esp, 4

   push number2 ; address of number2
   push formatin ; arguments are pushed right to left
   call scanf
   add esp, 8

finit
fld dword [constantone]       ;; st0 = 1.0
fld dword [number1]           ;; st0 = number1 , st1 = 1.0
FYL2X                               ;; st0 = log2(number1)

fld dword [constantone]       ;; st0 = 1.0  , st1 = log2(number1)
fld dword [number2]           ;; st0 = number2 , st1 = 1.0 , st2 = log2(number1)
FYL2X                               ;; st0 = log2(number2) , st1 = log2(number1)

fdiv st1  ;; st0 contains log2 of number2 , st1 contains log2 of number1  . so we can calculate st0/st1.

fstp qword [esp-8]     ; store it in a 64 bit location
sub esp,8 ; adjust stack.  because 'push qword' is invalid in 32 bit architecture
push formatout
    call printf
add esp,8+4              ; 8 bytes for the float parameter and 4 for the formatout address.
ret


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Calculating Logarithm
« Reply #5 on: January 19, 2013, 08:33:50 AM »
Works great here. Thanks, Mathi!

I think Z12 mentions Windows. Your code should work with some very minor changes. Windows calls 'em "_main", "_printf", and "_scanf". You could go through the code and add underscores "by hand", but Nasm will do it for you if you add "--prefix _" to the command line. If you're running a 64-bit system, gcc will need to be told we want 32-bit code. Just adding "-m32" should fix that. So...
Code: [Select]
nasm -f win32 --prefix _ myfile.asm
gcc -m32 -o myfile.exe myfile.obj
"Should" build it for Windows - without touching the source code! That's untested, of course.

Something interesting to note: "printf" always likes its floats to be double precision! 8 bytes, not 4. Useful to know.

There's an FPU instruction, "fld1" which will load a constant "1.0" without storing it in the code. Probably clearer to do it with the "fld" instruction you're already using, but it's an alternative...

Nice start at doing it in integer math, Z12. Did you know that "inc" doesn't affect the carry-flag, or were you just lucky? :) "inc" and "dec" are somewhat unusual in that way...

Best,
Frank


Offline Mathi

  • Jr. Member
  • *
  • Posts: 82
  • Country: in
    • Win32NASM
Re: Calculating Logarithm
« Reply #6 on: January 19, 2013, 09:42:22 AM »
Quote
I'm using Windows. Thank you
Oops ! Missed this line . Thanks Frank.

BTW, i discovered that my code was indeed cross platform :)

All you have to do is,

nasm -fwin32 log.asm
golink /entry main /console log.obj msvcrt.dll

assuming you have the C runtime dll(msvcrt.dll) in your system32 folder.

Thanks,
Mathi.
« Last Edit: January 19, 2013, 09:59:18 AM by Mathi »