News:

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

Main Menu

Passing 2d arrays and 1d arrays from c++ to asm

Started by pawkondr, January 13, 2015, 03:18:19 AM

Previous topic - Next topic

pawkondr

Hello!
I have a problem and I would like to ask if this is possible to do.
I have asm library, and I would like to pass two arrays and two 2d arrays. First is matrix given, second is result matrix third is matrix with answers and last is matrix with results after calculations. Last parameter is length. For example if last param is 5 you have matrixes 5x5, 5, 5x5, 5.
This is code in c++:
typedef int(_stdcall *DLLFunc)(double**, double*, double**, double*, int);
than in main function:
   
hDll = LoadLibrary("FibAsmLib");

if (hDll != NULL){

//proc = GetProcAddress(hDll, "MyProc");
myAsmProc = (DLLFunc)GetProcAddress(hDll, "MyProc");

if (myAsmProc != NULL){
result = myAsmProc(arrayA, arrayB, arrayAlfa, arrayBeta, rowA);
}
}

How am I supposed to operate on this pointers in asm? How to get any value from that array?
My code in asm:
.486
.model flat, stdcall
.data
.code

PUBLIC MyProc
MyProc proc w: DWORD, x:DWORD, y:DWORD, z:DWORD, e:DWORD
mov eax, 5
ret
MyProc endp
end

Library is connected correctly.

jj2007

What you want is certainly possible. You pass pointers to matrices - just use them. Suppose you want to return the sum w(n)+y(n) in x:
MyProc proc uses esi edi w: DWORD, x:DWORD, y:DWORD, z:DWORD, e:DWORD
  xor ecx, ecx
  ; int 3
  mov esi, w
  mov edx, y
  mov edi, x
  .Repeat
        mov eax, [esi+DWORD*ecx]  ; get w value from element ecx
        add eax, [edx+DWORD*ecx]  ; add y value from element ecx
        mov [edi+DWORD*ecx], eax  ; store in destination element ecx
        inc ecx
  .Until ecx>e  ; could be > or >=, check yourself
  ret


Besides, you should certainly uncomment the ; int 3, set Olly as your just in time debugger, and follow step by step using the F7 key.

Welcome to the forum :icon14:

pawkondr

Hello, thanks for answer. My job is to do the same thing in c++ and in assembler and compare results.
This is my code in c++ which is in an external library.
CPPLIBRARY_API int fnCPPLibrary(double** A, double* B, double** alfa, double* beta, int n){
for (int i = 0; i < n; i++){
if (A[i][i] == 0) {
std::cout << "You cant create alfa and beta matrix" << std::endl << "Devision by 0!" << std::endl;
return 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) alfa[i][j] = 0;
else
alfa[i][j] = -(A[i][j] / A[i][i]);
}
beta[i] = B[i] / A[i][i];
}
return 0;
}

Is this very complicated? I have never wrote code in assembler. Code in c++ was easy as pie. Can you give me some help?

dedndave

the forum search tool might help
i seem to recall a few threads related to C-called asm functions

probably one easy way is to use a static library
so - that might be a good search term

pawkondr

If I could find a solution myself i would try to solve it and definetly I wouldn't waste your time. I need some good advices :)

FORTRANS

Hi,

Quote from: pawkondr on January 15, 2015, 02:13:58 AM
My job is to do the same thing in c++ and in assembler and compare results.


   For the following line of code;

