---------------------------------------------------------------------------
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)
?official site?
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