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:
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
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