Java + ассемблер

Сначала думал написать тут короткую заметку про то, как подружить Java и ассемблер, но потом решил написать об этом пост на Хабре, и не зря — получил инвайт.
Статья: http://habrahabr.ru/post/145804/

В общем, этим я занимался вчера, а сегодня я успел сделать еще кое-что, на еще один пост на Хабре не тянет, так что напишу здесь. Для понимания того, что я делаю, рекомендуется прочесть эту статью.

Если хочется написать что-то сложнее суммы двух чисел, то неизбежно придется работать с массивами, строками и прочими объектами. Массив в Java выглядит посложнее, чем в C++, поэтому на ассемблере нельзя обратиться к его элементам, просто разыменовав переданный указатель. Для этого необходимо воспользоваться некоторой функцией из таблицы по адресу **JNIEnv. Но вот беда: в C++ можно просто обратиться к соответствующему полю данной структуры по имени, а в ассемблере так сделать не получится, нужно знать адрес интересующей нас функции.

Вот так это можно сделать, зная некий «номер» функции в таблице:

mov ebx, JNIEnv
mov eax, [ebx]
mov ebx, eax    ; save pointer to function table
mov eax, index  ; move the value of index into eax
mov ecx, 4
mul ecx         ; multiply index by 4
add ebx, eax    ; ebx points to the desired entry
mov eax, [ebx]  ; eax points to the desired function

Замечательно, но как узнать этот номер? Можно порыться в книге Sheng Liang по JNI и откопать ~100 страниц всевозможных табличек, но это не очень удобно. Я открыл файл jni.h из JDK и после некоторого изучения структуры JNIEnv_, описанной там, получил номера функций. Все очень просто, они идут в том порядке, в котором объявлены в JNIEnv, с некоторым смещением (первые 16 байтов для структуры, похоже, заняты под служебную информацию). Судя по таблицам из книжки и проверочным вызовам некоторых функций, информация корректна.

Вот они:

