| | |
ASM -> C function call problem, pointer issue
Please support our Assembly advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
•
•
Join Date: Jul 2009
Posts: 4
Reputation:
Solved Threads: 0
I've been writing a java wrapper to a c library, and need to use asm to push the parameters onto the stack to call the library function.
an extract of the c code:
and the asm_dispatch function
the c dispatch code takes the java types, converts them and places them in an array of union in the order that the library function should receive them.
the output that i get from my test app
pointer before asm: 7C97E1A0
string pointer before asm: 02E224E0
string before asm: maint
String pointer after asm: 7C97E178
Pointer after asm: 02E20280
the first 3 lines print the pointer address of the 2 parameters ( long*, char* ) and the string stored by the char*, these prints are located in the c function, everything is correct there, but when the data has passed through the asm dispatch function, they seem to get changed alittle, the causes my app to fail. ( the 2 final prints are in the function pointed to by func )
i appear that pointer address are slightly modified and swap over, which is not the behave your i'm looking for.
this has me stumped, been trying to solve the issue for the last day with no success.
i hope this is the appropriate sub-forum
regards, jason
an extract of the c code:
Assembly Syntax (Toggle Plain Text)
extern void asm_dispatch(void *func, int nwords, char *arg_types, long *args, int res_type, long *resP,int conv); /********************************************************************/ /* Native methods of class CFunction */ /********************************************************************/ /* These are the set of types CFunction can handle now */ typedef enum { TY_CPTR = 0, TY_INTEGER, TY_FLOAT, TY_DOUBLE, TY_DOUBLE2, TY_STRING } ty_t; /* represent a machine word */ typedef union { jint i; jfloat f; void* p; } word_t; /* invoke the real native function */ static void dispatch(JNIEnv *env, jobject self, jobjectArray arr, ty_t res_ty, jvalue *resP) { #define MAX_NARGS 32 int i, nargs, nwords; void *func; char argTypes[MAX_NARGS]; word_t *c_args[MAX_NARGS * 2]; int conv; nargs = env->GetArrayLength(arr); if (nargs > MAX_NARGS) { JNU_ThrowByName(env, "java/lang/IllegalArgumentException", "too many arguments"); return; } func = (void *)env->GetLongField(self, FID_CPointer_peer); for (nwords = 0, i = 0; i < nargs; i++) { jobject arg = env->GetObjectArrayElement(arr, i); if (arg == NULL) { c_args[nwords]->p = NULL; argTypes[nwords++] = TY_CPTR; } else if (env->IsInstanceOf(arg, Class_Integer)) { c_args[nwords]->i = env->GetIntField(arg, FID_Integer_value); argTypes[nwords++] = TY_INTEGER; } else if (env->IsInstanceOf(arg, Class_CPointer)) { c_args[nwords]->p = (void *)env->GetLongField(arg, FID_CPointer_peer); argTypes[nwords++] = TY_CPTR; printf("pointer before asm: %p\n", c_args[nwords]->p); } else if (env->IsInstanceOf(arg, Class_String)) { if ( (c_args[nwords]->p = JNU_GetStringNativeChars(env, (jstring)arg)) == 0 ) { goto cleanup; } printf("string pointer before asm: %p\n", (char *)c_args[nwords]->p); printf("string before asm: %s\n", (char *)c_args[nwords]->p); argTypes[nwords++] = TY_STRING; } else if (env->IsInstanceOf(arg, Class_Float)) { c_args[nwords]->f = env->GetFloatField(arg, FID_Float_value); argTypes[nwords++] = TY_FLOAT; } else if (env->IsInstanceOf(arg, Class_Double)) { *(jdouble *)(c_args + nwords) = env->GetDoubleField(arg, FID_Double_value); argTypes[nwords] = TY_DOUBLE; /* harmless with 64-bit machines*/ argTypes[nwords + 1] = TY_DOUBLE2; /* make sure things work on 64-bit machines */ nwords += sizeof(jdouble) / sizeof(word_t); } else { JNU_ThrowByName(env, "java/lang/IllegalArgumentException", "unrecognized argument type"); goto cleanup; } env->DeleteLocalRef(arg); } conv = env->GetIntField(self, FID_CFunction_conv); asm_dispatch(func, nwords, argTypes, (long*)c_args, res_ty, (long*)resP, conv); cleanup: for (i = 0; i < nwords; i++) { if (argTypes[i] == TY_STRING) { free(c_args[i]->p); } } return; }
and the asm_dispatch function
Assembly Syntax (Toggle Plain Text)
void asm_dispatch(void *func, int nwords, char *arg_types, long *args, int res_type, long *resP, int conv) { __asm { mov esi, args mov edx, nwords // word address -> byte address shl edx, 2 sub edx, 4 jc args_done // Push the last argument first. args_loop: mov eax, DWORD PTR [esi+edx] push eax sub edx, 4 jge SHORT args_loop args_done: call func mov edx, conv or edx, edx jnz is_stdcall // pop arguments mov edx, nwords shl edx, 2 add esp, edx is_stdcall: mov esi, resP mov edx, res_type dec edx jge not_p64 // p64 mov [esi], eax mov [esi+4], 0 jmp done not_p64: dec edx jge not_i32 // i32 mov [esi], eax jmp done not_i32: dec edx jge not_f32 // f32 fstp DWORD PTR [esi] jmp done not_f32: // f64 fstp QWORD PTR [esi] done: } }
the c dispatch code takes the java types, converts them and places them in an array of union in the order that the library function should receive them.
the output that i get from my test app
pointer before asm: 7C97E1A0
string pointer before asm: 02E224E0
string before asm: maint
String pointer after asm: 7C97E178
Pointer after asm: 02E20280
the first 3 lines print the pointer address of the 2 parameters ( long*, char* ) and the string stored by the char*, these prints are located in the c function, everything is correct there, but when the data has passed through the asm dispatch function, they seem to get changed alittle, the causes my app to fail. ( the 2 final prints are in the function pointed to by func )
i appear that pointer address are slightly modified and swap over, which is not the behave your i'm looking for.
this has me stumped, been trying to solve the issue for the last day with no success.
i hope this is the appropriate sub-forum
regards, jason
In this case is long 32-bit or 64-bit?
You're treating it as 32-bit!
I'm not sure what calling convention Java uses but please revise your code and repost!
You can reduce your pointer addressing a tad, use scaling.
I've tweaked a function but I noted a problem
You are essentially looping for (nwords+1)
I've reviewed the c code briefly (really needs decent indentation by the way) and that is a mistake and made changes for looping for count of nwords.
A carry set following a subtraction indicates a borrow occured! In essence the result went negative! That can only happen if you did a count of (nwords+1).
Then you call func, but how does func know how many arguments are on the stack?
You're treating it as 32-bit!
I'm not sure what calling convention Java uses but please revise your code and repost!
You can reduce your pointer addressing a tad, use scaling.
I've tweaked a function but I noted a problem
You are essentially looping for (nwords+1)
I've reviewed the c code briefly (really needs decent indentation by the way) and that is a mistake and made changes for looping for count of nwords.
A carry set following a subtraction indicates a borrow occured! In essence the result went negative! That can only happen if you did a count of (nwords+1).
Assembly Syntax (Toggle Plain Text)
mov esi, args mov edx, nwords ;; // word address -> byte address ;; shl edx, 2 ;; sub edx, 4 ;; jc args_done test edx,edx jz args_done // Push the last argument first. args_loop: dec edx ;; mov eax, DWORD PTR [esi+edx] mov eax, DWORD PTR [esi+edx * 4] push eax ; sub edx, 4 ; jge args_loop jnz args_loop
Then you call func, but how does func know how many arguments are on the stack?
Last edited by wildgoose; Jul 28th, 2009 at 2:53 pm.
Your argument conv doesn't appear to make sense!
You pushed <nwords> onto the stack you need to counteract them to correct the stack pointer
For code clarity use something as follows. it's called a vector table, kind of like a case statement!
Also something funky about your <conv> You push arguments, bypass the pops, and then process? review!
You pushed <nwords> onto the stack you need to counteract them to correct the stack pointer
Assembly Syntax (Toggle Plain Text)
args_done: ; ??? Don't we need to push number of arguments, since its variable or zero? call func ; this doesn't belong??? Args WERE pushed on stack so definitely need to adjust stack! ; mov edx, conv ; test edx,edx ; jnz is_stdcall // pop arguments mov edx, nwords shl edx, 2 add esp, edx ; Offset args on stack
For code clarity use something as follows. it's called a vector table, kind of like a case statement!
Also something funky about your <conv> You push arguments, bypass the pops, and then process? review!
Assembly Syntax (Toggle Plain Text)
is_stdcall: mov esi, resP ; long pointer ; TY_CPTR = 0, ; TY_INTEGER, ; TY_FLOAT, ; TY_DOUBLE, ; TY_DOUBLE2, ; TY_STRING ;;; You could put a jump vector table ; Note: eax contains result of function call! mov edx, res_type ; resource type? jmp Near Ptr FuncTbl[ edx * 4 ] FuncTbl:: dw offset FuncPtr dw offset FuncInt dw offset FuncFlt32 dw offset FuncDbl dw offset FuncDbl2 dw offset FuncStr FuncCptr: mov [esi], eax mov [esi+4], 0 jmp done FuncInt: mov [esi], eax jmp done FuncFlt32: FuncDbl: FuncDbl2: fstp DWORD PTR [esi] jmp done FuncStr: jmp done; done: }
Last edited by wildgoose; Jul 28th, 2009 at 3:12 pm.
•
•
Join Date: Jul 2009
Posts: 4
Reputation:
Solved Threads: 0
thanks for the assistance wildgoose.
i still get the same issue
should the arguments be pass in the other order, as the pointers seem to swap
pointer before asm: 7C97E1A0
string pointer before asm: 02E222B8
string before asm: maint
String pointer after asm: 7C97E178
Pointer after asm: 02E204A8
when using the revised code you posted.
i did not write the original code but got it from http://java.sun.com/docs/books/jni/ chapter 9.
the pointers should be 64bit, and the calling convention is __cdec as junc points to a library function in a .dll.
sorry about the formatting of the earlier code, seemed to get messed up by the copy/paste
the help is much appreciated
regard, jason
ps will fix the indentation, well i would if the edit button appeared
i still get the same issue
should the arguments be pass in the other order, as the pointers seem to swap
pointer before asm: 7C97E1A0
string pointer before asm: 02E222B8
string before asm: maint
String pointer after asm: 7C97E178
Pointer after asm: 02E204A8
when using the revised code you posted.
asm Syntax (Toggle Plain Text)
void asm_dispatch(void *func, int nwords, char *arg_types, long *args, int res_type, long *resP, int conv) { __asm { mov esi, args mov edx, nwords test edx, edx jz args_done // Push the last argument first. args_loop: dec edx mov eax, DWORD PTR [esi+(edx * 4)] push eax jnz args_loop args_done: call func // pop arguments mov edx, nwords shl edx, 2 add esp, edx is_stdcall: mov esi, resP mov edx, res_type dec edx jge not_p64 // p64 mov [esi], eax mov [esi+4], 0 jmp done not_p64: dec edx jge not_i32 // i32 mov [esi], eax jmp done not_i32: dec edx jge not_f32 // f32 fstp DWORD PTR [esi] jmp done not_f32: // f64 fstp QWORD PTR [esi] done: } }
i did not write the original code but got it from http://java.sun.com/docs/books/jni/ chapter 9.
the pointers should be 64bit, and the calling convention is __cdec as junc points to a library function in a .dll.
sorry about the formatting of the earlier code, seemed to get messed up by the copy/paste
the help is much appreciated
regard, jason
ps will fix the indentation, well i would if the edit button appeared
Last edited by JasonL220; Jul 29th, 2009 at 7:32 am.
•
•
Join Date: Jul 2009
Posts: 4
Reputation:
Solved Threads: 0
c Syntax (Toggle Plain Text)
#include <stdlib.h> #include <stdio.h> #include "tdapi.h" #ifdef WIN32 #include <windows.h> #define LOAD_LIBRARY(name) LoadLibrary(name) #define FIND_ENTRY(lib, name) GetProcAddress(lib, name) #endif /* These are the set of types CFunction can handle now */ typedef enum { TY_CPTR = 0, TY_INTEGER, TY_FLOAT, TY_DOUBLE, TY_DOUBLE2, TY_STRING } ty_t; /* represent a machine word */ typedef union { int i; float f; void* p; } word_t; void asm_dispatch(void *func, int nwords, char *arg_types, long *args, int res_type, long *resP, int conv) {
asm Syntax (Toggle Plain Text)
__asm { mov esi, args mov edx, nwords test edx, edx jz args_done // Push the last argument first. args_loop: dec edx mov eax, DWORD PTR [esi+(edx * 4)] push eax jnz args_loop args_done: call func // pop arguments mov edx, nwords shl edx, 2 add esp, edx is_stdcall: mov esi, resP mov edx, res_type dec edx jge not_p64 // p64 mov [esi], eax mov [esi+4], 0 jmp done not_p64: dec edx jge not_i32 // i32 mov [esi], eax jmp done not_i32: dec edx jge not_f32 // f32 fstp DWORD PTR [esi] jmp done not_f32: // f64 fstp QWORD PTR [esi] done: } }
c Syntax (Toggle Plain Text)
int main( int argc, char* argv[] ) { #define MAX_NARGS 32 #define NUM_CARDS 8 /* card states */ #define CARD_NIU 0 #define CARD_REQUIRED 1 #define CARD_PRESENT 2 #define NUM_SS7_TRUNKS 16 #define NUM_SS7_LINKS 2 #define NUM_TIMESLOTS 32 typedef int (*FNPTR)(int); typedef void (*FNPTR2)(char*); int nargs = 2; int nwords = 1; void *func; FNPTR InitM; FNPTR2 SetHost; char argTypes[MAX_NARGS]; word_t c_args[MAX_NARGS * 2]; int conv; long pointer = 10; long result = 0; HMODULE hDLL; int stat; int cardState[NUM_CARDS]; if( ( hDLL = LoadLibrary("C:\\ngntdapi.dll")) == NULL ) { printf ("LoadLibrary failed\n"); return 1; } func = GetProcAddress( hDLL, "TDapi_GetServiceProvider" ); InitM = (FNPTR)GetProcAddress( hDLL, "TDapi_InitM" ); SetHost = (FNPTR2)GetProcAddress( hDLL, "TDapi_SetHost" ); for(int i=0; i<NUM_CARDS; i++) { cardState[i] = CARD_NIU; } if( ( stat = InitM(4000)) != TDAPI_SUCCESS ) { printf("TDapi_Init() failed, status %d", stat); return 1; } if(argc > 1) { SetHost(argv[1]); } c_args[0].p = &pointer; argTypes[0] = TY_CPTR; c_args[1].p = "maint"; argTypes[1] = TY_STRING; printf("pointer before asm: %p\n", c_args[0].p); printf("string pointer before asm: %p\n", (char *)c_args[1].p); printf("string before asm: %s\n", (char *)c_args[1].p); asm_dispatch(func, 2, argTypes, (long*)c_args, TY_INTEGER, (long*)result, 0); return 0; }
i just run that i every worked fine, seems like the issue is not directly related to the asm, problem solved (ish)
any extra comment on the asm code would still be appreciated
regards, jason
Last edited by JasonL220; Jul 29th, 2009 at 10:56 am.
I see the C code a bit clearer now!
What is sizeof(word_t)
Is it 16-bit ? 32-bit? It's being passed like its two halves.
Win32 int and long are both 32-bit but the assembly doesn't treat it as such!
The initial loop in assembly only pushs <nwords> 32-bit values onto the stack. If 16-bit is being paired into 32-bit then its fine. But if word_t is 32-bit not 16-bit then only 1/2 the args are being pushed. If that's the case then...
What is sizeof(word_t)
Is it 16-bit ? 32-bit? It's being passed like its two halves.
Win32 int and long are both 32-bit but the assembly doesn't treat it as such!
The initial loop in assembly only pushs <nwords> 32-bit values onto the stack. If 16-bit is being paired into 32-bit then its fine. But if word_t is 32-bit not 16-bit then only 1/2 the args are being pushed. If that's the case then...
Assembly Syntax (Toggle Plain Text)
mov edx,nwords shl edx,1 dec edx
Ah, a fresh shower and everything is clearer!
word_t is a union declaration and currently it is 32-bits.
They haven't included the other data types such as double.
It's unclear what the function being called does, or why it doesn't need everything! It does seem the assembly isn't appropriate for the call, only like its unfinished!
word_t is a union declaration and currently it is 32-bits.
They haven't included the other data types such as double.
It's unclear what the function being called does, or why it doesn't need everything! It does seem the assembly isn't appropriate for the call, only like its unfinished!
![]() |
Similar Threads
- Function Call as a parameter? (C)
- Problem using Pointer Functions (C++)
- Function call problem (C++)
- Constructor function call problem (C++)
- Problem with pointer-to-function (C++)
- no matching function for call to 'strcmp(std::string&, std::string&)' (C++)
- Function call problem (HTML and CSS)
Other Threads in the Assembly Forum
- Previous Thread: How to detect the type of processor using Assembly Language???
- Next Thread: Help!!! Urgent!!!
| Thread Tools | Search this Thread |
Tag cloud for Assembly





