
---------------------------------------------------------------------------
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
