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: JasonL220 is an unknown quantity at this point 
Solved Threads: 0
JasonL220 JasonL220 is offline Offline
Newbie Poster

ASM -> C function call problem, pointer issue

 
0
  #1
Jul 28th, 2009
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:

  1. extern void asm_dispatch(void *func, int nwords, char *arg_types, long *args,
  2. int res_type, long *resP,int conv);
  3.  
  4. /********************************************************************/
  5. /* Native methods of class CFunction */
  6. /********************************************************************/
  7.  
  8. /* These are the set of types CFunction can handle now */
  9. typedef enum
  10. {
  11. TY_CPTR = 0,
  12. TY_INTEGER,
  13. TY_FLOAT,
  14. TY_DOUBLE,
  15. TY_DOUBLE2,
  16. TY_STRING
  17. } ty_t;
  18.  
  19. /* represent a machine word */
  20. typedef union
  21. {
  22. jint i;
  23. jfloat f;
  24. void* p;
  25. } word_t;
  26.  
  27. /* invoke the real native function */
  28. static void
  29. dispatch(JNIEnv *env,
  30. jobject self,
  31. jobjectArray arr,
  32. ty_t res_ty,
  33. jvalue *resP)
  34. {
  35. #define MAX_NARGS 32
  36. int i, nargs, nwords;
  37. void *func;
  38. char argTypes[MAX_NARGS];
  39. word_t *c_args[MAX_NARGS * 2];
  40. int conv;
  41.  
  42. nargs = env->GetArrayLength(arr);
  43. if (nargs > MAX_NARGS)
  44. {
  45. JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
  46. "too many arguments");
  47. return;
  48. }
  49.  
  50. func = (void *)env->GetLongField(self, FID_CPointer_peer);
  51.  
  52. for (nwords = 0, i = 0; i < nargs; i++)
  53. {
  54. jobject arg = env->GetObjectArrayElement(arr, i);
  55.  
  56. if (arg == NULL)
  57. {
  58. c_args[nwords]->p = NULL;
  59. argTypes[nwords++] = TY_CPTR;
  60. }
  61. else if (env->IsInstanceOf(arg, Class_Integer))
  62. {
  63. c_args[nwords]->i = env->GetIntField(arg, FID_Integer_value);
  64. argTypes[nwords++] = TY_INTEGER;
  65. }
  66. else if (env->IsInstanceOf(arg, Class_CPointer))
  67. {
  68. c_args[nwords]->p = (void *)env->GetLongField(arg, FID_CPointer_peer);
  69. argTypes[nwords++] = TY_CPTR;
  70. printf("pointer before asm: %p\n", c_args[nwords]->p);
  71. }
  72. else if (env->IsInstanceOf(arg, Class_String))
  73. {
  74. if ( (c_args[nwords]->p = JNU_GetStringNativeChars(env, (jstring)arg)) == 0 )
  75. {
  76. goto cleanup;
  77. }
  78. printf("string pointer before asm: %p\n", (char *)c_args[nwords]->p);
  79. printf("string before asm: %s\n", (char *)c_args[nwords]->p);
  80. argTypes[nwords++] = TY_STRING;
  81. }
  82. else if (env->IsInstanceOf(arg, Class_Float))
  83. {
  84. c_args[nwords]->f = env->GetFloatField(arg, FID_Float_value);
  85. argTypes[nwords++] = TY_FLOAT;
  86. }
  87. else if (env->IsInstanceOf(arg, Class_Double))
  88. {
  89. *(jdouble *)(c_args + nwords) = env->GetDoubleField(arg, FID_Double_value);
  90. argTypes[nwords] = TY_DOUBLE;
  91. /* harmless with 64-bit machines*/
  92. argTypes[nwords + 1] = TY_DOUBLE2;
  93. /* make sure things work on 64-bit machines */
  94. nwords += sizeof(jdouble) / sizeof(word_t);
  95. }
  96. else
  97. {
  98. JNU_ThrowByName(env, "java/lang/IllegalArgumentException", "unrecognized argument type");
  99. goto cleanup;
  100. }
  101. env->DeleteLocalRef(arg);
  102. }
  103.  
  104. conv = env->GetIntField(self, FID_CFunction_conv);
  105. asm_dispatch(func, nwords, argTypes, (long*)c_args, res_ty, (long*)resP, conv);
  106.  
  107. cleanup:
  108. for (i = 0; i < nwords; i++)
  109. {
  110. if (argTypes[i] == TY_STRING)
  111. {
  112. free(c_args[i]->p);
  113. }
  114. }
  115. return;
  116. }

