ItsMods

Full Version: Math in Assembly
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
- Math in Assembly By Ohad Klein And NieXrlaM (David)

how to do Square root in assembly?

the follow code will do this function
Code:
push Num
call sqrt
pop Num
sqrt:
pop eax
fld DWORD PTR [eax]
fsqrt
fstp DWORD ptr[eax]
push eax
retn

at c++ the code will be like this
Code:
inline float Sqrt(float Num)
{
    _asm
    {
        fld DWORD PTR [Num]
        fsqrt
        fstp DWORD ptr[Num]
    }
    return Num;
}

how to do Sine in assembly?

the follow code will do this function
Code:
push Rad
call Sine
pop Rad
Sine:
pop eax
fld DWORD PTR [eax]
fsin
fstp DWORD PTR [eax]
push eax
retn

at c++ the code will be like this
Code:
inline float Sine(float Rad)
{
    _asm
    {
        fld DWORD PTR [Rad]
        fsin
        fstp DWORD PTR [Rad]
    }
    return Rad;
}

same at cosine
just change from "fsin" to "fcos"

how to do tangents in assembly?

the follow code will do this function
Code:
push Rad
call tan
pop Rad
tan:
pop eax
fld DWORD PTR [eax]
fsincos
fdiv
fstp DWORD PTR [eax]
push eax
retn

How i can Prove it ?
answer..
sine(alpha)/cosine(alpha) = tangents(alpha)

at c++ the code will be like this
Code:
inline float Tan(float Rad)
{
    _asm
    {
        fld DWORD PTR [Rad]
        fsincos
        fdiv
        fstp DWORD PTR [Rad]
    }
    return Rad;
}

how to do Arc tangents in assembly?

the follow code will do this function
Code:
push Rad
call Atan
pop Rad
Atan:
pop eax
fld dword ptr [eax]
fld1
fpatan
fstp dword ptr [eax]
push eax
retn

at c++ the code will be like this
Code:
inline float Atan(float Rad)
{
    _asm{
    fld dword ptr [Rad]
    fld1
    fpatan
    fstp dword ptr [Rad]
    }
    return Rad;
}

also .. if you want to do
Asin or Acos functions ..
you will use this logic (C++)

Code:
inline float Asin(float Rad)
{
    Rad = Sqrt(Rad*Rad/(1-Rad*Rad));
    Rad = Atan(Rad);
    return Rad;
}

inline float Acos(float Rad)
{
    Rad = Sqrt((1-Rad*Rad)/(Rad*Rad));
    Rad = Atan(Rad);
    return Rad;
}

How i can Prove it ?
answer..

Asin(x) = Atan(((x*x/(1-x*x))^0.5)
Acos(x) = Atan(((1-x*x)/(x*x))^0.5)

how to do Exponentiation in assembly?

the follow code will do this function
Code:
push Base
push Power
call Pow
pop Num
Pow:
pop edx
pop ebx
fld DWORD PTR [edx]
fld DWORD PTR [ebx]
fld1
fsub
fyl2xp1
sub     esp,16                                ; z = x*log2
fist    DWORD PTR [esp+12]            ; round
fld1
fstp    TBYTE PTR [esp]
fisub   DWORD PTR [esp+12]            ; z - round
mov     eax, [esp+12]
add     [esp+8],eax
f2xm1
fld1
fadd
fld     TBYTE PTR [esp]               ; 2^(round )
fmul                                  ; 2^z = e^x
add     esp,16
fstp DWORD PTR [ebx]
push ebx
retn

at c++ the code will be like this
Code:
inline float Pow(float Base, float Power)
{
    _asm
    {
        fld DWORD PTR [Power]
        fld DWORD PTR [Base]
        fld1
        fsub
        fyl2xp1
        sub     esp,16                                ; z = x*log2
        fist    DWORD PTR [esp+12]            ; round
        fld1
        fstp    TBYTE PTR [esp]
        fisub   DWORD PTR [esp+12]            ; z - round
        mov     eax, [esp+12]
        add     [esp+8],eax
        f2xm1
        fld1
        fadd
        fld     TBYTE PTR [esp]               ; 2^(round )
        fmul                                  ; 2^z = e^x
        add     esp,16
        fstp DWORD PTR [Base]
    }
    return Base;
}

For more functions download the attachment file

Enjoy Smile
(and sorry for my english)
Interesting, how about mod (remainder)?
Great stuff, but I had a problem with your SinCos function.

Code:
inline void SinCos(float Rad, float &sinAns, float &cosAns)
{
    _asm
    {
        fld DWORD PTR [Rad]
        fsincos
        fstp    dword ptr [sinAns]
        fstp    dword ptr [cosAns]
    }
}

The first problem is the result from the function was always 0 for both sin and cos. I had to put the sinAns and cosAns into some registers for it to work.

Code:
inline void SinCos(float Rad, float &sinAns, float &cosAns)
{
    _asm
    {
        FLD        DWORD PTR [Rad]

        FSINCOS

        MOV        EAX, DWORD PTR [cosAns]
        MOV        ECX, DWORD PTR [sinAns]

        FSTP    DWORD PTR [EAX]
        FSTP    DWORD PTR [ECX]
    }
}

Second, I had to flip the cos and sine popping around so it gets cos first then sine. I am not sure why this is, because the documentation I read says Cos is in S0 and Sine is in S1. Very odd....
(10-08-2011, 07:58)skidz Wrote: [ -> ]Great stuff, but I had a problem with your SinCos function.

Code:
inline void SinCos(float Rad, float &sinAns, float &cosAns)
{
    _asm
    {
        fld DWORD PTR [Rad]
        fsincos
        fstp    dword ptr [sinAns]
        fstp    dword ptr [cosAns]
    }
}

The first problem is the result from the function was always 0 for both sin and cos. I had to put the sinAns and cosAns into some registers for it to work.

Code:
inline void SinCos(float Rad, float &sinAns, float &cosAns)
{
    _asm
    {
        fld DWORD PTR [Rad]
        fsincos
        mov eax, DWORD PTR[cosAns]
        mov edx, DWORD PTR[sinAns]
        fstp DWORD PTR[eax]
        fstp DWORD PTR[edx]
    }
}

Second, I had to flip the cos and sine popping around so it gets cos first then sine. I am not sure why this is, because the documentation I read says Cos is in S0 and Sine is in S1. Very odd....

yea.. this code is very old.. and not coded right,
thnx for the Note Smile