News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Operations on complex numbers in ASM dynamic library

Started by Yellow Matt, February 02, 2015, 01:26:28 AM

Previous topic - Next topic

Yellow Matt

Hello everyone, I'm new to this forum and I would like to ask you a question about my problem with complex numbers in my ASM DLL.
My whole solution contains GUI (C++ - Windows Forms), Dynamic Library in C++, and of course Dynamic Library in ASM. (In Visual Studio it's a solution which contains 3 projects - GUI, CppLib, AsmLib)
The whole program can add, subtract, multiply or divide complex numbers.
Libraries are connected to the main project (GUI) and everything works fine except my ASM knowledge..
I have never wrote/coded anything in ASM and I have no idea how to start and do it correctly.

Here's my header file from the C++ library:

CppMath.h
#ifdef CPPMATH_EXPORTS
#define CPPMATH_API __declspec(dllexport)
#else
#define CPPMATH_API __declspec(dllimport)
#endif

#pragma once
#include <string>
#include <iostream>

using namespace std;

// This class is exported from the CppMath.dll
class CPPMATH_API CppMath {
public:
CppMath(void);
};

extern CPPMATH_API double* nCppMath;

CPPMATH_API double* fnAddition(double a, double b, double c, double d);
CPPMATH_API double* fnSubtraction(double a, double b, double c, double d);
CPPMATH_API double* fnMultiplication(double a, double b, double c, double d);
CPPMATH_API double* fnDivision(double a, double b, double c, double d);


Where those 4 double variables are for 1st and 2nd complex numbers (a+bi , c+di)

Here's my header file from the ASM library:

AsmMath.h
#ifdef ASMMATH_EXPORTS
#define ASMMATH_API __declspec(dllexport)
#else
#define ASMMATH_API __declspec(dllimport)
#endif

ASMMATH_API double* fnAddition;
ASMMATH_API double* fnSubtraction;
ASMMATH_API double* fnMultiplication;
ASMMATH_API double* fnDivision;


Here's my first question: Do I need to add parameters to functions in my AsmMath.h like it's in CppMath, or can I leave it as it is ?
(ASMMATH_API double* fnAddition(double a, double b, double c, double d); ??)

Here's my ASM file from the ASM library:

AsmMath.asm

.486
.model flat, stdcall
.code

fnAddition proc a: DWORD, b: DWORD, c: DWORD, d: DWORD
xor eax,eax
mov eax,a
mov ecx,b
ror ecx,1 shld eax,ecx,2
jnc ET1
mul b
ret

ET1: mul a
neg b
    ret 8

fnAddition endp

fnSubtraction proc a: DWORD, b: DWORD, c: DWORD, d: DWORD
xor eax,eax
mov eax,a
mov ecx,b
ror ecx,1 shld eax,ecx,2
jnc ET1
mul b
ret

ET1: mul a
neg b
    ret 8

fnSubtraction endp

fnMultiplication proc a: DWORD, b: DWORD, c: DWORD, d: DWORD
xor eax,eax
mov eax,a
mov ecx,b
ror ecx,1 shld eax,ecx,2
jnc ET1
mul b
ret

ET1: mul a
neg b
    ret 8

fnMultiplication endp

fnDivision proc a: DWORD, b: DWORD, c: DWORD, d: DWORD
xor eax,eax
mov eax,a
mov ecx,b
ror ecx,1 shld eax,ecx,2
jnc ET1
mul b
ret

ET1: mul a
neg b
    ret 8

fnDivision endp

end


(Those commands inside every function are totally random / not used)

Here's my second question: Can I somehow transfer/pass double variables from C++ to ASM ?
(I mean, what kind of parameters should I use in my AsmMath.asm,because as I guess those DWORD won't work for my double variables)

I would like to create something like this - according to my algorithm wrote in C++:

CppMath.cpp
CPPMATH_API double* fnAddition(double a, double b, double c, double d)
{
double real_part = a + c;
double imaginary_part = b + d;
double* complex_number = new double[2];
complex_number[0] = real_part;
complex_number[1] = imaginary_part;
return complex_number;
}

CPPMATH_API double* fnSubtraction(double a, double b, double c, double d)
{
double real_part = a - c;
double imaginary_part = b - d;
double* complex_number = new double[2];
complex_number[0] = real_part;
complex_number[1] = imaginary_part;
return complex_number;
}

CPPMATH_API double* fnMultiplication(double a, double b, double c, double d)
{
double real_part = a * c - b * d;
double imaginary_part = b * c + a * d;
double* complex_number = new double[2];
complex_number[0] = real_part;
complex_number[1] = imaginary_part;
return complex_number;
}

CPPMATH_API double* fnDivision(double a, double b, double c, double d)
{
double real_part = (a * c + b * d) / (c * c + d * d);
double imaginary_part = (b * c - a * d) / (c * c + d * d);
double* complex_number = new double[2];
complex_number[0] = real_part;
complex_number[1] = imaginary_part;
return complex_number;
}


My libraries have to do the same thing in C++ and in Assembler to compare results and both DLL's timing results.
I'm wondering if it's possible to do.. I'd be greatful if someone could help me with this problem.
I'm using: Microsoft Visual Studio Ultimate 2013

qWord

Quote from: Yellow Matt on February 02, 2015, 01:26:28 AMDo I need to add parameters to functions in my AsmMath.h like it's in CppMath[...]?
Yes, of course.

Quote from: Yellow Matt on February 02, 2015, 01:26:28 AM
Can I somehow transfer/pass double variables from C++ to ASM ?
(I mean, what kind of parameters should I use in my AsmMath.asm,because as I guess those DWORD won't work for my double variables)
REAL8 is the type for doubles. (REAL4 = float). I would strongly suggest you to do the allocation in c++ and pass the pointer to the buffer:
.686
.xmm
option casemap: none
.model flat, C

.code
; CPPMATH_API double* fnAddition(double *result, double a, double b, double c, double d);
fnAddition proc C pResult: ptr REAL8, a: REAL8, b: REAL8, _c: REAL8, d: REAL8

mov eax,pResult
movsd xmm0,a
movsd xmm1,b
addsd xmm0,_c
addsd xmm1,d
movsd REAl8 ptr [eax+0],xmm0
movsd REAL8 ptr [eax+8],xmm1

ret

fnAddition endp
end


(Above assumes that the target platform is win32)
MREAL macros - when you need floating point arithmetic while assembling!

Yellow Matt

Thank you qWord for your help I appreciate it.  :t
Unfortunately adding parameters to functions in my AsmMath.h (ex.:)
ASMMATH_API double* fnAddition(double *result, double a, double b, double c, double d);
don't really work. I recive various linker's errors like:
1>import.def : error LNK2001: unresolved external symbol fnAddition
1>C:\Users\Matthew\Documents\Visual Studio 2013\Projects\Liczby zespolone\Debug\AsmLib.lib : fatal error LNK1120: 1 unresolved externals

On the other hand, leaving it blank as it was before eliminates those linker's errors. (Compilation was successfull)

According to an algorithm of multiplication and division from my CppMath.cpp, did I do it right in my AsmMath.asm, or am I just wrong ?
fnMultiplication proc C pResult: ptr REAL8, a: REAL8, b: REAL8, _c: REAL8, d: REAL8

mov eax,pResult
movsd xmm0,a
movsd xmm1,b
mulsd xmm0,_c
mulsd xmm1,d
subsd xmm0,xmm1
movsd xmm2,a
mulsd xmm1,_c
mulsd xmm2,d
addsd xmm1,xmm2
movsd REAl8 ptr [eax+0],xmm0
movsd REAL8 ptr [eax+8],xmm1

ret

fnMultiplication endp

fnDivision proc C pResult: ptr REAL8, a: REAL8, b: REAL8, _c: REAL8, d: REAL8

mov eax,pResult
movsd xmm0,a
movsd xmm1,b
mulsd xmm0,_c
mulsd xmm1,d
addsd xmm0,xmm1
movsd xmm1,_c
movsd xmm2,d
mulsd xmm1,_c
mulsd xmm2,d
addsd xmm1,xmm2
divsd xmm0,xmm1
movsd xmm1,b
movsd xmm2,a
mulsd xmm1,_c
mulsd xmm2,d
subsd xmm1,xmm2
movsd xmm2,_c
movsd xmm3,d
mulsd xmm2,_c
mulsd xmm3,d
addsd xmm2,xmm3
divsd xmm1,xmm2
movsd REAl8 ptr [eax+0],xmm0
movsd REAL8 ptr [eax+8],xmm1

ret

fnDivision endp

end


(I'm just not really sure if I can use some of xmm2,xmm3 and am I using divsd and mulsd commands correctly)
I'm using: Microsoft Visual Studio Ultimate 2013

qWord

Quote from: Yellow Matt on February 02, 2015, 04:16:14 AMdon't really work. I recive various linker's errors
You must disable name mangling by using the linkage directives extern "C":
Quote#define ASMMATH_API extern "C" __declspec(...)

Quote from: Yellow Matt on February 02, 2015, 04:16:14 AMAccording to an algorithm of multiplication and division from my CppMath.cpp, did I do it right in my AsmMath.asm, or am I just wrong ?
These scalar XMM instructions are very intuitive to use and your code looks good, but if you are not sure, please take look into AMD's or Intel's Manuals. Remarks that you can use XMM0 to XMM7.
MREAL macros - when you need floating point arithmetic while assembling!

Yellow Matt

I have implemented this into my code and the results are still bad ..  :(

// AsmMath.h

#ifdef ASMMATH_EXPORTS
#define ASMMATH_API extern "C" __declspec(dllexport)
#else
#define ASMMATH_API extern "C" __declspec(dllimport)
#endif

ASMMATH_API double* fnAddition(double* results, double a, double b, double c, double d);
ASMMATH_API double* fnSubtraction(double* results, double a, double b, double c, double d);
ASMMATH_API double* fnMultiplication(double* results, double a, double b, double c, double d);
ASMMATH_API double* fnDivision(double* results, double a, double b, double c, double d);


Errors:
1>import.def : error LNK2001: unresolved external symbol fnAddition
1>import.def : error LNK2001: unresolved external symbol fnDivision
1>import.def : error LNK2001: unresolved external symbol fnMultiplication
1>import.def : error LNK2001: unresolved external symbol fnSubtraction
1>C:\Users\Matthew\Documents\Visual Studio 2013\Projects\Liczby zespolone\Debug\AsmLib.lib : fatal error LNK1120: 4 unresolved externals


I just can't handle this error.. Everything seems fine for me.

import.def

LIBRARY "ComplexAsm"
EXPORTS
fnAddition
fnSubtraction
fnMultiplication
fnDivision


I have the ASMMATH_EXPORTS into the preprocesor definitions as well as import.def in definition module file. (In my AsmLib project properties..)
I'm using: Microsoft Visual Studio Ultimate 2013

rrr314159

Hello Yellow, Welcome to the forum!

By an amazing coincidence I was writing the routines you want (but, SIMD) when you posted the other day. I'm converting a bunch of algos from FPU to SSE/AVX and was doing complex rational polynomials, and other analytic functions, like Zeta function power series. I don't particularly know about interfacing to C++, since I work entirely in assembler; but could figure it out easily enough.

Your fnMultiplication routine is close, but why are you doing "mulsd xmm1, _c"? Actually I know why, but what value is in xmm1 at that point in the code?

One other question, is this a homework assignment? Actually I know the answer to that one also  :icon_cool:
I am NaN ;)

qWord

It seems like that the linker doesn't get the assembler written module.(?)
You maybe can upload the project? (after deleting precompiled headers (*.ipch), the *.sdf-file(s) and all builds (Release/Debug))
MREAL macros - when you need floating point arithmetic while assembling!

raymond

If you are writing programs entirely in assembly, you may find some use for the library of complex number functions (using the FPU) available at: http://www.ray.masmcode.com/complex.html

If you are writing in-line assembly code within a C/C++ program, the above could still be of some use depending on your knowledge for interfacing C and assembly.

Or, if you intend to write your own functions in C, the source code of each function could be used as a guide.
Whenever you assume something, you risk being wrong half the time.
https://masm32.com/masmcode/rayfil/index.html

Yellow Matt

Here's my whole project solution:

Complex Numbers.rar - Visual Studio Project Files   (File size: 14.32[MB])
http://download1349.mediafire.com/w3vw55mtzaxg/3yema4kqn4zjdh5/Complex+Numbers.rar
(I could not upload this package here, because of the limits)
I'm using: Microsoft Visual Studio Ultimate 2013

qWord

The file ComplexAsm.asm is not part of the build process.
-> In the solution explorer right-click on file ComplexAsm.asm, open the properties and then select the element type "Microsoft Macro Assembler".
MREAL macros - when you need floating point arithmetic while assembling!

Yellow Matt

Thank you very much qWord, you have solved my problem and you have also proved, that I'm an idiot ;D
Everything is fine now.  :biggrin:
 
(Riddle solved - Topic closed.. I think)
I'm using: Microsoft Visual Studio Ultimate 2013