for (int i = 0; i < n; i++) {

The assembly code could look like this:

NTest   EQU     5       ;  Assign a value for "n".  Or MOV the value
                        ; into a register to test against.

        MOV     [IndexI],0      ; int i = 0;"
ForI:                           ; Top of for loop. "for ("

        CMP     [IndexI],NTest  ; "i < n;"
        JGE     ForEnd

                                ; Do stuff "{ ... }"

        INC     [IndexI]        ;  "i++"
        JMP     ForI

ForEnd:


   Does that help or hurt?

Regards,

Steve N.

habran

Hi pawkondr

My version of JWasm has built in .FOR - .ENDFOR loop
To type the separator '¦' pres ALT then type 221 and release ALT
I promise you it will work faster than C++
you can write something like this:

     .for (ebx=0¦ebx<n¦ebx++)
         .for (edi=0¦edi<n¦edi++)
              ;some code
         .endfor
     .endfor
Cod-Father

pawkondr

Ok, thanks for answers. How to get value from correct field in array? like a[index i][index j] in c++?

dedndave

Quote from: pawkondr on January 15, 2015, 06:14:16 AM
If I could find a solution myself i would try to solve it and definetly I wouldn't waste your time. I need some good advices :)

i would help more if i could
i just don't write much code in anything but assembler
i can make a static library, however   :P

jj2007

Here is part of the solution - more attached, with sources in *.asc aka RTF format.

Quote from: pawkondr on January 15, 2015, 08:12:02 AM
How to get value from correct field in array? like a[index i][index j] in c++?
Check in particular the lea instruction in the source.

include \masm32\include\masm32rt.inc

.code
fnCPPLibrary proc uses esi edi ebx pA, B:DOUBLE, pAlfa, beta:DOUBLE, n      ; double** A, double* B, double** alfa, double* beta, int n) $export (keyword for building the dll with RichMasm)
  mov esi, pA
  A equ <DOUBLE ptr [esi]>
  mov edi, pAlfa
  alfa equ <DOUBLE ptr [edi]>
  i equ <eax>
  j equ <ebx>
  mov i, 0
  .While i<n
      mov j, 0
      .While j<n
            push eax
            .if i==j
                  imul eax, i, DOUBLE      ; alfa[j]=0
                  imul n
                  lea eax, [eax+j*DOUBLE]
                  ; deb 4, "Loop", eax      ; debug macro needs MasmBasic
                  fldz      ; alfa[j]=0
            .else
                  imul eax, i, DOUBLE
                  imul n      ; i*n
                  mov edx, [esp]
                  lea eax, [eax+edx*DOUBLE]
                  fld A[eax]      ; A
                  imul eax, dword ptr [esp], DOUBLE
                  imul n
                  lea eax, [eax+j*DOUBLE]
                  ; deb 4, "Loop", eax
                  fld A[eax]      ; A[j]
                  fchs      ; change sign
                  fdiv      ; divide: alfa[j] = -(A[j] / A)
            .endif
            fstp alfa[eax]
            pop eax
            inc j
      .Endw
      inc i
  .Endw
  ret
fnCPPLibrary endp

LibMain proc instance:DWORD, reason:DWORD, unused:DWORD
    m2m eax, TRUE
    ret
LibMain endp

end LibMain


Output using a 5x5 matrix:
mxA DOUBLE 100.0, 100.1, 100.2, 100.3, 100.4
DOUBLE 101.0, 101.1, 101.2, 101.3, 101.4
DOUBLE 102.0, 102.1, 102.2, 102.3, 102.4
DOUBLE 103.0, 103.1, 103.2, 103.3, 103.4
DOUBLE 104.0, 104.1, 104.2, 104.3, 104.4

mxB DOUBLE rows*columns dup(?)

; *       c0      c1      c2      c3      c4
; r0      0.000   -0.999  -0.998  -0.997  -0.996
; r1      -1.001  0.000   -0.999  -0.998  -0.997
; r2      -1.002  -1.001  0.000   -0.999  -0.998
; r3      -1.003  -1.002  -1.001  0.000   -0.999
; r4      -1.004  -1.003  -1.002  -1.001  0.000

pawkondr

Thanks for your answer, I am impressed :)
But i need to do this as a library in visual studio. I must have code inside that library and then i need to call this function from my cpp code which i gave in first post. How to do that with that code from post above?
Thanks for all your help. I am so grateful.

dedndave

you haven't said whether you want a static library or dynamic one

but, here is an example of a static lib, written in ASM
all you need is a simple C header file to include it into a C project

http://masm32.com/board/index.php?topic=2743.msg29059#msg29059

pawkondr

Here is my library, project from visual studio. It must be called from this code in c++:
hDll = LoadLibrary("FibAsmLib");

if (hDll != NULL){

myAsmProc = (DLLFunc)GetProcAddress(hDll, "MyProc");

if (myAsmProc != NULL){
result = myAsmProc(arrayA, arrayB, arrayAlfa, arrayBeta, rowA);
}
}

jj2007

You are still showing code that loads a DLL, so my previous code would perfectly fit.
However, if you prefer a static library, it's attached. The source file is in RTF format.

You call MyProc exactly as you would call your static C++ library. Just change the library name.

pawkondr

Hello again, I tried to change called library name but it throws me error like this:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

And if I try to paste code that you wrote to me to my dll, that I created visual throws me some errors too:
Error   1   error A1000: cannot open file : \masm32\include\masm32rt.inc
Error   2   error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\fibAsm.obj" /W3 /errorReport:prompt  /TafibAsm.asm" exited with code 1.   C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\BuildCustomizations\masm.targets   50   5   FibAsmLib

This language is killing me :(
Thanks for answers