and the asm_dispatch function

  1. void asm_dispatch(void *func,
  2. int nwords,
  3. char *arg_types,
  4. long *args,
  5. int res_type,
  6. long *resP,
  7. int conv)
  8. {
  9. __asm {
  10. mov esi, args
  11. mov edx, nwords
  12. // word address -> byte address
  13. shl edx, 2
  14. sub edx, 4
  15. jc args_done
  16.  
  17. // Push the last argument first.
  18. args_loop:
  19. mov eax, DWORD PTR [esi+edx]
  20. push eax
  21. sub edx, 4
  22. jge SHORT args_loop
  23.  
  24. args_done:
  25. call func
  26.  
  27. mov edx, conv
  28. or edx, edx
  29. jnz is_stdcall
  30.  
  31. // pop arguments
  32. mov edx, nwords
  33. shl edx, 2
  34. add esp, edx
  35.  
  36. is_stdcall:
  37. mov esi, resP
  38. mov edx, res_type
  39. dec edx
  40. jge not_p64
  41.  
  42. // p64
  43. mov [esi], eax
  44. mov [esi+4], 0
  45. jmp done
  46.  
  47. not_p64:
  48. dec edx
  49. jge not_i32
  50.  
  51. // i32
  52. mov [esi], eax
  53. jmp done
  54.  
  55. not_i32:
  56. dec edx
  57. jge not_f32
  58.  
  59. // f32
  60. fstp DWORD PTR [esi]
  61. jmp done
  62.  
  63. not_f32:
  64. // f64
  65. fstp QWORD PTR [esi]
  66.  
  67. done:
  68. }
  69. }

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
Reply With Quote Quick reply to this message  
Join Date: Jun 2009
Posts: 830
Reputation: wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all 
Solved Threads: 94
wildgoose's Avatar
wildgoose wildgoose is offline Offline
Practically a Posting Shark

Re: ASM -> C function call problem, pointer issue

 
0
  #2
Jul 28th, 2009
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).
  1. mov esi, args
  2. mov edx, nwords
  3. ;; // word address -> byte address
  4. ;; shl edx, 2
  5. ;; sub edx, 4
  6. ;; jc args_done
  7. test edx,edx
  8. jz args_done
  9.  
  10. // Push the last argument first.
  11. args_loop:
  12. dec edx
  13. ;; mov eax, DWORD PTR [esi+edx]
  14. mov eax, DWORD PTR [esi+edx * 4]
  15. push eax
  16. ; sub edx, 4
  17. ; jge args_loop
  18. 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.
Reply With Quote Quick reply to this message  
Join Date: Jun 2009
Posts: 830
Reputation: wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all 
Solved Threads: 94
wildgoose's Avatar
wildgoose wildgoose is offline Offline
Practically a Posting Shark

Re: ASM -> C function call problem, pointer issue

 
0
  #3
Jul 28th, 2009
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

  1. args_done:
  2. ; ??? Don't we need to push number of arguments, since its variable or zero?
  3. call func
  4.  
  5. ; this doesn't belong??? Args WERE pushed on stack so definitely need to adjust stack!
  6. ; mov edx, conv
  7. ; test edx,edx
  8. ; jnz is_stdcall
  9.  
  10. // pop arguments
  11. mov edx, nwords
  12. shl edx, 2
  13. 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!
  1. is_stdcall:
  2. mov esi, resP ; long pointer
  3.  
  4. ; TY_CPTR = 0,
  5. ; TY_INTEGER,
  6. ; TY_FLOAT,
  7. ; TY_DOUBLE,
  8. ; TY_DOUBLE2,
  9. ; TY_STRING
  10.  
  11. ;;; You could put a jump vector table
  12.  
  13. ; Note: eax contains result of function call!
  14.  
  15. mov edx, res_type ; resource type?
  16. jmp Near Ptr FuncTbl[ edx * 4 ]
  17.  
  18. FuncTbl:: dw offset FuncPtr
  19. dw offset FuncInt
  20. dw offset FuncFlt32
  21. dw offset FuncDbl
  22. dw offset FuncDbl2
  23. dw offset FuncStr
  24.  
  25.  
  26. FuncCptr:
  27. mov [esi], eax
  28. mov [esi+4], 0
  29. jmp done
  30.  
  31. FuncInt:
  32. mov [esi], eax
  33. jmp done
  34.  
  35. FuncFlt32:
  36. FuncDbl:
  37. FuncDbl2:
  38. fstp DWORD PTR [esi]
  39. jmp done
  40.  
  41. FuncStr:
  42. jmp done;
  43.  
  44. done:
  45. }
