ASM with JAVA

ASM Reverse

The power of assembler



Using assembler with Java projects

Contents

Return to Source Code page

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
#endif
Return 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

ja

    Для проверки результата можно откомпилировать 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 Errors
	   
Return to top page

Total

    Используя необходимую документацию, можно написать native метод на чистом
assemblere, а также и на других языках.
Return to top page

Documentation

Official documentation : http://java.sun.com/docs/books/jni/
Return to top page

Return to Source Code page