--------------------------------------------------------------------------- Jacques Philippe April 2002 HOWTO Include ASM routines in RapidQ using NASM and API CallWindowProc --------------------------------------------------------------------------- First of all, a special thank to Pavel Minayev -aka evilone666- who opened this road with Vector.Asm and Crc32.Asm. See Crc32.Zip and Rqasm.Zip in RapidQ YahooGroups files section INTRODUCTION ------------ - All the examples are ready for a NASM installation in c:\Nasm, otherwise, you'll have to modify some directories. - All the executable files are "TINY", to run them, you must copy your RAPIDQCC.DLL and RAPIDQ32.DLL in your Windows directory (c:\Windows\) - NASM, the 32 bits ASM compiler, is free. It's syntaxe is slightly different from other Assemblers ; this can be confusing. - Related Sites (I am new to NASM, so there may be better sites) Home http://nasm.sourceforge.net/wakka.php?wakka=HomePage http://sourceforge.net/projects/nasm ??????? http://nasm.octium.net/ download http://www.web-sites.co.uk/nasm/where.html GUI http://www.phoenix.gb.net/x86/ - Pavel's method loads a proc.bin as a resource at compile time and at run time moves that resource to a QMemoryStream then uses the property QMemoryStream.Pointer to point the procedure in API CallWindowProc. - it's possible to directly load the proc.bin in a String or an Array and use the VarPtr(String) or VarPtr(Array(0)) to point the procedure in API CallWindowProc. The softwares BinToInc and BinToInc_Plus in /Bin_To_Inc/ do that (the name BinTonInc was choosen for Binary to RapidQ Include file). So, a single and simple file Included in the RapidQ code will give access to ASM procedures. NASM_SHELL_0, NASM_SHELL_1, NASM_SHELL_2 in dir \NASM_Shell\ ---------------------------------------- Are NASM Shells to write Assembler routines called by Api CallWindowProc in RapidQ - use NASM_SHELL_2 - see NASM_SHELL_0 and NASM_SHELL_1 for a very basic tutorial COMPILETOBIN.BAT in Directory \NASM_Compile\ ---------------- Compiles a NASM source to a BIN file - the line "set fich=GetByteAt" must be adapted to the filename of the NASM source you want to compile - the path to Nasmw.exe, the NASM compiler, must be adapted to your directories - CompileToBin.Bat must be in the directory of the NASM source code file you want to compile - the compiled .BIN file will be created in the same directory as CompileToBin.Bat BINTOINC.EXE in direcrtory \Bin_To_Inc\ ------------ Creates a RapidQ code file containing the BIN file in an Array. The name of the .BIN file is used to create a function and a pointer to that array. Just run BinToInc.Exe, then use menu File/Open to select a .Bin file. As Soon as a .Bin file is selected, a RapidQ code is generated on the screen ; save that code in an .Inc file using menu File/Save. The Option menu allows you to Include the "CallAsmProc API" declaration to the RapidQ code or not ; it's usefull if you include many asm .Inc files in you software... Demo : Run BinToInc.Exe in \Bin_To_Inc\, then File/Open \Bin_To_Inc\Demo\ReverseString.Bin, once selected, the screen fills with A RapidQ Code. Save It as \Bin_To_Inc\Demo\ReverseString.Inc Now, you should be able to RQ Compile \Bin_To_Inc\Demo\ReverseStringDemo_2.Bas Here is the kind of file created by BinToInc.Exe with an ASM .Bin file ' Begin of File ReverseString.Inc cut and pasted ' DECLARE FUNCTION CallAsmProc LIB "user32" ALIAS "CallWindowProcA" _ (Proc AS LONG, A1 AS LONG, A2 AS LONG, A3 AS LONG, _ A4 AS LONG) AS LONG ' ' ============================================================ ' ----- START ASM ReverseString ----- DefByte ReverseStringArray (0 To 60) = _ { _ &HC8, &H00, &H00, &H00, &H51, &H56, &H57, &H8B, &H7D, &H0C, _ &H8B, &H75, &H08, &HB8, &H00, &H00, &H00, &H00, &HB9, &H00, _ &H01, &H00, &H00, &HFC, &HA4, &H40, &H80, &H3E, &H00, &H0F, _ &H84, &H02, &H00, &H00, &H00, &HE0, &HF2, &H8B, &H75, &H0C, _ &H01, &HC6, &H4E, &H8B, &H7D, &H08, &H89, &HC1, &HFC, &HA4, _ &H4E, &H4E, &HE0, &HFA, &H5F, &H5E, &H59, &HC9, &HC2, &H10, _ &H00 _ } ' ----- END ASM ReverseString ----- ' ' ----- POINTER to use In CallAsmProc ----- ' A Bit Faster than Calling ReverseString DefInt ptrReverseString ptrReverseString = VarPtr (ReverseStringArray(0)) ' ' ----- RQ CALL ReverseString ----- Function ReverseString (Arg1 As Long, Arg2 As Long, Arg3 As Long, _ Arg4 As Long) as Long Result = CallAsmProc (ptrReverseString, Arg1, Arg2, Arg3, Arg4) End Function ' ' ============================================================ ' End of File ReverseString.Inc cut and pasted RapidQ source BinToInc.Bas is available in \Bin_To_Inc\RQ_Source ; these sources require QRedEx.Inc and QIni_JP.Inc to compile. BINTOINC_PLUS.BAS ----------------- Does the same as BINTOINC.BAS, but with all the .BIN files present in the selected directory. Try in \Bin_To_Inc\Demo_Plus\ RQASMTOINC.BAS RqAsm editor 'Compiling' directly Bin To an RQ .Inc file -------------- RqAsm Adds the Nasm Header and Footer, creates the arguments macro to call them by their names in the Nasm code. _ RqAsm knows four words if most left on a line and followed by a space function end function sub end sub - the first word following 'function' or 'sub' is the name of the function used in the creation of the RQ code. That 'name' will be used to - create the 'name.Asm' file - compile the 'name.Bin' file - name the RQ 'nameArray' - create the RQ 'ptrName' to nameArray(0) - create the RQ function or sub 'name' - the words following the function or sub name are the arguments names they will be used to define NASM macros, allowing easier access to 'pushed' arguments, - separator between names and arguments is a single space = " " - all lines out of function/end function or sub/end sub are ignored - all other lines will simply be copied in the name.Asm file, such as asm code lines, commented lines, ... Here is An RqAsm Example : --- RqASm Code Start -------------- ; FUNCTION GET BYTE AT ; -------------------- ; address is a pointer ; function GetByteAt address push edx mov eax, address mov edx, 0 mov dl, [eax] mov eax, edx pop edx end function --- RqAsm Code End ---------------- RqAsmToInc will create a NASM code GetByteAt.Asm file : --- NASM Code Start --------------- ; PROC NAME : GETBYTEAT ; ; NASM CODE Generated by rqAsmToBin on 04-14-2002 at 14:07:54 ; bits 32 ; %define address [ebp+08] ; segment .text start: enter 0, 0 ; ; End Of RqAsm Automated Header ; User's Code Begins Here ; push edx mov eax, address mov edx, 0 mov dl, [eax] mov eax, edx pop edx ; ; End of User's Code ; Automated RqAsm Footer leave ret 16 ; ; End of NASM Code --- NASM Code End ------------------- RqAsmToInc will compile it in GetByteAt.Bin file And Finnally RqAsmToInc will create a GetByteAt.Inc file ' ' ============================================================ ' ----- START ASM GetByteAt ----- DefByte GetByteAtArray (0 To 21) = _ { _ &HC8, &H00, &H00, &H00, &H52, &H8B, &H45, &H08, &HBA, &H00, _ &H00, &H00, &H00, &H8A, &H10, &H89, &HD0, &H5A, &HC9, &HC2, _ &H10, &H00 _ } ' ----- END ASM GetByteAt ----- ' ' ----- POINTER to use In CallAsmProc ----- ' A Bit Faster than Calling GetByteAt DefInt ptrGetByteAt ptrGetByteAt = VarPtr (GetByteAtArray(0)) ' ' ----- RQ CALL GetByteAt ----- Function GetByteAt (Arg1 As Long) As Long Result = CallAsmProc (ptrGetByteAt, Arg1, 0, 0, 0) End Function ' ' ============================================================ ' that can be included in your RApidQ code. And simply called in RQ by GetByteAt(address) ...more - Sub, Function and End Sub and End Function are delimiter. Same reserved word as in RapidQ - functionName, subName, arg_1, arg_2, arg_3, arg_4 must br any 'valid' NASM names - the function/sub elements are separated by one single space - arg_1, arg_2, arg_3, arg_4 are always Longs. Long can be a pointer to anything : string, array, structure, CodePtr, ... - functions returns always a Long (register eax is the returned value). - Sub and Function cannot be nested - Nearly all NASM procedure in the world can be 'ported' to RQ. There even is a GUI 'set' written NASM available named 'gaz'. Files and Directories --------------------- - The RqAsm file is saved in the RqAsm directory (choosen by user) All the intermediary files, .ASM files and .BIN files, are stored in that directory too. - The final .INC file is saved in the INC directory (choosen by the user) IE, in the RapidQ current project directory - These two directories are choosen by the user on "Open RqAsm" or "New RqAsm" - The last directories and filename used are saved in an INI file on RqAsmToInc Exit and reloaded on start. RAPIDQ_TEST RQ ASM SPEED TESTS in directory \RapidQ_Test\ ----------- - ConAsmTest.Exe source : ConAsmTest.Bas - GuiAsmTest.Exe source : GuiAsmTest.Bas These will show you that CallWindowProc put a terrible time burden on your fast ASM procedures... RqAsmToInc in an usefull but unfinished thing... it could - include the RQ Call Function - have a better file saving system - ... April 14th, 2002 Jacques