Last edited by wildgoose; Jul 28th, 2009 at 3:12 pm.
Reply With Quote Quick reply to this message  
Join Date: Jul 2009
Posts: 4
Reputation: JasonL220 is an unknown quantity at this point 
Solved Threads: 0
JasonL220 JasonL220 is offline Offline
Newbie Poster

Re: ASM -> C function call problem, pointer issue

 
0
  #4
Jul 29th, 2009
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.

  1. void asm_dispatch(void *func,
  2. int nwords,
  3. char *arg_types,
  4. long *args,
  5. int res_type,
  6. long *resP,
  7. int conv)
  8. {
  9. __asm {
  10. mov esi, args
  11. mov edx, nwords
  12. test edx, edx
  13. jz args_done
  14.  
  15. // Push the last argument first.
  16. args_loop:
  17. dec edx
  18. mov eax, DWORD PTR [esi+(edx * 4)]
  19. push eax
  20. jnz args_loop
  21.  
  22. args_done:
  23. call func
  24.  
  25. // pop arguments
  26. mov edx, nwords
  27. shl edx, 2
  28. add esp, edx
  29.  
  30. is_stdcall:
  31. mov esi, resP
  32. mov edx, res_type
  33. dec edx
  34. jge not_p64
  35.  
  36. // p64
  37. mov [esi], eax
  38. mov [esi+4], 0
  39. jmp done
  40.  
  41. not_p64:
  42. dec edx
  43. jge not_i32
  44.  
  45. // i32
  46. mov [esi], eax
  47. jmp done
  48.  
  49. not_i32:
  50. dec edx
  51. jge not_f32
  52.  
  53. // f32
  54. fstp DWORD PTR [esi]
  55. jmp done
  56.  
  57. not_f32:
  58. // f64
  59. fstp QWORD PTR [esi]
  60.  
  61. done:
  62. }
  63. }

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.
Reply With Quote Quick reply to this message  
Join Date: Jul 2009
Posts: 4
Reputation: JasonL220 is an unknown quantity at this point 
Solved Threads: 0
JasonL220 JasonL220 is offline Offline
Newbie Poster

Re: ASM -> C function call problem, pointer issue

 
0
  #5
