Embedding Binary Code in newLISP
updated 2013-10-29
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) and will not work on all platforms.
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" 8456) (first (dump foo)) 4)
; on LINUX/UNIX cdecl
(cpymem (pack "ld" 4360) (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") 8456 4360)) (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