Making use of Java with the BCB 4.0 CPU feature detectors author: Wang Sen Taiwan Jiaotong University Institute of Technology Management moli.mt88g@nctu.edu.tw Note: This also applies Borland C Builder 5.0█ I recently engaged in a foreword to use Java The development of the password module is not good because the password module created by the pure Java language is not good. Finally, we will move the brain to JNI (Java Native Interface). Why think of using JNI? Everyone should know the Java program Execution must pass Java Virtual Machine, through the results of a layer of intermediary, the efficiency of the execution is inevitably compared to the original code compiled by C / C (Native Code, the exclusive command set of the exclusive processor) is slow. In fact, In the Java.math attached to JDK, many parts also apply JNI to speed up computational speed (such as Big Integer operations). ■ Hardware advantage Once the JNI is used, the representative we will be able to connect C / C or Assembly Written encryption module. In order to speed up the password module's Performance, you must use some hardware advantages. For example, when processing block encryption operations, if you can use a point of parallel processing, you can properly speed up the computation speed. Take the current For the processor on the PC, the technology that supports parallel processing power is MMX, STREAMING SIMD EXTENSION (you may be more familiar with KNI), and 3DNOW !. These technologies are actually SIMD ( The concept of Single-Instruction, MultiPle-Data allows the processor to use a single directive within the same time. In addition, the CPU above the Pentium level has the ability to speed up the execution speed. As long as the Assembly Code is adjusted, you can make full use of the U-PIPE and V-PIPE in the CPU, speed up the execution speed. In fact, the Visual C 6.0 and Borland C Builder 4.0 used in the author. To put, although there are compiler instructions to make optimization for the processor, if you personally look at the results of the compiled, there can be many places can't help, so if you encounter the part of Time Critical, it is still often Need us to go to adjust the school to improve Performance.█ preparation and precautions OK, tell Here, it seems a bit far away from the theme, let us return to the topic! In order to let us perform the optimization program code in the execution period, the primary work is to write some functions to detect The character of the CPU, so I chose JDK 1.2 and BCB 4.0 to complete the entire test program of Java Code è JNi PLATFORM NATIVA Code è JNi PLATFORM NATIVE CODE. If you are expressed as shown below If you grab the original code provided by the author, you should You can see the following three program modules written by Java and C , respectively:
CPutestDLL.BPR cputestdll.cpp real detects a CPU feature-related function module. This is a project file of BCB 4.0. After using Project / Make CPutest instruction, the result of the result cputest.dll is what we want. Compile attention. Matters:
Since we use the assembly language instruction CPUID in cputestdll.cpp, please open the Advanced Compiler page of Project / Option, and there is a place called Instruction Set. Please check the Pentium, otherwise the compiler will not support this instruction. Generate compilation errors. If you want to use the compiled results to others, it is recommended that you cancel the build with run-time package options in the Project / Option / Package page and the Use Dynamic RTL option in the Linker page. Please open the Project / Option / Directories Conditionals page, add the Directory / INCLUDE of JDK to the include Path in the directory / include / win32; in the library path, you will also add the JDK in the library path, otherwise it will cause compilation errors. CPUTEST.JAVA This Java program is an interface as another Java program to call cputestdll.dll through JNI. The author declares this interface under the package of My.cpu. Compile note: When compiling the Java program, set the environment variable Path Installing ClassPath, such as JDK, installed in C: /JDK1.2, and this file is placed under c: /jdk1.2/my, then please command Path C: /jdk1.2/bin set ClassPath under the prompt symbol. = C: /JDK1.2/Classes; c: /jdk1.2/my test.java This Java program will use the CPUTEST object as an interface to call the CPU feature detection function in CPUTESTDLL.DLL compilation precautions In addition to the precautions for 2, put the cputest.java in the
File list cputest.java / ***************************************************** ******************************************** CPUTEST.JAVAJNI Interface Objects 1999 April 20 by Wang Sen ** *********************************************************** **************************** /// joins my.cpu this package Package my.cpu; public class cputest { / * The following defines the constant representative represented by each processor * / static public final Int i386 = 0; // does not support CPUID processor (identifiable) static public final int pentium = 1; // The earliest Pentium processor (Identification) Static Public Final Int Pentium_m = 2; // Pentium with MMX Processor (Identification) Static Public Final INT Pentium_2 = 3; // Pentium II Processor (Identification) Static Public Final Int Pentium_3 = 4; / / Pentium III processor (identifiable) static public final int pentium_p = 5; // Pentium Pro processor (identifiable) static public final INT K6 = 11; // Tong Pentium with mmx static public final INT K6_2 = 12; / / K6-2 processor ((identifiable) Static public final int k6_3 = 13; // That is the following definition of K6-2 / * All Functions that will be used by JNI * / // test whether CPU supports CPUID instructions If support is returned to True, otherwise, false public native boolean checkcpuid (); ^^^^^^ Note, all JNI functions must be plus Native this modifier // if the JNI is added to the VATIVE. Support MMX, if support Remove True, otherwise, false public native boolean checkmmmx (); // Identify whether the processor supports Stream SIMD EXTENSION (ie, if support is returned, otherwise, false public native boolean checkssimd (); // Identify whether the processor supports AMD 3DNOW, if support is returned back, otherwise returns false public native boolean check3dnow (); // identifies the level of the CPU and passing an integer representing the level of the CPU public native int checkcputype (); / / Print the relevant information of the CPU PUBLIC NATIVE VOID PRINTCPUInfo (); Note: Please call all the functions in front of the previous function, because the DLL file will be set in addition to the authentication. The whole country variables and PRINTCPUInfo uses these all-domain variables to make a determination work. Static {We make the module that implements the CPU detection function into a DLL (dynamic connecting card) file, named cpudtestdll.dll, So here is to load this DLL System.loadLibrary ("cputestdll");}} After using instruction Javac CPutest.java under the prompt symbol, we generate CPUTEST.CLASS files. Then we put these two files Move to
/ Classes / my / cpu / this directory, if this action is not done, I am afraid the following steps will encounter some errors. The last step is to generate an introduction file, we will compile CPUTESTDLL.DLL Practically to this import file. Using instructions under the prompt symbol Javah my.cpu.cputest will see MY_CPU_CPUTEST.H in your current working directory, we have completed the first phase.
Case list my_cpu_CPUTest.h / * DO NOT EDIT THIS FILE - it is machine generated * / # include
#ifdef __cplusplus} # Endif # Endif Attached, the above file is completely generated using Javah JDK, we don't want to modify it, so as not to happen more unexpected trouble. Good end, complete the interface part, then start the real part! First, please open your BCB 4.0 first, select the new page of File / New, select Open a DLL project file. After the success, Ten this project named cputestdll. You will see two files of cputestdll.bpr and cputestdll.cpp in the directory. In addition, in order to make compilation work smoothly, you must adjust some compiler options, please refer to Previous █ Prepare work and precautions. First, please introduce MY_CPU_CPUTEST.H in cputestdll.cpp to introduce the "Undefined Symbol XXXX" error full program code as follows:
Archive list cputestdll.cpp #include
BUILDER When compiled in the program code, the CPUTESTDLL.ASM is generated in the program directory, and the Advanced Compiler of Project / Option has a place called Instruction Set, please check Pentium, otherwise, regardless of the 386 or 486, the compiler will generate the group translation error because of this directive. JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_Check3DNOW (JNIEnv * J, jobject O) {// If you do not support the CPUID instruction, you do not do wrong if (CPUID_S == false) return false in order to avoid going; unsigned long temp; asm mov eax, 80000001h; asm CPUID; ASM MOV TEMP, EDX; // IF (Temp & 0x80000000) {_3DNOW = true; Return True;} / * Test CPU support CPUID Directive * / JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckCPUID (JNIEnv * J, jobject O) {// following procedure is used to test whether the CPU supports the CPUID instruction unsigned int A, B; asm pushfd; asm pop eax; asm mov ebx, eax; asm xor eax, 00200000h; ASM PUSH EAX; ASM PUSHFD; ASM POP EAX; ASM MOV A, EAX; ASM MOV B, EBX; IF (A! = B) { CPUID_S = true; return true;} RETURN FALSE;} / * Identify CPU level * / jniexport jint JNICALL JAVA_MY_CPU_CPUTEST_CHECKCPUTYPE (JNIENV * J, JOBJECT O) {// If you do not support CPUID instructions, you don't have to do it again to avoid error IF. (Cpuid_s == false) Return I386; Unsigned int Temp; ASM MOV EAX, 0; ASM CPUID; ASM MOV TEMP, EAX; if (Temp == 2) // This is the situation of P6 family {CPUTYPE = Pentium_P; // The first processor of the P6 family is Pentium Pro if (SSIMD) // P6 and then supports SSIMD .. must be Pentium III {CPUTYPE = Pentium_3; Return Pentium_3;
} IF (mmx) / / otherwise P6 then supports MMX .. must be Pentium II {cputype = pentium_2; if (_3DNOW) // supports MMX and supports 3D! Now, must be K6-2 {cPUTYPE = K6_2; return k6_2 } Return Pentium_2;} // If there is no more than the above multimedia instruction sets, then it should be Pentium PRO RETURN PENTIUM_P;} if (TEMP == 1) // This is the case of P5 family {CPUTYPE = Pentium; / The first processor of the P5 family is Pentium if (mmx) // P5 and then supports MMX .. must be Pentium with mmx {cputype = pentium_m;} return pentium;} returnix pentium;} Return I386;} / * Identification processor Whether to support mmx * / jniexport jboolean JNICALL JAVA_MY_CPU_CPUTEST_CHECKMMX (JNIENV * J, JOBJECT O) {// If you do not support the CPUID instruction, you don't have to do it again to avoid error IF (CPUID_S == false) Return False; Unsigned Long Temp; ASM MOV Eax, 1; ASM CPUID; ASM MOV TEMP, EDX; // The number of feature values for MMX // ps bit numbers from 0 to 31 IF (Temp & 0x00800000) { MMX = true; return true;} return false;} / * recognition processor supports Stream SIMD Extension (i.e. KNI) * / JNIEXPORT jboolean JNICALL Java_my_cpu_CPUTest_CheckSSIMD (JNIEnv * J, jobject O) {// If not CPUID instruction, Don't do anything to avoid errors if (cpuid_s == false) return false; unsigned long temp; ASM MOV Eax, 1; ASM CPUID; ASM MOV TEMP, EDX;
// The 25th Bit is the characteristic bit / / PS bit number of the PS bit by 0 ~ 31 if (Temp & 0x02000000) {ssimd = true; return true;} Return False;} / * Printing CPU information * / Jniexport void JNICALL JAVA_MY_CPU_CPUTEST_PRINTCPUINFO (JNIENV * J, JOBJECT O) {cout << "... Verify Some Processor Information ..." << Endl; coucessor: "<< end1; if (Mmx) {cout << "Support Intel MMX Technology" << Endl;} else {cout << "No Intel MMX Technology Support" << Endl;} IF (SSIMD) {cout << "Support Intel Streaming SIMD EXTENSITIONS" << Endl;} else {cout << "no intel streaming simd extensions support" << endl;} if (_3d1) {cout << "Support amd 3d! now technology << endl;} else {cout <<" NO AMD 3D! Now Technology Support "<< Endl;} cout << "CPU TYPE:"; Switch (cputype) {Case i386: cout << "General i386 processor" << Endl; Break; Case Pentium: cout << "Intel Pentium Processor << Endl; Break Case Pentium_m: COUT << "Intel Pentium with mmx processor" << Endl; Break; Case Pentium_2: COUT << "Intel Pentium II Processor <<
Endl; Break; Case Pentium_3: COUT << "Intel Pentium III Processor" << Endl; Break; Case Pentium_p: COUT << "Intel Pentium Pro Processor << Endl; Break; Case K6: COUT <<" AMD K6 Processor << Endl; Break; Case K6_2: COUT << "AMD K6 II Processor" << Endl; Break; Case K6_3: Cout << "AMD K6 III Processor" << ".." Verify end ... "<< endl;} int WinApi DLLENTRYPOINT (Hinstance Hinst, unsigned long reason, void *) {return 1;} // ----------------- -------------------------------------------------- -------- Everyone may find that each letter is before returning to the Boolean value first, this is because the efficiency is considered, if readers are interested in expanding the program Let the Java program can call the appropriate function because of the Characteristics of the CPU, once you encounter this situation, you must call the Checkxxxx plurality, ten times, you have to call ten times, quite There is no efficiency, if the refinement of the pen, as long as the call is called once, it will set a national variable of the record CPU feature. Next, you will not have to call Checkxxxx again, and you can access the whole country variable. You can refer to the printcpuinfo letter. Big It is not the reason why you can do this. There is a method of checkcputype. This is not the most formal method. The author just assumes that only AMD and Intel have two vendors on the market. If you want to identify the manufacturer's model We must also use the CPUID to get more information. This is treated as a chance to be exercised by the reader. I believe that as long as the reader is heart, I will find the correct detection method. █ Test finally got to test the correctness of our program, so we wrote Test.java
File list Test.java import my.cpu. *; Class test {/ * The following defines the constant represented by each processor * / static public final Int i386 = 0; // Does not support CPUID processor (identifiable) Static Public final int pentium = 1; // The earliest Pentium processor (identifiable) static public final int pentium_m = 2; // Pentium with MMX processor (identifiable) static public final int pentium_2 = 3; // Pentium II Processor (identifiable) static public final int pince_3 = 4; // Pentium III processor (identifiable) static public final int pentium_p = 5; // Pentium Pro processor (identifiable) static public final INT K6 = 11; // Tong Pentium with MMX Static Public Final Int K6_2 = 12; // K6-2 processor ((identifiable) static public final int k6_3 = 13; // That is starting public static void main in the K6-2 // String args []) {boolean Temp; // gets the JNI interface object cputest my = new cputest (); // Start the initialization of the CPU related information TEMP = my.checkcpuid (); if (temp) {system.out.println ("Cpuid support");} else {system.out.println ("CPUID Not Support"); } Temp = my.checkmmmmmmmx (); if (temp) {system.out.println ("mmx support");} else {system.out.println ("mmx not support");} Temp = my.checkssimd () ; If (temp) {system.out.println ("SSIMD Support");} else {system.out.println ("SSIMD Not Support");} temp = my.check3dnow (); if (temp) {system. Out.println ("3DNOW Support");} else {system.out.println ("3DNOW Not Support");} system.out.println ("
"); System.out.println (" ------- Starting Java Code Print -------- "); Switch (my.checkcputype ()) {Case i386: System.out. Println ("I386"); Break; Case Pentium: System.out.Println ("Pentium"); Break; Case Pentium_M: System.out.Println; Break; Case Pentium_2: System.out. Println ("Pentium II"); Break; Case Pentium_3: System.Out.println ("Pentium III"); Break; Case Pentium_p: System.out.Println ("Pentium Pro"); Break; Case K6: System.out .println ("k6"); Break; Case K6_2: System.out.Println ("K6-2"); Break; Case K6_3: System.out.Println ("K6-3"); Break;} system.out .println (""); system.out. Println ("------- Starting Native Code Print --------"); my.printcpuinfo ();} // end of main} // End of class hits under the command Enter Javac Test.java, you can generate Test.class files. Please play Java Test to execute the program, but you will first encounter the following error message: c: /jdk1.2/my> Java testException in thread "main" java.lang.UnsatisfiedLinkError: no CPUTestDll in java.library.pathat java.lang.ClassLoader.loadLibrary (Compiled Code) at java.lang.Runtime.loadLibrary0 (Runtime.java:470) at java.lang.System. LoadLibrary (System.java: 745) at my.cpu.cputest.