Jul 29th, 2009
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include "tdapi.h"
  4.  
  5. #ifdef WIN32
  6. #include <windows.h>
  7. #define LOAD_LIBRARY(name) LoadLibrary(name)
  8. #define FIND_ENTRY(lib, name) GetProcAddress(lib, name)
  9. #endif
  10.  
  11. /* These are the set of types CFunction can handle now */
  12. typedef enum
  13. {
  14. TY_CPTR = 0,
  15. TY_INTEGER,
  16. TY_FLOAT,
  17. TY_DOUBLE,
  18. TY_DOUBLE2,
  19. TY_STRING
  20. } ty_t;
  21.  
  22. /* represent a machine word */
  23. typedef union
  24. {
  25. int i;
  26. float f;
  27. void* p;
  28. } word_t;
  29.  
  30. void asm_dispatch(void *func,
  31. int nwords,
  32. char *arg_types,
  33. long *args,
  34. int res_type,
  35. long *resP,
  36. int conv)
  37. {
  1. __asm {
  2. mov esi, args
  3. mov edx, nwords
  4. test edx, edx
  5. jz args_done
  6.  
  7. // Push the last argument first.
  8. args_loop:
  9. dec edx
  10. mov eax, DWORD PTR [esi+(edx * 4)]
  11. push eax
  12. jnz args_loop
  13.  
  14. args_done:
  15. call func
  16.  
  17. // pop arguments
  18. mov edx, nwords
  19. shl edx, 2
  20. add esp, edx
  21.  
  22. is_stdcall:
  23. mov esi, resP
  24. mov edx, res_type
  25. dec edx
  26. jge not_p64
  27.  
  28. // p64
  29. mov [esi], eax
  30. mov [esi+4], 0
  31. jmp done
  32.  
  33. not_p64:
  34. dec edx
  35. jge not_i32
  36.  
  37. // i32
  38. mov [esi], eax
  39. jmp done
  40.  
  41. not_i32:
  42. dec edx
  43. jge not_f32
  44.  
  45. // f32
  46. fstp DWORD PTR [esi]
  47. jmp done
  48.  
  49. not_f32:
  50. // f64
  51. fstp QWORD PTR [esi]
  52.  
  53. done:
  54. }
  55. }

  1. int main( int argc, char* argv[] )
  2. {
  3. #define MAX_NARGS 32
  4. #define NUM_CARDS 8
  5. /* card states */
  6. #define CARD_NIU 0
  7. #define CARD_REQUIRED 1
  8. #define CARD_PRESENT 2
  9.  
  10. #define NUM_SS7_TRUNKS 16
  11. #define NUM_SS7_LINKS 2
  12. #define NUM_TIMESLOTS 32
  13. typedef int (*FNPTR)(int);
  14. typedef void (*FNPTR2)(char*);
  15.  
  16. int nargs = 2;
  17. int nwords = 1;
  18. void *func;
  19. FNPTR InitM;
  20. FNPTR2 SetHost;
  21. char argTypes[MAX_NARGS];
  22. word_t c_args[MAX_NARGS * 2];
  23. int conv;
  24. long pointer = 10;
  25. long result = 0;
  26. HMODULE hDLL;
  27. int stat;
  28. int cardState[NUM_CARDS];
  29.  
  30. if( ( hDLL = LoadLibrary("C:\\ngntdapi.dll")) == NULL )
  31. {
  32. printf ("LoadLibrary failed\n");
  33. return 1;
  34. }
  35.  
  36. func = GetProcAddress( hDLL, "TDapi_GetServiceProvider" );
  37. InitM = (FNPTR)GetProcAddress( hDLL, "TDapi_InitM" );
  38. SetHost = (FNPTR2)GetProcAddress( hDLL, "TDapi_SetHost" );
  39.  
  40. for(int i=0; i<NUM_CARDS; i++)
  41. {
  42. cardState[i] = CARD_NIU;
  43. }
  44.  
  45. if( ( stat = InitM(4000)) != TDAPI_SUCCESS )
  46. {
  47. printf("TDapi_Init() failed, status %d", stat);
  48. return 1;
  49. }
  50.  
  51. if(argc > 1)
  52. {
  53. SetHost(argv[1]);
  54. }
  55.  
  56. c_args[0].p = &pointer;
  57. argTypes[0] = TY_CPTR;
  58.  
  59. c_args[1].p = "maint";
  60. argTypes[1] = TY_STRING;
  61.  
  62. printf("pointer before asm: %p\n", c_args[0].p);
  63. printf("string pointer before asm: %p\n", (char *)c_args[1].p);
  64. printf("string before asm: %s\n", (char *)c_args[1].p);
  65.  
  66. asm_dispatch(func, 2, argTypes, (long*)c_args, TY_INTEGER, (long*)result, 0);
  67. return 0;
  68. }

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.
Reply With Quote Quick reply to this message  
Join Date: Jun 2009
Posts: 830
Reputation: wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all 
Solved Threads: 94
wildgoose's Avatar
wildgoose wildgoose is offline Offline
Practically a Posting Shark

Re: ASM -> C function call problem, pointer issue

 
0
  #6
Jul 29th, 2009
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...
  1. mov edx,nwords
  2. shl edx,1
  3. dec edx
Reply With Quote Quick reply to this message  
Join Date: Jun 2009
Posts: 830
Reputation: wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all wildgoose is a name known to all 
Solved Threads: 94
wildgoose's Avatar
wildgoose wildgoose is offline Offline
Practically a Posting Shark

Re: ASM -> C function call problem, pointer issue

 
0
  #7
Jul 29th, 2009
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!
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



Tag cloud for Assembly
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC