Embedding Binary Code in newLISP
The following hack shows how to embed binary code in newLISP for execution just like any other function call in newLISP. The trick is to create a built-in function symbol and point it to the code to execute. The code should be written to 'C' calling conventions of the platform newLISP is running on.
The following example assumes a x86 like CPU (args on the stack).
1. The code to execute
The following lines show x86 assembly for a function taking two integers and returning the sum of both:55 push ebp
8B EC mov ebp, esp
8B 45 08 mov eax, [ebp+08]
03 45 0C add eax, [ebp+0c]
5D pop ebp
C3 ret
; for Win32/stdcall change last line
C2 08 00 ret
Create a string containing the binary code. Variable foo-code must not be reassigned:
(set 'foo-code (pack "ccccccccccc"
0x55 0x8B 0xEC 0x8B 0x45 0x08
0x03 0x45 0x0C 0x5D 0xC3))
2. Get a function template from a built-in function
(set 'foo print)3. Change the type to a library function
; on WIN32 stdcall(cpymem (pack "ld" 2312) (first (dump foo)) 4)
; on LINUX/UNIX cdecl
(cpymem (pack "ld" 1288) (first (dump foo)) 4)
4. Point the function to the binary code
This is done copying the address of the bin-data into the cell contents field of fooat offset 12:
(cpymem (pack "ld" (address foo-code))
(+ (first (dump foo)) 12) 4)
5. Set name ptr to correct function name
This copies a ptr to the function name into the auxilary cell field of foo.Variable foo-name must not be reassigned:
(set 'foo-name "foo")
(cpymem (pack "ld" foo-name)
(+ (first (dump foo)) 8) 4)
6. Putting it all together platform independent
(set 'foo-code (append(pack "bbbbbbbbbb" 0x55 0x8B 0xEC 0x8B 0x45 0x08 0x03 0x45 0x0C 0x5D)
(if (= ostype "Win32") (pack "bbb" 0xC2 0x08 0x00) (pack "b" 0xC3))))
(set 'foo print)
(cpymem (pack "ld" (if (= ostype "Win32") 2312 1288)) (first (dump foo)) 4)
(cpymem (pack "ld" (address foo-code)) (+ (first (dump foo)) 12) 4)
(set 'foo-name "foo")
(cpymem (pack "ld" foo-name) (+ (first (dump foo)) 8) 4)
; execute
(foo 3 4) => 7