ASM ReverseThe power of assembler |
Using assembler with Java projectsContents
IntroХотя это случается редко, но все же иногда может понадобиться вызвать подпрограмму, написанную на языке, отличном от Java. Например, нужно вывести результат типа double в бинарном виде, да еще и в расширенном вещественном типе, т.е. 80 разрядов, с которым может работать FPU. Так как Java ограничен в работе бинарных операций с определенными типами данных, приходиться воспользоваться native методом. Обычно такая подпрограмма существует в виде исполняемого кода для CPU и среды, в которой вы работаете, то есть в виде родного (native) кода. Например, вы можете решить вызвать такую подпрограмму для достижения более высокой скорости выполнения. Или же вам может понадобиться работать со специализированной библиотекой от независимых поставщиков. Jаvа программы компилируются в байткод, который затем интерпретируется(или компилируется "на лету") исполняющей системой Java. В Java предусмотрено ключевое слово native, которое используется для объявления родных методов. Однажды объя- вленные, эти методы могут быть вызваны из вашей Jаvа программы точно так же, как вызываются любой другой метод Java.Return to top page Declare the Native MethodЧтобы объявить родной метод, предварите eгo имя модификатором native, но не определяйте тело метода. Например: public native void enc(); Напишем короткую программу, которая использует native-метод: public class NativeAsm { double i; public static void main(String[] args) { NativeAsm ob = new NativeAsm(); ob.i = -80.5; System.out.println("Its ob.i in decimal view : " + ob.i); System.out.println("Its ob.i after native metod in binary" + " view / eqv : REAL10 | TBYTE / : "); ob.enc(); } public native void enc(); static { System.loadLibrary("NativeAsm"); } }Return to top page Create the Native Method Header FileПосле ввода текста прогpаммы скомпилируйте ее, чтобы получить NativeAsm.class Далее вы должны использовать javah.ехе, чтобы сгенерировать один заголовочный файл: NativeAsm.h( javah.exe включена в JDK ). Вы включите NativeAsm.h в свою реализацию enc(). Чтобы получить NativeAsm.h, выполните следующую команду: javah -jni NativeAsm Эта команда сгенерирует файл по имени NativeAsm.h. Этот файл должен быть включен в cpp-project, реализующий метод enc(). Вывод, сгенерированный этой командой, показан ниже: /* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class NativeAsm */ #ifndef _Included_NativeAsm #define _Included_NativeAsm #ifdef __cplusplus extern "C" { #endif /* * Class: NativeAsm * Method: enc * Signature: ()V */ JNIEXPORT void JNICALL Java_NativeAsm_enc (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endifReturn to top page Realized native metodЗаголовочный файл содержит подключение "jni.h", который в свою очередь подключает "jni_md.h", а сами находятся в директории Java JDK: C:\Program Files\Java\jdk1.6.0_1x\include\win32 скопируйте их в свою папку проекта, рядом с исходниками. После генерации необходимого заголовочного файла можно написать свою реализацию метода, в нашем случае enc() и сохранить ее в файле NativeAsm.cpp (типы данных смотрим в официальной документации): #include "NativeAsm.h" #include <math.h> #include <iostream> using namespace std; JNIEXPORT void JNICALL Java_NativeAsm_enc(JNIEnv *env, jobject obj) { jclass cls; jfieldID fid; jdouble i; cout << "start native metod" << endl; cls = (*env).GetObjectClass(obj); fid = (*env).GetFieldID(cls, "i", "D"); if(fid == 0) { cout << "ERROR... dont get field id" << endl; return; } i = (*env).GetDoubleField(obj, fid); long double man; short int exp,n; __asm fld i __asm fxtract /*...stores the exponent in ST(0), ST(1) register contains the value of the original operand’s true (unbiased) exponent expressed as a real number.*/ /*...выделяет из числа, находящегося в вершине стека ST(0), порядок (exponent) и мантиссу (mantissa, significand). При этом значение порядка помещается в регистр ST(1), а мантисса — в регистр ST(0)...*/ __asm fstp man __asm fistp exp cout << i << " -> " << man << " " << exp << endl; if(man < 0) { cout << "1 "; man = fabs(man); } exp += 16383; __asm mov bx,exp for(register int k=0; k<16; k++) { __asm { mov ax,bx rol ax,1 and ax,1 mov n,ax rol bx,1 } if(k != 0) cout << n; } cout << " "; for(register int k=0; k<64; k++) { if(man >= 1) { cout << "1"; man--; } else cout << "0"; man *= 2; } cout << endl << "end native metod" << endl; }Return to top page DLLКомпилируем проект для получения DLL библиотеки. Забираем DDL-ку и кидаем в Java project / на скриншоте будет видно /, делаем Java Runnable JAR или запускаем непосредственно в IDE и смотрим результат.Return to top page Check result![]() Для проверки результата можно откомпилировать asm файл с файлом листинга и сравнить результат / сделал для наглядности для всех типов данных поддер- живаемых FPU, со знаком и без /: Microsoft (R) Macro Assembler Version 9.00.30729.01 01/03/10 20:51:51 asm1.asm Page 1 - 1 .686 .model flat,stdcall 00000000 .data ; old & new style type ; real number in the memory size of 32 bits 00000000 42A10000 DD 80.5 00000004 C2A10000 DD -80.5 00000008 42A10000 DWORD 80.5 0000000C C2A10000 DWORD -80.5 00000010 42A10000 SDWORD 80.5 00000014 C2A10000 SDWORD -80.5 00000018 42A10000 REAL4 80.5 ; IEEE 0000001C C2A10000 REAL4 -80.5 ; IEEE ; real number in the memory size of 64 bits 00000020 4054200000000000 DQ 80.5 00000028 C054200000000000 DQ -80.5 00000030 4054200000000000 QWORD 80.5 00000038 C054200000000000 QWORD -80.5 00000040 4054200000000000 REAL8 80.5 ; IEEE 00000048 C054200000000000 REAL8 -80.5 ; IEEE ; real number in the memory size of 80 bits 00000050 4005A100000000000000 DT 80.5 0000005A C005A100000000000000 DT -80.5 00000064 4005A100000000000000 TBYTE 80.5 0000006E C005A100000000000000 TBYTE -80.5 00000078 4005A100000000000000 REAL10 80.5 ; IEEE 00000082 C005A100000000000000 REAL10 -80.5 ; IEEE 00000000 .code 00000000 _start: 00000000 C3 ret end _start Microsoft (R) Macro Assembler Version 9.00.30729.01 01/03/10 20:51:51 asm1.asm Symbols 2 - 1 Segments and Groups: N a m e Size Length Align Combine Class FLAT . . . . . . . . . . . . . . GROUP _DATA . . . . . . . . . . . . . 32 Bit 0000008C Para Public 'DATA' _TEXT . . . . . . . . . . . . . 32 Bit 00000001 Para Public 'CODE' Symbols: N a m e Type Value Attr @CodeSize . . . . . . . . . . . Number 00000000h @DataSize . . . . . . . . . . . Number 00000000h @Interface . . . . . . . . . . . Number 00000003h @Model . . . . . . . . . . . . . Number 00000007h @code . . . . . . . . . . . . . Text _TEXT @data . . . . . . . . . . . . . Text FLAT @fardata? . . . . . . . . . . . Text FLAT @fardata . . . . . . . . . . . . Text FLAT @stack . . . . . . . . . . . . . Text FLAT _start . . . . . . . . . . . . . L Near 00000000 _TEXT Public STDCALL 0 Warnings 0 ErrorsReturn to top page TotalИспользуя необходимую документацию, можно написать native метод на чистом assemblere, а также и на других языках.Return to top page DocumentationOfficial documentation : http://java.sun.com/docs/books/jni/Return to top page Return to Source Code page |