/*   4 */ jint GetVersion();
/*   5 */ jclass DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len);
/*   6 */ jclass FindClass(const char *name);
/*   7 */ jmethodID FromReflectedMethod(jobject method);
/*   8 */ jfieldID FromReflectedField(jobject field);
/*   9 */ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic);
/*  10 */ jclass GetSuperclass(jclass sub);
/*  11 */ jboolean IsAssignableFrom(jclass sub, jclass sup);
/*  12 */ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic);
/*  13 */ jint Throw(jthrowable obj);
/*  14 */ jint ThrowNew(jclass clazz, const char *msg);
/*  15 */ jthrowable ExceptionOccurred();
/*  16 */ void ExceptionDescribe();
/*  17 */ void ExceptionClear();
/*  18 */ void FatalError(const char *msg);
/*  19 */ jint PushLocalFrame(jint capacity);
/*  20 */ jobject PopLocalFrame(jobject result);
/*  21 */ jobject NewGlobalRef(jobject lobj);
/*  22 */ void DeleteGlobalRef(jobject gref);
/*  23 */ void DeleteLocalRef(jobject obj);
/*  24 */ jboolean IsSameObject(jobject obj1, jobject obj2);
/*  25 */ jobject NewLocalRef(jobject ref);
/*  26 */ jint EnsureLocalCapacity(jint capacity);
/*  27 */ jobject AllocObject(jclass clazz);
/*  28 */ jobject NewObject(jclass clazz, jmethodID methodID, ...);
/*  29 */ jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args);
/*  30 */ jobject NewObjectA(jclass clazz, jmethodID methodID, const jvalue *args);
/*  31 */ jclass GetObjectClass(jobject obj);
/*  32 */ jboolean IsInstanceOf(jobject obj, jclass clazz);
/*  33 */ jmethodID GetMethodID(jclass clazz, const char *name, const char *sig);
/*  34 */ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...);
/*  35 */ jobject CallObjectMethodV(jobject obj, jmethodID methodID, va_list args);
/*  36 */ jobject CallObjectMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  37 */ jboolean CallBooleanMethod(jobject obj, jmethodID methodID, ...);
/*  38 */ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args);
/*  39 */ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  40 */ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...);
/*  41 */ jbyte CallByteMethodV(jobject obj, jmethodID methodID, va_list args);
/*  42 */ jbyte CallByteMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  43 */ jchar CallCharMethod(jobject obj, jmethodID methodID, ...);
/*  44 */ jchar CallCharMethodV(jobject obj, jmethodID methodID, va_list args);
/*  45 */ jchar CallCharMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  46 */ jshort CallShortMethod(jobject obj, jmethodID methodID, ...);
/*  47 */ jshort CallShortMethodV(jobject obj, jmethodID methodID, va_list args);
/*  48 */ jshort CallShortMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  49 */ jint CallIntMethod(jobject obj, jmethodID methodID, ...);
/*  50 */ jint CallIntMethodV(jobject obj, jmethodID methodID, va_list args);
/*  51 */ jint CallIntMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  52 */ jlong CallLongMethod(jobject obj, jmethodID methodID, ...);
/*  53 */ jlong CallLongMethodV(jobject obj, jmethodID methodID, va_list args);
/*  54 */ jlong CallLongMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  55 */ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...);
/*  56 */ jfloat CallFloatMethodV(jobject obj, jmethodID methodID, va_list args);
/*  57 */ jfloat CallFloatMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  58 */ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...);
/*  59 */ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args);
/*  60 */ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  61 */ void CallVoidMethod(jobject obj, jmethodID methodID, ...);
/*  62 */ void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args);
/*  63 */ void CallVoidMethodA(jobject obj, jmethodID methodID, const jvalue * args);
/*  64 */ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  65 */ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  66 */ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  67 */ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  68 */ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  69 */ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  70 */ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  71 */ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  72 */ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  73 */ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  74 */ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  75 */ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  76 */ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  77 */ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  78 */ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  79 */ jint CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  80 */ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  81 */ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  82 */ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  83 */ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  84 */ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  85 */ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  86 */ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  87 */ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  88 */ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  89 */ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  90 */ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  91 */ void CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
/*  92 */ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
/*  93 */ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue * args);
/*  94 */ jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);
/*  95 */ jobject GetObjectField(jobject obj, jfieldID fieldID);
/*  96 */ jboolean GetBooleanField(jobject obj, jfieldID fieldID);
/*  97 */ jbyte GetByteField(jobject obj, jfieldID fieldID);
/*  98 */ jchar GetCharField(jobject obj, jfieldID fieldID);
/*  99 */ jshort GetShortField(jobject obj, jfieldID fieldID);
/* 100 */ jint GetIntField(jobject obj, jfieldID fieldID);
/* 101 */ jlong GetLongField(jobject obj, jfieldID fieldID);
/* 102 */ jfloat GetFloatField(jobject obj, jfieldID fieldID);
/* 103 */ jdouble GetDoubleField(jobject obj, jfieldID fieldID);
/* 104 */ void SetObjectField(jobject obj, jfieldID fieldID, jobject val);
/* 105 */ void SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
/* 106 */ void SetByteField(jobject obj, jfieldID fieldID, jbyte val);
/* 107 */ void SetCharField(jobject obj, jfieldID fieldID, jchar val);
/* 108 */ void SetShortField(jobject obj, jfieldID fieldID, jshort val);
/* 109 */ void SetIntField(jobject obj, jfieldID fieldID, jint val);
/* 110 */ void SetLongField(jobject obj, jfieldID fieldID, jlong val);
/* 111 */ void SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
/* 112 */ void SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
/* 113 */ jmethodID GetStaticMethodID(jclass clazz, const char *name, const char *sig);
/* 114 */ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...);
/* 115 */ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 116 */ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 117 */ jboolean CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...);
/* 118 */ jboolean CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 119 */ jboolean CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 120 */ jbyte CallStaticByteMethod(jclass clazz, jmethodID methodID, ...);
/* 121 */ jbyte CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 122 */ jbyte CallStaticByteMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 123 */ jchar CallStaticCharMethod(jclass clazz, jmethodID methodID, ...);
/* 124 */ jchar CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 125 */ jchar CallStaticCharMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 126 */ jshort CallStaticShortMethod(jclass clazz, jmethodID methodID, ...);
/* 127 */ jshort CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 128 */ jshort CallStaticShortMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 129 */ jint CallStaticIntMethod(jclass clazz, jmethodID methodID, ...);
/* 130 */ jint CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 131 */ jint CallStaticIntMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 132 */ jlong CallStaticLongMethod(jclass clazz, jmethodID methodID, ...);
/* 133 */ jlong CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 134 */ jlong CallStaticLongMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 135 */ jfloat CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...);
/* 136 */ jfloat CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 137 */ jfloat CallStaticFloatMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 138 */ jdouble CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...);
/* 139 */ jdouble CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args);
/* 140 */ jdouble CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, const jvalue *args);
/* 141 */ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...);
/* 142 */ void CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args);
/* 143 */ void CallStaticVoidMethodA(jclass cls, jmethodID methodID, const jvalue * args);
/* 144 */ jfieldID GetStaticFieldID(jclass clazz, const char *name, const char *sig);
/* 145 */ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID);
/* 146 */ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID);
/* 147 */ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID);
/* 148 */ jchar GetStaticCharField(jclass clazz, jfieldID fieldID);
/* 149 */ jshort GetStaticShortField(jclass clazz, jfieldID fieldID);
/* 150 */ jint GetStaticIntField(jclass clazz, jfieldID fieldID);
/* 151 */ jlong GetStaticLongField(jclass clazz, jfieldID fieldID);
/* 152 */ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID);
/* 153 */ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID);
/* 154 */ void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject value);
/* 155 */ void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean value);
/* 156 */ void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte value);
/* 157 */ void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar value);
/* 158 */ void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort value);
/* 159 */ void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value);
/* 160 */ void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong value);
/* 161 */ void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat value);
/* 162 */ void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble value);
/* 163 */ jstring NewString(const jchar *unicode, jsize len);
/* 164 */ jsize GetStringLength(jstring str);
/* 165 */ const jchar *GetStringChars(jstring str, jboolean *isCopy);
/* 166 */ void ReleaseStringChars(jstring str, const jchar *chars);
/* 167 */ jstring NewStringUTF(const char *utf);
/* 168 */ jsize GetStringUTFLength(jstring str);
/* 169 */ const char* GetStringUTFChars(jstring str, jboolean *isCopy);
/* 170 */ void ReleaseStringUTFChars(jstring str, const char* chars);
/* 171 */ jsize GetArrayLength(jarray array);
/* 172 */ jobjectArray NewObjectArray(jsize len, jclass clazz, jobject init);
/* 173 */ jobject GetObjectArrayElement(jobjectArray array, jsize index);
/* 174 */ void SetObjectArrayElement(jobjectArray array, jsize index, jobject val);
/* 175 */ jbooleanArray NewBooleanArray(jsize len);
/* 176 */ jbyteArray NewByteArray(jsize len);
/* 177 */ jcharArray NewCharArray(jsize len);
/* 178 */ jshortArray NewShortArray(jsize len);
/* 179 */ jintArray NewIntArray(jsize len);
/* 180 */ jlongArray NewLongArray(jsize len);
/* 181 */ jfloatArray NewFloatArray(jsize len);
/* 182 */ jdoubleArray NewDoubleArray(jsize len);
/* 183 */ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy);
/* 184 */ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy);
/* 185 */ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy);
/* 186 */ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy);
/* 187 */ jint * GetIntArrayElements(jintArray array, jboolean *isCopy);
/* 188 */ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy);
/* 189 */ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy);
/* 190 */ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy);
/* 191 */ void ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode);
/* 192 */ void ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode);
/* 193 */ void ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode);
/* 194 */ void ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode);
/* 195 */ void ReleaseIntArrayElements(jintArray array, jint *elems, jint mode);
/* 196 */ void ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode);
/* 197 */ void ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode);
/* 198 */ void ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode);
/* 199 */ void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, jboolean *buf);
/* 200 */ void GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
/* 201 */ void GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
/* 202 */ void GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
/* 203 */ void GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
/* 204 */ void GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
/* 205 */ void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
/* 206 */ void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
/* 207 */ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, const jboolean *buf);
/* 208 */ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, const jbyte *buf);
/* 209 */ void SetCharArrayRegion(jcharArray array, jsize start, jsize len, const jchar *buf);
/* 210 */ void SetShortArrayRegion(jshortArray array, jsize start, jsize len, const jshort *buf);
/* 211 */ void SetIntArrayRegion(jintArray array, jsize start, jsize len, const jint *buf);
/* 212 */ void SetLongArrayRegion(jlongArray array, jsize start, jsize len, const jlong *buf);
/* 213 */ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, const jfloat *buf);
/* 214 */ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, const jdouble *buf);
/* 215 */ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);
/* 216 */ jint UnregisterNatives(jclass clazz);
/* 217 */ jint MonitorEnter(jobject obj);
/* 218 */ jint MonitorExit(jobject obj);
/* 219 */ jint GetJavaVM(JavaVM **vm);
/* 220 */ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf);
/* 221 */ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf);
/* 222 */ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy);
/* 223 */ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode);
/* 224 */ const jchar * GetStringCritical(jstring string, jboolean *isCopy);
/* 225 */ void ReleaseStringCritical(jstring string, const jchar *cstring);
/* 226 */ jweak NewWeakGlobalRef(jobject obj);
/* 227 */ void DeleteWeakGlobalRef(jweak ref);
/* 228 */ jboolean ExceptionCheck();
/* 229 */ jobject NewDirectByteBuffer(void* address, jlong capacity);
/* 230 */ void* GetDirectBufferAddress(jobject buf);
/* 231 */ jlong GetDirectBufferCapacity(jobject buf);
/* 232 */ jobjectRefType GetObjectRefType(jobject obj);
Реклама


Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s