Author Topic: Calling OpCode Strings  (Read 10094 times)

0 Members and 1 Guest are viewing this topic.

Online Charles Pegge

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 672
  • User-Rate: +27/-1
    • Charles Pegge
Calling OpCode Strings
« on: June 22, 2007, 08:28:03 AM »
This shows how to call strings of x86 machine code. It shows how the EAX register is used to return integer results and how to extract a parameter from the stack, replacing the return address. This assumes the SDECL calling protocol where the called function cleans the stack of any parameters before returning to the caller.

This approach can be used for dynamic assembly or compilation during run time.

Code: [Select]
' Calling Opcode strings
' Charles E V Pegge
' 22 June 2007

' FreeBasic  ver 0.16b

union opcodestring
 s as byte ptr
 f as function () as long
 f1 as function ( byval long ) as long
end union

dim as string st,st1
dim as opcodestring act,act1

' clear the eax register, increment it  and return

st=chr$(&h33)+chr$(&hc0)+chr$(&h40)+chr$(&hc3)  ' xor eax,eax inc eax ret

' extract the parameter from the stack into eax and return

st1=chr$(&h5a)+chr$(&h58)+chr$(&h52)+chr$(&hc3) ' pop edx pop eax push edx ret

act.s=strptr(st): act1.s=strptr(st1)  ' set string pointers

' Test the strings

print act.f()    ' answer 1

print act1.f1(42) ' answer 42

Online Charles Pegge

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 672
  • User-Rate: +27/-1
    • Charles Pegge
Re: Calling OpCode Strings
« Reply #1 on: June 22, 2007, 09:04:09 AM »

Not quite so simple in PowerBasic:

Code: [Select]
' Calling Opcode strings
' Charles E V Pegge
' 22 June 2007

' PowerBasic  ver 8.x

#COMPILE EXE
#DIM ALL


UNION opcodestring
 s AS BYTE PTR
 f  AS LONG PTR
 f1 AS LONG PTR
END UNION

DECLARE FUNCTION f() AS LONG
DECLARE FUNCTION f1 (BYVAL v AS LONG) AS LONG


FUNCTION PBMAIN () AS LONG


DIM t AS STRING, st AS STRING ,st1 AS STRING
DIM act AS opcodestring, act1 AS opcodestring
DIM v AS LONG

' clear the eax register, increment it  and return

st=CHR$(&h33)+CHR$(&hc0)+CHR$(&h40)+CHR$(&hc3)  ' xor eax,eax inc eax ret

' extract the parameter from the stack into eax and return

st1=CHR$(&h5a)+CHR$(&h58)+CHR$(&h52)+CHR$(&hc3) ' pop edx pop eax push edx ret

act.s=STRPTR(st): act1.s=STRPTR(st1)  ' set string pointers

' Test the strings

'print act.f()     ' answer 1
'print act1.f1(42) ' answer 42

CALL DWORD act.f USING f() TO v: t=STR$(v)
CALL DWORD act1.f1 USING f1(42) TO v: t=t+"    "+STR$(v)

MSGBOX t

END FUNCTION

Offline Edwin Knoppert

  • Sr. Member
  • ****
  • Posts: 254
  • User-Rate: +11/-4
    • Hellobasic.com
Re: Calling OpCode Strings
« Reply #2 on: June 22, 2007, 10:08:36 AM »
Neat..
I thought it required VirtualAlloc() or something to execute opcode.

Online Charles Pegge

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 672
  • User-Rate: +27/-1
    • Charles Pegge
Re: Calling OpCode Strings
« Reply #3 on: June 22, 2007, 11:43:58 AM »
No, you can execute opcodes from anywhere as long as there are no address dependencies in the code itself. Since most x86 calls and jumps are 'relative' and variables are stack based or indexed from a register, this is very easy to do.

As you can see, some of the coding effort goes into persuading Basic that what you want to do is legitimate and that you are not just messing about.

Offline Donald Darden

  • Sr. Member
  • ****
  • Posts: 363
  • User-Rate: +3/-13
Re: Calling OpCode Strings
« Reply #4 on: June 23, 2007, 01:32:24 AM »
It's an interesting idea, but where or why would you expect to resort to this?
I could see that you could read something into a string to esecute it this way,
but I can't conceive of anything I would trust to read in this manner and trust on the blind to do something beneficial for my program.  It it were already in my
program, then it would actually be much easier to use the inline assembler.

Online Charles Pegge

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 672
  • User-Rate: +27/-1
    • Charles Pegge
Re: Calling OpCode Strings
« Reply #5 on: June 23, 2007, 04:52:53 AM »
This technique can be used in scripting languages to compile on-the-fly instead of interpreting rext or byte code. This is especially useful for speeding up repetitive blocks of code.

It opens up all kinds of possibilities for high level language development,
resolving the conflict between speed and flexibility.

Offline Eros Olmi

  • Full Member
  • ***
  • Posts: 243
  • User-Rate: +18/-7
    • thinBasic
Re: Calling OpCode Strings
« Reply #6 on: June 23, 2007, 11:50:04 AM »
FBSL interpreter uses this technique: www.fbsl.net
If you install it there are some examples showing it
thinBasic Script Interpreter - www.thinbasic.com | www.thinbasic.com/community
Win7Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

Online Charles Pegge

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 672
  • User-Rate: +27/-1
    • Charles Pegge
Re: Calling OpCode Strings
« Reply #7 on: June 23, 2007, 01:47:03 PM »

Thanks Eros, I had a look at their website and online manual. They seem to have everything! I would quite like to know how to create DLLs and EXE
files from scratch. Header formats and table etc. Not that these are needed with dynamic compilation.

Offline Gérôme Guillemin

  • Newbie
  • *
  • Posts: 12
  • User-Rate: +0/-6
Re: Calling OpCode Strings
« Reply #8 on: February 04, 2009, 08:57:52 PM »

Thanks Eros, I had a look at their website and online manual. They seem to have everything! I would quite like to know how to create DLLs and EXE
files from scratch. Header formats and table etc. Not that these are needed with dynamic compilation.



The opcode technique is used within the FBSL Eclecta's IDE, an IDE 100% made in FBSL code with syntax color done thanks to these opcodes :)