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