PureBasic Forum • View topic - Real-time machine-code execution

# PureBasic Forum

PureBasic web site
PureBasic blog page

FAQ Search | Register Login

| It is currently Sat Sep 08, 2012 8:00 am

View unanswered posts | View active topics

All times are UTC + 1 hour

## Real-time machine-code execution

| [ 19 posts ] | Go to page 1, 2 Next

Author | Message
--- | ---

Crusiatus Black

Post subject: Real-time machine-code execution Posted: Tue Sep 04, 2012 1:32 am

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

Hey all,
This is more of a thing that was interesting me for quite a while. I know you can allocate a buffer with execution
permissions, which you in turn can fill with opcodes and data like below (calling MessageBoxA).
Code:
Import "user32.lib" MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l) EndImport Procedure assemblyCall() Protected requiredSize = 28 ; 4x 1byte push with 4 dword values = 20 ; 1x MOV EAX, DWORD = 5 bytes ; 1x CALL EAX = 2 bytes ; 1x return = 1 byte. vm = VirtualAlloc_(#Null, requiredSize, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE) If(vm) Protected szTitle.s = "Hello World!!" Protected szMessage.s = "Testing executing the contents of this buffer." Protected Flags = #MB_ICONINFORMATION | #MB_YESNO Protected dwOffset = 0 Protected *function = @MessageBoxA() ; MsgBoxStyle - PUSH Flags PokeA(vm + dwOffset, $68): dwOffset + 1 PokeL(vm + dwOffset, Flags): dwOffset + 4 ; szTitle - PUSH lpszTitle PokeA(vm + dwOffset, $68): dwOffset + 1 PokeL(vm + dwOffset, @szTitle): dwOffset + 4 ; szMessage - PUSH lpszMessage PokeA(vm + dwOffset, $68): dwOffset + 1 PokeL(vm + dwOffset, @szMessage): dwOffset + 4 ; hWindowHandle - PUSH 0 PokeA(vm + dwOffset, $68): dwOffset + 1 PokeL(vm + dwOffset, 0): dwOffset + 4 ; push function = MOV EAX, function PokeA(vm + dwOffset, $B8): dwOffset + 1 PokeL(vm + dwOffset, *function): dwOffset + 4 ; Call PokeA(vm + dwOffset, $FF): dwOffset + 1 ; CALL EAX PokeA(vm + dwOffset, $D0): dwOffset + 1 PokeA(vm + dwOffset, $C3): dwOffset + 1 ;RETN eax_result.l = CallFunctionFast(vm) If(eax_result = #IDYES) Debug "You pressed yes :)" Else Debug "You pressed no :(" EndIf VirtualFree_(vm, 0, #MEM_RELEASE) EndIf EndProcedure assemblyCall()
Plier/DéplierCode originalCopierOuvrirCompiler
Import "user32.lib"
MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l)
EndImport
Procedure assemblyCall()
Protected requiredSize = 28
; 4x 1byte push with 4 dword values = 20
; 1x MOV EAX, DWORD = 5 bytes
; 1x CALL EAX = 2 bytes
; 1x return = 1 byte.
vm = VirtualAlloc_(#Null, requiredSize, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If(vm)
Protected szTitle.s = "Hello World!!"
Protected szMessage.s = "Testing executing the contents of this buffer."
Protected Flags = #MB_ICONINFORMATION | #MB_YESNO
Protected dwOffset = 0
Protected *function = @MessageBoxA()
; MsgBoxStyle - PUSH Flags
PokeA(vm + dwOffset, $68): dwOffset + 1
PokeL(vm + dwOffset, Flags): dwOffset + 4
; szTitle - PUSH lpszTitle
PokeA(vm + dwOffset, $68): dwOffset + 1
PokeL(vm + dwOffset, @szTitle): dwOffset + 4
; szMessage - PUSH lpszMessage
PokeA(vm + dwOffset, $68): dwOffset + 1
PokeL(vm + dwOffset, @szMessage): dwOffset + 4
; hWindowHandle - PUSH 0
PokeA(vm + dwOffset, $68): dwOffset + 1
PokeL(vm + dwOffset, 0): dwOffset + 4
; push function = MOV EAX, function
PokeA(vm + dwOffset, $B8): dwOffset + 1
PokeL(vm + dwOffset, *function): dwOffset + 4
; Call
PokeA(vm + dwOffset, $FF): dwOffset + 1 ; CALL EAX
PokeA(vm + dwOffset, $D0): dwOffset + 1
PokeA(vm + dwOffset, $C3): dwOffset + 1 ;RETN
eax_result.l = CallFunctionFast(vm)
If(eax_result = #IDYES)
Debug "You pressed yes :)"
Else
Debug "You pressed no :("
EndIf
VirtualFree_(vm, 0, #MEM_RELEASE)
EndIf
EndProcedure
assemblyCall()

| Import "user32.lib"
| MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l)
| EndImport
| Procedure assemblyCall()
| Protected requiredSize = 28
| ; 4x 1byte push with 4 dword values = 20
| ; 1x MOV EAX, DWORD = 5 bytes
| ; 1x CALL EAX = 2 bytes
| ; 1x return = 1 byte.
| vm = VirtualAlloc_(#Null, requiredSize, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
| If(vm)
| Protected szTitle.s = "Hello World!!"
| Protected szMessage.s = "Testing executing the contents of this buffer."
| Protected Flags = #MB_ICONINFORMATION | #MB_YESNO
| Protected dwOffset = 0
| Protected *function = @MessageBoxA()
| ; MsgBoxStyle - PUSH Flags
| PokeA(vm + dwOffset, $68): dwOffset + 1
| PokeL(vm + dwOffset, Flags): dwOffset + 4
| ; szTitle - PUSH lpszTitle
| PokeA(vm + dwOffset, $68): dwOffset + 1
| PokeL(vm + dwOffset, @szTitle): dwOffset + 4
| ; szMessage - PUSH lpszMessage
| PokeA(vm + dwOffset, $68): dwOffset + 1
| PokeL(vm + dwOffset, @szMessage): dwOffset + 4
| ; hWindowHandle - PUSH 0
| PokeA(vm + dwOffset, $68): dwOffset + 1
| PokeL(vm + dwOffset, 0): dwOffset + 4
| ; push function = MOV EAX, function
| PokeA(vm + dwOffset, $B8): dwOffset + 1
| PokeL(vm + dwOffset, *function): dwOffset + 4
| ; Call
| PokeA(vm + dwOffset, $FF): dwOffset + 1 ; CALL EAX
| PokeA(vm + dwOffset, $D0): dwOffset + 1
| PokeA(vm + dwOffset, $C3): dwOffset + 1 ;RETN
| eax_result.l = CallFunctionFast(vm)
| If(eax_result = #IDYES)
| Debug "You pressed yes :)"
| Else
| Debug "You pressed no :("
| EndIf
| VirtualFree_(vm, 0, #MEM_RELEASE)
| EndIf
| EndProcedure
| assemblyCall()

Now, I was wondering because this is quite interesting to me, is there something available or doable
that can assemble / compile assembly code and execute it dynamically? I mean, I know it must be possible,
because this code works for me. But this isn't really an easy read.
I would like a real-time assembler like this, because then I'd be able to use assembly dynamically. Extending
scripting languages with it etc.
Anyhow, just my curiosity here. I'm curious of what is currently possible.
I remember that something like this has been done in AutoIt a while ago, dynamically assembling and executing FASM code.
Thanks.
_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

jack

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:07 am

Addict

Joined: Fri Apr 25, 2003 11:10 pm
Posts: 804

interesting, you could use the fasmDLL to do the assembling http://board.flatassembler.net/topic.php?t=6239

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:31 am

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

Hey Jack,
That's pretty cool! I never knew about a FASM dll, it would be even more awesome if there was
a static library instead of a DLL, but I'm not going to get into compiling static libraries with FASM haha.
Anyhow, this works too, thanks for the link man, this is really interesting.
Code:
; The following structure resides at the beginning of memory block provided ; to the fasm_Assemble function. The condition field contains the same value ; as the one returned by function. ; When function returns FASM_OK condition, the output_length and ; output_data fields are filled - with pointer to generated output ; (somewhere within the provided memory block) and the count of bytes stored ; there. ; When function returns FASM_ERROR, the error_code is filled with the ; code of specific error that happened and error_line is a pointer to the ; LINE_HEADER structure, providing information about the line that caused ; the error. Structure FASM_STATE condition.l StructureUnion output_length.l error_code.l EndStructureUnion StructureUnion output_data.l error_line.l EndStructureUnion EndStructure ; The following structure has two variants - it either defines the line ; that was loaded directly from source, or the line that was generated by ; macroinstruction. First case has the highest bit of line_number set to 0, ; while the second case has this bit set. ; In the first case, the file_path field contains pointer to the path of ; source file (empty string if it's the source that was provided directly to ; fasm_Assemble function), the line_number is the number of line within ; that file (starting from 1) and the file_offset field contains the offset ; within the file where the line starts. ; In the second case the macro_calling_line field contains the pointer to ; LINE_HEADER structure for the line which called the macroinstruction, and ; the macro_line field contains the pointer to LINE_HEADER structure for the ; line within the definition of macroinstruction, which generated this one. Structure LINE_HEADER file_path.l line_number.l StructureUnion file_offset.l macro_calling_line.l EndStructureUnion Macro_line.l EndStructure ; General errors and conditions #FASM_OK = 0 ; FASM_STATE points to output #FASM_WORKING = 1 #FASM_ERROR = 2 ; FASM_STATE contains error code #FASM_INVALID_PARAMETER = -1 #FASM_OUT_OF_MEMORY = -2 #FASM_STACK_OVERFLOW = -3 #FASM_SOURCE_NOT_FOUND = -4 #FASM_UNEXPECTED_END_OF_SOURCE = -5 #FASM_CANNOT_GENERATE_CODE = -6 #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7 #FASM_WRITE_FAILED = -8 ; Error codes for FASM_ERROR condition #FASMERR_FILE_NOT_FOUND = -101 #FASMERR_ERROR_READING_FILE = -102 #FASMERR_INVALID_FILE_FORMAT = -103 #FASMERR_INVALID_MACRO_ARGUMENTS = -104 #FASMERR_INCOMPLETE_MACRO = -105 #FASMERR_UNEXPECTED_CHARACTERS = -106 #FASMERR_INVALID_ARGUMENT = -107 #FASMERR_ILLEGAL_INSTRUCTION = -108 #FASMERR_INVALID_OPERAND = -109 #FASMERR_INVALID_OPERAND_SIZE = -110 #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111 #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112 #FASMERR_INVALID_ADDRESS_SIZE = -113 #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114 #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115 #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116 #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117 #FASMERR_INVALID_EXPRESSION = -118 #FASMERR_INVALID_ADDRESS = -119 #FASMERR_INVALID_VALUE = -120 #FASMERR_VALUE_OUT_OF_RANGE = -121 #FASMERR_UNDEFINED_SYMBOL = -122 #FASMERR_INVALID_USE_OF_SYMBOL = -123 #FASMERR_NAME_TOO_LONG = -124 #FASMERR_INVALID_NAME = -125 #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126 #FASMERR_SYMBOL_ALREADY_DEFINED = -127 #FASMERR_MISSING_END_QUOTE = -128 #FASMERR_MISSING_END_DIRECTIVE = -129 #FASMERR_UNEXPECTED_INSTRUCTION = -130 #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131 #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132 #FASMERR_SETTING_ALREADY_SPECIFIED = -133 #FASMERR_DATA_ALREADY_DEFINED = -134 #FASMERR_TOO_MANY_REPEATS = -135 #FASMERR_SYMBOL_OUT_OF_SCOPE = -136 #FASMERR_USER_ERROR = -140 #FASMERR_ASSERTION_FAILED = -141 DataSection fasm_dll: IncludeBinary "FASM.dll" EndDataSection Prototype.l fasm_GetVersion() Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Global fasm_GetVersion .fasm_GetVersion = 0 Global fasm_Assemble .fasm_Assemble = 0 Global fasm_AssembleFile.fasm_AssembleFile = 0 Global fasm_hLibrary = 0 Procedure fasm_init() fasm_hLibrary = LoadLibraryM(?fasm_dll) If(fasm_hLibrary) fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion") fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble") fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile") ProcedureReturn 1 EndIf EndProcedure Procedure fasm_close() If(fasm_hLibrary) FreeLibraryM(fasm_hLibrary) fasm_GetVersion = 0 fasm_Assemble = 0 fasm_AssembleFile = 0 EndIf EndProcedure If(fasm_init()) *lpOut.FASM_STATE = AllocateMemory(1024) szSource.s = "use32" + #CRLF$ szSource.s + "push 0" + #CRLF$ szSource.s + "xor eax,eax" + #CRLF$ Debug fasm_Assemble(@szSource, *lpOut, 1024) Debug *lpOut\output_length EndIf
Plier/DéplierCode originalCopierOuvrirCompiler
; The following structure resides at the beginning of memory block provided
; to the fasm_Assemble function. The condition field contains the same value
; as the one returned by function.
; When function returns FASM_OK condition, the output_length and
; output_data fields are filled - with pointer to generated output
; (somewhere within the provided memory block) and the count of bytes stored
; there.
; When function returns FASM_ERROR, the error_code is filled with the
; code of specific error that happened and error_line is a pointer to the
; LINE_HEADER structure, providing information about the line that caused
; the error.
Structure FASM_STATE
condition.l
StructureUnion
output_length.l
error_code.l
EndStructureUnion
StructureUnion
output_data.l
error_line.l
EndStructureUnion
EndStructure
; The following structure has two variants - it either defines the line
; that was loaded directly from source, or the line that was generated by
; macroinstruction. First case has the highest bit of line_number set to 0,
; while the second case has this bit set.
; In the first case, the file_path field contains pointer to the path of
; source file (empty string if it's the source that was provided directly to
; fasm_Assemble function), the line_number is the number of line within
; that file (starting from 1) and the file_offset field contains the offset
; within the file where the line starts.
; In the second case the macro_calling_line field contains the pointer to
; LINE_HEADER structure for the line which called the macroinstruction, and
; the macro_line field contains the pointer to LINE_HEADER structure for the
; line within the definition of macroinstruction, which generated this one.
Structure LINE_HEADER
file_path.l
line_number.l
StructureUnion
file_offset.l
macro_calling_line.l
EndStructureUnion
Macro_line.l
EndStructure
; General errors and conditions
#FASM_OK = 0 ; FASM_STATE points to output
#FASM_WORKING = 1
#FASM_ERROR = 2 ; FASM_STATE contains error code
#FASM_INVALID_PARAMETER = -1
#FASM_OUT_OF_MEMORY = -2
#FASM_STACK_OVERFLOW = -3
#FASM_SOURCE_NOT_FOUND = -4
#FASM_UNEXPECTED_END_OF_SOURCE = -5
#FASM_CANNOT_GENERATE_CODE = -6
#FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
#FASM_WRITE_FAILED = -8
; Error codes for FASM_ERROR condition
#FASMERR_FILE_NOT_FOUND = -101
#FASMERR_ERROR_READING_FILE = -102
#FASMERR_INVALID_FILE_FORMAT = -103
#FASMERR_INVALID_MACRO_ARGUMENTS = -104
#FASMERR_INCOMPLETE_MACRO = -105
#FASMERR_UNEXPECTED_CHARACTERS = -106
#FASMERR_INVALID_ARGUMENT = -107
#FASMERR_ILLEGAL_INSTRUCTION = -108
#FASMERR_INVALID_OPERAND = -109
#FASMERR_INVALID_OPERAND_SIZE = -110
#FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
#FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
#FASMERR_INVALID_ADDRESS_SIZE = -113
#FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
#FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
#FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
#FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
#FASMERR_INVALID_EXPRESSION = -118
#FASMERR_INVALID_ADDRESS = -119
#FASMERR_INVALID_VALUE = -120
#FASMERR_VALUE_OUT_OF_RANGE = -121
#FASMERR_UNDEFINED_SYMBOL = -122
#FASMERR_INVALID_USE_OF_SYMBOL = -123
#FASMERR_NAME_TOO_LONG = -124
#FASMERR_INVALID_NAME = -125
#FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
#FASMERR_SYMBOL_ALREADY_DEFINED = -127
#FASMERR_MISSING_END_QUOTE = -128
#FASMERR_MISSING_END_DIRECTIVE = -129
#FASMERR_UNEXPECTED_INSTRUCTION = -130
#FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
#FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
#FASMERR_SETTING_ALREADY_SPECIFIED = -133
#FASMERR_DATA_ALREADY_DEFINED = -134
#FASMERR_TOO_MANY_REPEATS = -135
#FASMERR_SYMBOL_OUT_OF_SCOPE = -136
#FASMERR_USER_ERROR = -140
#FASMERR_ASSERTION_FAILED = -141
DataSection
fasm_dll: IncludeBinary "FASM.dll"
EndDataSection
Prototype.l fasm_GetVersion()
Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Global fasm_GetVersion .fasm_GetVersion = 0
Global fasm_Assemble .fasm_Assemble = 0
Global fasm_AssembleFile.fasm_AssembleFile = 0
Global fasm_hLibrary = 0
Procedure fasm_init()
fasm_hLibrary = LoadLibraryM(?fasm_dll)
If(fasm_hLibrary)
fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
ProcedureReturn 1
EndIf
EndProcedure
Procedure fasm_close()
If(fasm_hLibrary)
FreeLibraryM(fasm_hLibrary)
fasm_GetVersion = 0
fasm_Assemble = 0
fasm_AssembleFile = 0
EndIf
EndProcedure
If(fasm_init())
*lpOut.FASM_STATE = AllocateMemory(1024)
szSource.s = "use32" + #CRLF$
szSource.s + "push 0" + #CRLF$
szSource.s + "xor eax,eax" + #CRLF$
Debug fasm_Assemble(@szSource, *lpOut, 1024)
Debug *lpOut\output_length
EndIf

| ; The following structure resides at the beginning of memory block provided
| ; to the fasm_Assemble function. The condition field contains the same value
| ; as the one returned by function.
| ; When function returns FASM_OK condition, the output_length and
| ; output_data fields are filled - with pointer to generated output
| ; (somewhere within the provided memory block) and the count of bytes stored
| ; there.
| ; When function returns FASM_ERROR, the error_code is filled with the
| ; code of specific error that happened and error_line is a pointer to the
| ; LINE_HEADER structure, providing information about the line that caused
| ; the error.
| Structure FASM_STATE
| condition.l
| StructureUnion
| output_length.l
| error_code.l
| EndStructureUnion
| StructureUnion
| output_data.l
| error_line.l
| EndStructureUnion
| EndStructure
| ; The following structure has two variants - it either defines the line
| ; that was loaded directly from source, or the line that was generated by
| ; macroinstruction. First case has the highest bit of line_number set to 0,
| ; while the second case has this bit set.
| ; In the first case, the file_path field contains pointer to the path of
| ; source file (empty string if it's the source that was provided directly to
| ; fasm_Assemble function), the line_number is the number of line within
| ; that file (starting from 1) and the file_offset field contains the offset
| ; within the file where the line starts.
| ; In the second case the macro_calling_line field contains the pointer to
| ; LINE_HEADER structure for the line which called the macroinstruction, and
| ; the macro_line field contains the pointer to LINE_HEADER structure for the
| ; line within the definition of macroinstruction, which generated this one.
| Structure LINE_HEADER
| file_path.l
| line_number.l
| StructureUnion
| file_offset.l
| macro_calling_line.l
| EndStructureUnion
| Macro_line.l
| EndStructure
| ; General errors and conditions
| #FASM_OK = 0 ; FASM_STATE points to output
| #FASM_WORKING = 1
| #FASM_ERROR = 2 ; FASM_STATE contains error code
| #FASM_INVALID_PARAMETER = -1
| #FASM_OUT_OF_MEMORY = -2
| #FASM_STACK_OVERFLOW = -3
| #FASM_SOURCE_NOT_FOUND = -4
| #FASM_UNEXPECTED_END_OF_SOURCE = -5
| #FASM_CANNOT_GENERATE_CODE = -6
| #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
| #FASM_WRITE_FAILED = -8
| ; Error codes for FASM_ERROR condition
| #FASMERR_FILE_NOT_FOUND = -101
| #FASMERR_ERROR_READING_FILE = -102
| #FASMERR_INVALID_FILE_FORMAT = -103
| #FASMERR_INVALID_MACRO_ARGUMENTS = -104
| #FASMERR_INCOMPLETE_MACRO = -105
| #FASMERR_UNEXPECTED_CHARACTERS = -106
| #FASMERR_INVALID_ARGUMENT = -107
| #FASMERR_ILLEGAL_INSTRUCTION = -108
| #FASMERR_INVALID_OPERAND = -109
| #FASMERR_INVALID_OPERAND_SIZE = -110
| #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
| #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
| #FASMERR_INVALID_ADDRESS_SIZE = -113
| #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
| #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
| #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
| #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
| #FASMERR_INVALID_EXPRESSION = -118
| #FASMERR_INVALID_ADDRESS = -119
| #FASMERR_INVALID_VALUE = -120
| #FASMERR_VALUE_OUT_OF_RANGE = -121
| #FASMERR_UNDEFINED_SYMBOL = -122
| #FASMERR_INVALID_USE_OF_SYMBOL = -123
| #FASMERR_NAME_TOO_LONG = -124
| #FASMERR_INVALID_NAME = -125
| #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
| #FASMERR_SYMBOL_ALREADY_DEFINED = -127
| #FASMERR_MISSING_END_QUOTE = -128
| #FASMERR_MISSING_END_DIRECTIVE = -129
| #FASMERR_UNEXPECTED_INSTRUCTION = -130
| #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
| #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
| #FASMERR_SETTING_ALREADY_SPECIFIED = -133
| #FASMERR_DATA_ALREADY_DEFINED = -134
| #FASMERR_TOO_MANY_REPEATS = -135
| #FASMERR_SYMBOL_OUT_OF_SCOPE = -136
| #FASMERR_USER_ERROR = -140
| #FASMERR_ASSERTION_FAILED = -141
| DataSection
| fasm_dll: IncludeBinary "FASM.dll"
| EndDataSection
| Prototype.l fasm_GetVersion()
| Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Global fasm_GetVersion .fasm_GetVersion = 0
| Global fasm_Assemble .fasm_Assemble = 0
| Global fasm_AssembleFile.fasm_AssembleFile = 0
| Global fasm_hLibrary = 0
| Procedure fasm_init()
| fasm_hLibrary = LoadLibraryM(?fasm_dll)
| If(fasm_hLibrary)
| fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
| fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
| fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
| ProcedureReturn 1
| EndIf
| EndProcedure
| Procedure fasm_close()
| If(fasm_hLibrary)
| FreeLibraryM(fasm_hLibrary)
| fasm_GetVersion = 0
| fasm_Assemble = 0
| fasm_AssembleFile = 0
| EndIf
| EndProcedure
| If(fasm_init())
| *lpOut.FASM_STATE = AllocateMemory(1024)
| szSource.s = "use32" + #CRLF$
| szSource.s + "push 0" + #CRLF$
| szSource.s + "xor eax,eax" + #CRLF$
| Debug fasm_Assemble(@szSource, *lpOut, 1024)
| Debug *lpOut\output_length
| EndIf

_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:53 am

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

That being said, I managed assembling the code, execution isn't quite working yet ;p
_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 3:46 am

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

There we go! Man, this is fun.
Code:
; The following structure resides at the beginning of memory block provided ; to the fasm_Assemble function. The condition field contains the same value ; as the one returned by function. ; When function returns FASM_OK condition, the output_length and ; output_data fields are filled - with pointer to generated output ; (somewhere within the provided memory block) and the count of bytes stored ; there. ; When function returns FASM_ERROR, the error_code is filled with the ; code of specific error that happened and error_line is a pointer to the ; LINE_HEADER structure, providing information about the line that caused ; the error. Structure FASM_STATE condition.l StructureUnion output_length.l error_code.l EndStructureUnion StructureUnion output_data.l error_line.l EndStructureUnion EndStructure ; The following structure has two variants - it either defines the line ; that was loaded directly from source, or the line that was generated by ; macroinstruction. First case has the highest bit of line_number set to 0, ; while the second case has this bit set. ; In the first case, the file_path field contains pointer to the path of ; source file (empty string if it's the source that was provided directly to ; fasm_Assemble function), the line_number is the number of line within ; that file (starting from 1) and the file_offset field contains the offset ; within the file where the line starts. ; In the second case the macro_calling_line field contains the pointer to ; LINE_HEADER structure for the line which called the macroinstruction, and ; the macro_line field contains the pointer to LINE_HEADER structure for the ; line within the definition of macroinstruction, which generated this one. Structure LINE_HEADER file_path.l line_number.l StructureUnion file_offset.l macro_calling_line.l EndStructureUnion Macro_line.l EndStructure ; General errors and conditions #FASM_OK = 0 ; FASM_STATE points to output #FASM_WORKING = 1 #FASM_ERROR = 2 ; FASM_STATE contains error code #FASM_INVALID_PARAMETER = -1 #FASM_OUT_OF_MEMORY = -2 #FASM_STACK_OVERFLOW = -3 #FASM_SOURCE_NOT_FOUND = -4 #FASM_UNEXPECTED_END_OF_SOURCE = -5 #FASM_CANNOT_GENERATE_CODE = -6 #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7 #FASM_WRITE_FAILED = -8 ; Error codes for FASM_ERROR condition #FASMERR_FILE_NOT_FOUND = -101 #FASMERR_ERROR_READING_FILE = -102 #FASMERR_INVALID_FILE_FORMAT = -103 #FASMERR_INVALID_MACRO_ARGUMENTS = -104 #FASMERR_INCOMPLETE_MACRO = -105 #FASMERR_UNEXPECTED_CHARACTERS = -106 #FASMERR_INVALID_ARGUMENT = -107 #FASMERR_ILLEGAL_INSTRUCTION = -108 #FASMERR_INVALID_OPERAND = -109 #FASMERR_INVALID_OPERAND_SIZE = -110 #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111 #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112 #FASMERR_INVALID_ADDRESS_SIZE = -113 #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114 #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115 #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116 #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117 #FASMERR_INVALID_EXPRESSION = -118 #FASMERR_INVALID_ADDRESS = -119 #FASMERR_INVALID_VALUE = -120 #FASMERR_VALUE_OUT_OF_RANGE = -121 #FASMERR_UNDEFINED_SYMBOL = -122 #FASMERR_INVALID_USE_OF_SYMBOL = -123 #FASMERR_NAME_TOO_LONG = -124 #FASMERR_INVALID_NAME = -125 #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126 #FASMERR_SYMBOL_ALREADY_DEFINED = -127 #FASMERR_MISSING_END_QUOTE = -128 #FASMERR_MISSING_END_DIRECTIVE = -129 #FASMERR_UNEXPECTED_INSTRUCTION = -130 #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131 #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132 #FASMERR_SETTING_ALREADY_SPECIFIED = -133 #FASMERR_DATA_ALREADY_DEFINED = -134 #FASMERR_TOO_MANY_REPEATS = -135 #FASMERR_SYMBOL_OUT_OF_SCOPE = -136 #FASMERR_USER_ERROR = -140 #FASMERR_ASSERTION_FAILED = -141 DataSection fasm_dll: IncludeBinary "FASM.dll" EndDataSection Prototype.l fasm_GetVersion() Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Prototype.l fasm_Procedure() Global fasm_GetVersion .fasm_GetVersion = 0 Global fasm_Assemble .fasm_Assemble = 0 Global fasm_AssembleFile.fasm_AssembleFile = 0 Global fasm_hLibrary = 0 Procedure fasm_init() fasm_hLibrary = LoadLibraryM(?fasm_dll) If(fasm_hLibrary) fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion") fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble") fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile") ProcedureReturn 1 EndIf EndProcedure Procedure fasm_close() If(fasm_hLibrary) FreeLibraryM(fasm_hLibrary) fasm_GetVersion = 0 fasm_Assemble = 0 fasm_AssembleFile = 0 EndIf EndProcedure Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0) Protected result = 0 Protected chunkSize.l = 4096 Protected *line.LINE_HEADER = 0 Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize) If(*lpOut) Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize) If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY) Debug "Error" Debug *lpOut\error_code *line = *lpOut\error_line Debug *line\line_number Else While(assemblerResult = #FASM_OUT_OF_MEMORY) chunkSize + 1024 *lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize) assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize) If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY) Debug "Error" Debug *lpOut\error_code *line = *lpOut\error_line Debug *line\line_number Break EndIf Wend If(assemblerResult = #FASM_OK) *vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE) If(*vm) CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length) If(*lpdwBufferSize) PokeL(*lpdwBufferSize, *lpOut\output_length) EndIf result = *vm EndIf EndIf EndIf FreeMemory(*lpOut) EndIf ProcedureReturn result EndProcedure Procedure fasm_Free(*lpvm) VirtualFree_(*lpvm, 0, #MEM_RELEASE) EndProcedure If(fasm_init()) test.l = 10 asm.s + "use32" + #LF$ asm.s + "org 100h" + #LF$ asm.s + "xor eax, eax" + #LF$ asm.s + "mov eax, 100" + #LF$ asm.s + "add eax, 20" + #LF$ asm.s + "ret" + #LF$ dwSize.l *chunk.fasm_Procedure = fasm_Compile(@asm, @dwSize) If(*chunk) Debug *chunk() fasm_Free(*chunk) EndIf EndIf
Plier/DéplierCode originalCopierOuvrirCompiler
; The following structure resides at the beginning of memory block provided
; to the fasm_Assemble function. The condition field contains the same value
; as the one returned by function.
; When function returns FASM_OK condition, the output_length and
; output_data fields are filled - with pointer to generated output
; (somewhere within the provided memory block) and the count of bytes stored
; there.
; When function returns FASM_ERROR, the error_code is filled with the
; code of specific error that happened and error_line is a pointer to the
; LINE_HEADER structure, providing information about the line that caused
; the error.
Structure FASM_STATE
condition.l
StructureUnion
output_length.l
error_code.l
EndStructureUnion
StructureUnion
output_data.l
error_line.l
EndStructureUnion
EndStructure
; The following structure has two variants - it either defines the line
; that was loaded directly from source, or the line that was generated by
; macroinstruction. First case has the highest bit of line_number set to 0,
; while the second case has this bit set.
; In the first case, the file_path field contains pointer to the path of
; source file (empty string if it's the source that was provided directly to
; fasm_Assemble function), the line_number is the number of line within
; that file (starting from 1) and the file_offset field contains the offset
; within the file where the line starts.
; In the second case the macro_calling_line field contains the pointer to
; LINE_HEADER structure for the line which called the macroinstruction, and
; the macro_line field contains the pointer to LINE_HEADER structure for the
; line within the definition of macroinstruction, which generated this one.
Structure LINE_HEADER
file_path.l
line_number.l
StructureUnion
file_offset.l
macro_calling_line.l
EndStructureUnion
Macro_line.l
EndStructure
; General errors and conditions
#FASM_OK = 0 ; FASM_STATE points to output
#FASM_WORKING = 1
#FASM_ERROR = 2 ; FASM_STATE contains error code
#FASM_INVALID_PARAMETER = -1
#FASM_OUT_OF_MEMORY = -2
#FASM_STACK_OVERFLOW = -3
#FASM_SOURCE_NOT_FOUND = -4
#FASM_UNEXPECTED_END_OF_SOURCE = -5
#FASM_CANNOT_GENERATE_CODE = -6
#FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
#FASM_WRITE_FAILED = -8
; Error codes for FASM_ERROR condition
#FASMERR_FILE_NOT_FOUND = -101
#FASMERR_ERROR_READING_FILE = -102
#FASMERR_INVALID_FILE_FORMAT = -103
#FASMERR_INVALID_MACRO_ARGUMENTS = -104
#FASMERR_INCOMPLETE_MACRO = -105
#FASMERR_UNEXPECTED_CHARACTERS = -106
#FASMERR_INVALID_ARGUMENT = -107
#FASMERR_ILLEGAL_INSTRUCTION = -108
#FASMERR_INVALID_OPERAND = -109
#FASMERR_INVALID_OPERAND_SIZE = -110
#FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
#FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
#FASMERR_INVALID_ADDRESS_SIZE = -113
#FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
#FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
#FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
#FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
#FASMERR_INVALID_EXPRESSION = -118
#FASMERR_INVALID_ADDRESS = -119
#FASMERR_INVALID_VALUE = -120
#FASMERR_VALUE_OUT_OF_RANGE = -121
#FASMERR_UNDEFINED_SYMBOL = -122
#FASMERR_INVALID_USE_OF_SYMBOL = -123
#FASMERR_NAME_TOO_LONG = -124
#FASMERR_INVALID_NAME = -125
#FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
#FASMERR_SYMBOL_ALREADY_DEFINED = -127
#FASMERR_MISSING_END_QUOTE = -128
#FASMERR_MISSING_END_DIRECTIVE = -129
#FASMERR_UNEXPECTED_INSTRUCTION = -130
#FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
#FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
#FASMERR_SETTING_ALREADY_SPECIFIED = -133
#FASMERR_DATA_ALREADY_DEFINED = -134
#FASMERR_TOO_MANY_REPEATS = -135
#FASMERR_SYMBOL_OUT_OF_SCOPE = -136
#FASMERR_USER_ERROR = -140
#FASMERR_ASSERTION_FAILED = -141
DataSection
fasm_dll: IncludeBinary "FASM.dll"
EndDataSection
Prototype.l fasm_GetVersion()
Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Prototype.l fasm_Procedure()
Global fasm_GetVersion .fasm_GetVersion = 0
Global fasm_Assemble .fasm_Assemble = 0
Global fasm_AssembleFile.fasm_AssembleFile = 0
Global fasm_hLibrary = 0
Procedure fasm_init()
fasm_hLibrary = LoadLibraryM(?fasm_dll)
If(fasm_hLibrary)
fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
ProcedureReturn 1
EndIf
EndProcedure
Procedure fasm_close()
If(fasm_hLibrary)
FreeLibraryM(fasm_hLibrary)
fasm_GetVersion = 0
fasm_Assemble = 0
fasm_AssembleFile = 0
EndIf
EndProcedure
Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0)
Protected result = 0
Protected chunkSize.l = 4096
Protected *line.LINE_HEADER = 0
Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize)
If(*lpOut)
Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
Debug "Error"
Debug *lpOut\error_code
*line = *lpOut\error_line
Debug *line\line_number
Else
While(assemblerResult = #FASM_OUT_OF_MEMORY)
chunkSize + 1024
*lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize)
assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
Debug "Error"
Debug *lpOut\error_code
*line = *lpOut\error_line
Debug *line\line_number
Break
EndIf
Wend
If(assemblerResult = #FASM_OK)
*vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If(*vm)
CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length)
If(*lpdwBufferSize)
PokeL(*lpdwBufferSize, *lpOut\output_length)
EndIf
result = *vm
EndIf
EndIf
EndIf
FreeMemory(*lpOut)
EndIf
ProcedureReturn result
EndProcedure
Procedure fasm_Free(*lpvm)
VirtualFree_(*lpvm, 0, #MEM_RELEASE)
EndProcedure
If(fasm_init())
test.l = 10
asm.s + "use32" + #LF$
asm.s + "org 100h" + #LF$
asm.s + "xor eax, eax" + #LF$
asm.s + "mov eax, 100" + #LF$
asm.s + "add eax, 20" + #LF$
asm.s + "ret" + #LF$
dwSize.l
*chunk.fasm_Procedure = fasm_Compile(@asm, @dwSize)
If(*chunk)
Debug *chunk()
fasm_Free(*chunk)
EndIf
EndIf

| ; The following structure resides at the beginning of memory block provided
| ; to the fasm_Assemble function. The condition field contains the same value
| ; as the one returned by function.
| ; When function returns FASM_OK condition, the output_length and
| ; output_data fields are filled - with pointer to generated output
| ; (somewhere within the provided memory block) and the count of bytes stored
| ; there.
| ; When function returns FASM_ERROR, the error_code is filled with the
| ; code of specific error that happened and error_line is a pointer to the
| ; LINE_HEADER structure, providing information about the line that caused
| ; the error.
| Structure FASM_STATE
| condition.l
| StructureUnion
| output_length.l
| error_code.l
| EndStructureUnion
| StructureUnion
| output_data.l
| error_line.l
| EndStructureUnion
| EndStructure
| ; The following structure has two variants - it either defines the line
| ; that was loaded directly from source, or the line that was generated by
| ; macroinstruction. First case has the highest bit of line_number set to 0,
| ; while the second case has this bit set.
| ; In the first case, the file_path field contains pointer to the path of
| ; source file (empty string if it's the source that was provided directly to
| ; fasm_Assemble function), the line_number is the number of line within
| ; that file (starting from 1) and the file_offset field contains the offset
| ; within the file where the line starts.
| ; In the second case the macro_calling_line field contains the pointer to
| ; LINE_HEADER structure for the line which called the macroinstruction, and
| ; the macro_line field contains the pointer to LINE_HEADER structure for the
| ; line within the definition of macroinstruction, which generated this one.
| Structure LINE_HEADER
| file_path.l
| line_number.l
| StructureUnion
| file_offset.l
| macro_calling_line.l
| EndStructureUnion
| Macro_line.l
| EndStructure
| ; General errors and conditions
| #FASM_OK = 0 ; FASM_STATE points to output
| #FASM_WORKING = 1
| #FASM_ERROR = 2 ; FASM_STATE contains error code
| #FASM_INVALID_PARAMETER = -1
| #FASM_OUT_OF_MEMORY = -2
| #FASM_STACK_OVERFLOW = -3
| #FASM_SOURCE_NOT_FOUND = -4
| #FASM_UNEXPECTED_END_OF_SOURCE = -5
| #FASM_CANNOT_GENERATE_CODE = -6
| #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
| #FASM_WRITE_FAILED = -8
| ; Error codes for FASM_ERROR condition
| #FASMERR_FILE_NOT_FOUND = -101
| #FASMERR_ERROR_READING_FILE = -102
| #FASMERR_INVALID_FILE_FORMAT = -103
| #FASMERR_INVALID_MACRO_ARGUMENTS = -104
| #FASMERR_INCOMPLETE_MACRO = -105
| #FASMERR_UNEXPECTED_CHARACTERS = -106
| #FASMERR_INVALID_ARGUMENT = -107
| #FASMERR_ILLEGAL_INSTRUCTION = -108
| #FASMERR_INVALID_OPERAND = -109
| #FASMERR_INVALID_OPERAND_SIZE = -110
| #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
| #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
| #FASMERR_INVALID_ADDRESS_SIZE = -113
| #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
| #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
| #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
| #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
| #FASMERR_INVALID_EXPRESSION = -118
| #FASMERR_INVALID_ADDRESS = -119
| #FASMERR_INVALID_VALUE = -120
| #FASMERR_VALUE_OUT_OF_RANGE = -121
| #FASMERR_UNDEFINED_SYMBOL = -122
| #FASMERR_INVALID_USE_OF_SYMBOL = -123
| #FASMERR_NAME_TOO_LONG = -124
| #FASMERR_INVALID_NAME = -125
| #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
| #FASMERR_SYMBOL_ALREADY_DEFINED = -127
| #FASMERR_MISSING_END_QUOTE = -128
| #FASMERR_MISSING_END_DIRECTIVE = -129
| #FASMERR_UNEXPECTED_INSTRUCTION = -130
| #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
| #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
| #FASMERR_SETTING_ALREADY_SPECIFIED = -133
| #FASMERR_DATA_ALREADY_DEFINED = -134
| #FASMERR_TOO_MANY_REPEATS = -135
| #FASMERR_SYMBOL_OUT_OF_SCOPE = -136
| #FASMERR_USER_ERROR = -140
| #FASMERR_ASSERTION_FAILED = -141
| DataSection
| fasm_dll: IncludeBinary "FASM.dll"
| EndDataSection
| Prototype.l fasm_GetVersion()
| Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Prototype.l fasm_Procedure()
| Global fasm_GetVersion .fasm_GetVersion = 0
| Global fasm_Assemble .fasm_Assemble = 0
| Global fasm_AssembleFile.fasm_AssembleFile = 0
| Global fasm_hLibrary = 0
| Procedure fasm_init()
| fasm_hLibrary = LoadLibraryM(?fasm_dll)
| If(fasm_hLibrary)
| fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
| fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
| fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
| ProcedureReturn 1
| EndIf
| EndProcedure
| Procedure fasm_close()
| If(fasm_hLibrary)
| FreeLibraryM(fasm_hLibrary)
| fasm_GetVersion = 0
| fasm_Assemble = 0
| fasm_AssembleFile = 0
| EndIf
| EndProcedure
| Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0)
| Protected result = 0
| Protected chunkSize.l = 4096
| Protected *line.LINE_HEADER = 0
| Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize)
| If(*lpOut)
| Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
| If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
| Debug "Error"
| Debug *lpOut\error_code
| *line = *lpOut\error_line
| Debug *line\line_number
| Else
| While(assemblerResult = #FASM_OUT_OF_MEMORY)
| chunkSize + 1024
| *lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize)
| assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
| If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
| Debug "Error"
| Debug *lpOut\error_code
| *line = *lpOut\error_line
| Debug *line\line_number
| Break
| EndIf
| Wend
| If(assemblerResult = #FASM_OK)
| *vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
| If(*vm)
| CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length)
| If(*lpdwBufferSize)
| PokeL(*lpdwBufferSize, *lpOut\output_length)
| EndIf
| result = *vm
| EndIf
| EndIf
| EndIf
| FreeMemory(*lpOut)
| EndIf
| ProcedureReturn result
| EndProcedure
| Procedure fasm_Free(*lpvm)
| VirtualFree_(*lpvm, 0, #MEM_RELEASE)
| EndProcedure
| If(fasm_init())
| test.l = 10
| asm.s + "use32" + #LF$
| asm.s + "org 100h" + #LF$
| asm.s + "xor eax, eax" + #LF$
| asm.s + "mov eax, 100" + #LF$
| asm.s + "add eax, 20" + #LF$
| asm.s + "ret" + #LF$
| dwSize.l
| *chunk.fasm_Procedure = fasm_Compile(@asm, @dwSize)
| If(*chunk)
| Debug *chunk()
| fasm_Free(*chunk)
| EndIf
| EndIf

_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

jack

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 4:06 am

Addict

Joined: Fri Apr 25, 2003 11:10 pm
Posts: 804

excellent!

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 1:31 pm

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

So, I've got this to work, I'm assuming assembling and executing is possible, but
the second assembly example in this code causes a read error exception at address 6 or 7,
and 6 or 7 are the results MessageBoxA can return in this case. I'm not sure why this is
happening, because executing assembly like this is different from the PB inline assembly.
Any assembler experts here?
Code:
; The following structure resides at the beginning of memory block provided ; to the fasm_Assemble function. The condition field contains the same value ; as the one returned by function. ; When function returns FASM_OK condition, the output_length and ; output_data fields are filled - with pointer to generated output ; (somewhere within the provided memory block) and the count of bytes stored ; there. ; When function returns FASM_ERROR, the error_code is filled with the ; code of specific error that happened and error_line is a pointer to the ; LINE_HEADER structure, providing information about the line that caused ; the error. Structure FASM_STATE condition.l StructureUnion output_length.l error_code.l EndStructureUnion StructureUnion output_data.l error_line.l EndStructureUnion EndStructure ; The following structure has two variants - it either defines the line ; that was loaded directly from source, or the line that was generated by ; macroinstruction. First case has the highest bit of line_number set to 0, ; while the second case has this bit set. ; In the first case, the file_path field contains pointer to the path of ; source file (empty string if it's the source that was provided directly to ; fasm_Assemble function), the line_number is the number of line within ; that file (starting from 1) and the file_offset field contains the offset ; within the file where the line starts. ; In the second case the macro_calling_line field contains the pointer to ; LINE_HEADER structure for the line which called the macroinstruction, and ; the macro_line field contains the pointer to LINE_HEADER structure for the ; line within the definition of macroinstruction, which generated this one. Structure LINE_HEADER file_path.l line_number.l StructureUnion file_offset.l macro_calling_line.l EndStructureUnion Macro_line.l EndStructure ; General errors and conditions #FASM_OK = 0 ; FASM_STATE points to output #FASM_WORKING = 1 #FASM_ERROR = 2 ; FASM_STATE contains error code #FASM_INVALID_PARAMETER = -1 #FASM_OUT_OF_MEMORY = -2 #FASM_STACK_OVERFLOW = -3 #FASM_SOURCE_NOT_FOUND = -4 #FASM_UNEXPECTED_END_OF_SOURCE = -5 #FASM_CANNOT_GENERATE_CODE = -6 #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7 #FASM_WRITE_FAILED = -8 ; Error codes for FASM_ERROR condition #FASMERR_FILE_NOT_FOUND = -101 #FASMERR_ERROR_READING_FILE = -102 #FASMERR_INVALID_FILE_FORMAT = -103 #FASMERR_INVALID_MACRO_ARGUMENTS = -104 #FASMERR_INCOMPLETE_MACRO = -105 #FASMERR_UNEXPECTED_CHARACTERS = -106 #FASMERR_INVALID_ARGUMENT = -107 #FASMERR_ILLEGAL_INSTRUCTION = -108 #FASMERR_INVALID_OPERAND = -109 #FASMERR_INVALID_OPERAND_SIZE = -110 #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111 #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112 #FASMERR_INVALID_ADDRESS_SIZE = -113 #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114 #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115 #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116 #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117 #FASMERR_INVALID_EXPRESSION = -118 #FASMERR_INVALID_ADDRESS = -119 #FASMERR_INVALID_VALUE = -120 #FASMERR_VALUE_OUT_OF_RANGE = -121 #FASMERR_UNDEFINED_SYMBOL = -122 #FASMERR_INVALID_USE_OF_SYMBOL = -123 #FASMERR_NAME_TOO_LONG = -124 #FASMERR_INVALID_NAME = -125 #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126 #FASMERR_SYMBOL_ALREADY_DEFINED = -127 #FASMERR_MISSING_END_QUOTE = -128 #FASMERR_MISSING_END_DIRECTIVE = -129 #FASMERR_UNEXPECTED_INSTRUCTION = -130 #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131 #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132 #FASMERR_SETTING_ALREADY_SPECIFIED = -133 #FASMERR_DATA_ALREADY_DEFINED = -134 #FASMERR_TOO_MANY_REPEATS = -135 #FASMERR_SYMBOL_OUT_OF_SCOPE = -136 #FASMERR_USER_ERROR = -140 #FASMERR_ASSERTION_FAILED = -141 DataSection fasm_dll: IncludeBinary "FASM.dll" EndDataSection Prototype.l fasm_GetVersion() Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null) Prototype.l fasm_Procedure() Global fasm_GetVersion .fasm_GetVersion = 0 Global fasm_Assemble .fasm_Assemble = 0 Global fasm_AssembleFile.fasm_AssembleFile = 0 Global fasm_hLibrary = 0 Procedure fasm_init() fasm_hLibrary = LoadLibraryM(?fasm_dll) If(fasm_hLibrary) fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion") fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble") fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile") ProcedureReturn 1 EndIf EndProcedure Procedure fasm_close() If(fasm_hLibrary) FreeLibraryM(fasm_hLibrary) fasm_GetVersion = 0 fasm_Assemble = 0 fasm_AssembleFile = 0 EndIf EndProcedure Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0) Protected result = 0 Protected chunkSize.l = 4096 Protected *line.LINE_HEADER = 0 Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize) If(*lpOut) Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize) If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY) Debug "Error" Debug *lpOut\error_code *line = *lpOut\error_line Debug *line\line_number Else While(assemblerResult = #FASM_OUT_OF_MEMORY) chunkSize + 1024 *lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize) assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize) If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY) Debug "Error" Debug *lpOut\error_code *line = *lpOut\error_line Debug *line\line_number Break EndIf Wend If(assemblerResult = #FASM_OK) *vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE) If(*vm) CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length) If(*lpdwBufferSize) PokeL(*lpdwBufferSize, *lpOut\output_length) EndIf result = *vm EndIf EndIf EndIf FreeMemory(*lpOut) EndIf ProcedureReturn result EndProcedure Procedure fasm_Free(*lpvm) VirtualFree_(*lpvm, 0, #MEM_RELEASE) EndProcedure Import "user32.lib" MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l) EndImport If(fasm_init()) ; works asm.s + "use32" + #LF$ asm.s + "org 100h" + #LF$ asm.s + "xor eax, eax" + #LF$ asm.s + "mov eax, 100" + #LF$ asm.s + "add eax, 20" + #LF$ asm.s + "ret" + #LF$ flags = #MB_YESNO | #MB_ICONINFORMATION hWnd = 0 szTitle.s = "Hello World!!" szMessage.s = "This function was executed through an FASM assembler via PureBasic! 0_o" hwnd = 0 pfunc = @MessageBoxA() asm2.s + "use32" + #LF$ asm2.s + "org 100h" + #LF$ asm2.s + "mov [esp+12], dword " + Str(flags) + "" + #LF$ asm2.s + "mov [esp+08], dword " + Str(@szTitle) + #LF$ asm2.s + "mov [esp+04], dword " + Str(@szMessage) + #LF$ asm2.s + "mov [esp+00], dword " + Str(hwnd) + #LF$ asm2.s + "xor eax, eax" + #LF$ asm2.s + "mov ecx, dword " + Str(@MessageBoxA()) + "" + #LF$ asm2.s + "call ecx" + #LF$ asm2.s + "ret" + #LF$ dwSize.l = 0 ; works, returns 120 *myMessageBox.fasm_Procedure = fasm_Compile(@asm, @dwSize) If(*myMessageBox) Debug *myMessageBox() fasm_Free(*myMessageBox) EndIf ; Doesn't work, tries interpreting the MessageBoxA result as memory address? *myMessageBox.fasm_Procedure = fasm_Compile(@asm2, @dwSize) If(*myMessageBox) Debug *myMessageBox() fasm_Free(*myMessageBox) EndIf EndIf
Plier/DéplierCode originalCopierOuvrirCompiler
; The following structure resides at the beginning of memory block provided
; to the fasm_Assemble function. The condition field contains the same value
; as the one returned by function.
; When function returns FASM_OK condition, the output_length and
; output_data fields are filled - with pointer to generated output
; (somewhere within the provided memory block) and the count of bytes stored
; there.
; When function returns FASM_ERROR, the error_code is filled with the
; code of specific error that happened and error_line is a pointer to the
; LINE_HEADER structure, providing information about the line that caused
; the error.
Structure FASM_STATE
condition.l
StructureUnion
output_length.l
error_code.l
EndStructureUnion
StructureUnion
output_data.l
error_line.l
EndStructureUnion
EndStructure
; The following structure has two variants - it either defines the line
; that was loaded directly from source, or the line that was generated by
; macroinstruction. First case has the highest bit of line_number set to 0,
; while the second case has this bit set.
; In the first case, the file_path field contains pointer to the path of
; source file (empty string if it's the source that was provided directly to
; fasm_Assemble function), the line_number is the number of line within
; that file (starting from 1) and the file_offset field contains the offset
; within the file where the line starts.
; In the second case the macro_calling_line field contains the pointer to
; LINE_HEADER structure for the line which called the macroinstruction, and
; the macro_line field contains the pointer to LINE_HEADER structure for the
; line within the definition of macroinstruction, which generated this one.
Structure LINE_HEADER
file_path.l
line_number.l
StructureUnion
file_offset.l
macro_calling_line.l
EndStructureUnion
Macro_line.l
EndStructure
; General errors and conditions
#FASM_OK = 0 ; FASM_STATE points to output
#FASM_WORKING = 1
#FASM_ERROR = 2 ; FASM_STATE contains error code
#FASM_INVALID_PARAMETER = -1
#FASM_OUT_OF_MEMORY = -2
#FASM_STACK_OVERFLOW = -3
#FASM_SOURCE_NOT_FOUND = -4
#FASM_UNEXPECTED_END_OF_SOURCE = -5
#FASM_CANNOT_GENERATE_CODE = -6
#FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
#FASM_WRITE_FAILED = -8
; Error codes for FASM_ERROR condition
#FASMERR_FILE_NOT_FOUND = -101
#FASMERR_ERROR_READING_FILE = -102
#FASMERR_INVALID_FILE_FORMAT = -103
#FASMERR_INVALID_MACRO_ARGUMENTS = -104
#FASMERR_INCOMPLETE_MACRO = -105
#FASMERR_UNEXPECTED_CHARACTERS = -106
#FASMERR_INVALID_ARGUMENT = -107
#FASMERR_ILLEGAL_INSTRUCTION = -108
#FASMERR_INVALID_OPERAND = -109
#FASMERR_INVALID_OPERAND_SIZE = -110
#FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
#FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
#FASMERR_INVALID_ADDRESS_SIZE = -113
#FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
#FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
#FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
#FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
#FASMERR_INVALID_EXPRESSION = -118
#FASMERR_INVALID_ADDRESS = -119
#FASMERR_INVALID_VALUE = -120
#FASMERR_VALUE_OUT_OF_RANGE = -121
#FASMERR_UNDEFINED_SYMBOL = -122
#FASMERR_INVALID_USE_OF_SYMBOL = -123
#FASMERR_NAME_TOO_LONG = -124
#FASMERR_INVALID_NAME = -125
#FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
#FASMERR_SYMBOL_ALREADY_DEFINED = -127
#FASMERR_MISSING_END_QUOTE = -128
#FASMERR_MISSING_END_DIRECTIVE = -129
#FASMERR_UNEXPECTED_INSTRUCTION = -130
#FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
#FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
#FASMERR_SETTING_ALREADY_SPECIFIED = -133
#FASMERR_DATA_ALREADY_DEFINED = -134
#FASMERR_TOO_MANY_REPEATS = -135
#FASMERR_SYMBOL_OUT_OF_SCOPE = -136
#FASMERR_USER_ERROR = -140
#FASMERR_ASSERTION_FAILED = -141
DataSection
fasm_dll: IncludeBinary "FASM.dll"
EndDataSection
Prototype.l fasm_GetVersion()
Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
Prototype.l fasm_Procedure()
Global fasm_GetVersion .fasm_GetVersion = 0
Global fasm_Assemble .fasm_Assemble = 0
Global fasm_AssembleFile.fasm_AssembleFile = 0
Global fasm_hLibrary = 0
Procedure fasm_init()
fasm_hLibrary = LoadLibraryM(?fasm_dll)
If(fasm_hLibrary)
fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
ProcedureReturn 1
EndIf
EndProcedure
Procedure fasm_close()
If(fasm_hLibrary)
FreeLibraryM(fasm_hLibrary)
fasm_GetVersion = 0
fasm_Assemble = 0
fasm_AssembleFile = 0
EndIf
EndProcedure
Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0)
Protected result = 0
Protected chunkSize.l = 4096
Protected *line.LINE_HEADER = 0
Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize)
If(*lpOut)
Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
Debug "Error"
Debug *lpOut\error_code
*line = *lpOut\error_line
Debug *line\line_number
Else
While(assemblerResult = #FASM_OUT_OF_MEMORY)
chunkSize + 1024
*lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize)
assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
Debug "Error"
Debug *lpOut\error_code
*line = *lpOut\error_line
Debug *line\line_number
Break
EndIf
Wend
If(assemblerResult = #FASM_OK)
*vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If(*vm)
CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length)
If(*lpdwBufferSize)
PokeL(*lpdwBufferSize, *lpOut\output_length)
EndIf
result = *vm
EndIf
EndIf
EndIf
FreeMemory(*lpOut)
EndIf
ProcedureReturn result
EndProcedure
Procedure fasm_Free(*lpvm)
VirtualFree_(*lpvm, 0, #MEM_RELEASE)
EndProcedure
Import "user32.lib"
MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l)
EndImport
If(fasm_init())
; works
asm.s + "use32" + #LF$
asm.s + "org 100h" + #LF$
asm.s + "xor eax, eax" + #LF$
asm.s + "mov eax, 100" + #LF$
asm.s + "add eax, 20" + #LF$
asm.s + "ret" + #LF$
flags = #MB_YESNO | #MB_ICONINFORMATION
hWnd = 0
szTitle.s = "Hello World!!"
szMessage.s = "This function was executed through an FASM assembler via PureBasic! 0_o"
hwnd = 0
pfunc = @MessageBoxA()
asm2.s + "use32" + #LF$
asm2.s + "org 100h" + #LF$
asm2.s + "mov [esp+12], dword " + Str(flags) + "" + #LF$
asm2.s + "mov [esp+08], dword " + Str(@szTitle) + #LF$
asm2.s + "mov [esp+04], dword " + Str(@szMessage) + #LF$
asm2.s + "mov [esp+00], dword " + Str(hwnd) + #LF$
asm2.s + "xor eax, eax" + #LF$
asm2.s + "mov ecx, dword " + Str(@MessageBoxA()) + "" + #LF$
asm2.s + "call ecx" + #LF$
asm2.s + "ret" + #LF$
dwSize.l = 0
; works, returns 120
*myMessageBox.fasm_Procedure = fasm_Compile(@asm, @dwSize)
If(*myMessageBox)
Debug *myMessageBox()
fasm_Free(*myMessageBox)
EndIf
; Doesn't work, tries interpreting the MessageBoxA result as memory address?
*myMessageBox.fasm_Procedure = fasm_Compile(@asm2, @dwSize)
If(*myMessageBox)
Debug *myMessageBox()
fasm_Free(*myMessageBox)
EndIf
EndIf

| ; The following structure resides at the beginning of memory block provided
| ; to the fasm_Assemble function. The condition field contains the same value
| ; as the one returned by function.
| ; When function returns FASM_OK condition, the output_length and
| ; output_data fields are filled - with pointer to generated output
| ; (somewhere within the provided memory block) and the count of bytes stored
| ; there.
| ; When function returns FASM_ERROR, the error_code is filled with the
| ; code of specific error that happened and error_line is a pointer to the
| ; LINE_HEADER structure, providing information about the line that caused
| ; the error.
| Structure FASM_STATE
| condition.l
| StructureUnion
| output_length.l
| error_code.l
| EndStructureUnion
| StructureUnion
| output_data.l
| error_line.l
| EndStructureUnion
| EndStructure
| ; The following structure has two variants - it either defines the line
| ; that was loaded directly from source, or the line that was generated by
| ; macroinstruction. First case has the highest bit of line_number set to 0,
| ; while the second case has this bit set.
| ; In the first case, the file_path field contains pointer to the path of
| ; source file (empty string if it's the source that was provided directly to
| ; fasm_Assemble function), the line_number is the number of line within
| ; that file (starting from 1) and the file_offset field contains the offset
| ; within the file where the line starts.
| ; In the second case the macro_calling_line field contains the pointer to
| ; LINE_HEADER structure for the line which called the macroinstruction, and
| ; the macro_line field contains the pointer to LINE_HEADER structure for the
| ; line within the definition of macroinstruction, which generated this one.
| Structure LINE_HEADER
| file_path.l
| line_number.l
| StructureUnion
| file_offset.l
| macro_calling_line.l
| EndStructureUnion
| Macro_line.l
| EndStructure
| ; General errors and conditions
| #FASM_OK = 0 ; FASM_STATE points to output
| #FASM_WORKING = 1
| #FASM_ERROR = 2 ; FASM_STATE contains error code
| #FASM_INVALID_PARAMETER = -1
| #FASM_OUT_OF_MEMORY = -2
| #FASM_STACK_OVERFLOW = -3
| #FASM_SOURCE_NOT_FOUND = -4
| #FASM_UNEXPECTED_END_OF_SOURCE = -5
| #FASM_CANNOT_GENERATE_CODE = -6
| #FASM_FORMAT_LIMITATIONS_EXCEDDED = -7
| #FASM_WRITE_FAILED = -8
| ; Error codes for FASM_ERROR condition
| #FASMERR_FILE_NOT_FOUND = -101
| #FASMERR_ERROR_READING_FILE = -102
| #FASMERR_INVALID_FILE_FORMAT = -103
| #FASMERR_INVALID_MACRO_ARGUMENTS = -104
| #FASMERR_INCOMPLETE_MACRO = -105
| #FASMERR_UNEXPECTED_CHARACTERS = -106
| #FASMERR_INVALID_ARGUMENT = -107
| #FASMERR_ILLEGAL_INSTRUCTION = -108
| #FASMERR_INVALID_OPERAND = -109
| #FASMERR_INVALID_OPERAND_SIZE = -110
| #FASMERR_OPERAND_SIZE_NOT_SPECIFIED = -111
| #FASMERR_OPERAND_SIZES_DO_NOT_MATCH = -112
| #FASMERR_INVALID_ADDRESS_SIZE = -113
| #FASMERR_ADDRESS_SIZES_DO_NOT_AGREE = -114
| #FASMERR_DISALLOWED_COMBINATION_OF_REGISTERS = -115
| #FASMERR_LONG_IMMEDIATE_NOT_ENCODABLE = -116
| #FASMERR_RELATIVE_JUMP_OUT_OF_RANGE = -117
| #FASMERR_INVALID_EXPRESSION = -118
| #FASMERR_INVALID_ADDRESS = -119
| #FASMERR_INVALID_VALUE = -120
| #FASMERR_VALUE_OUT_OF_RANGE = -121
| #FASMERR_UNDEFINED_SYMBOL = -122
| #FASMERR_INVALID_USE_OF_SYMBOL = -123
| #FASMERR_NAME_TOO_LONG = -124
| #FASMERR_INVALID_NAME = -125
| #FASMERR_RESERVED_WORD_USED_AS_SYMBOL = -126
| #FASMERR_SYMBOL_ALREADY_DEFINED = -127
| #FASMERR_MISSING_END_QUOTE = -128
| #FASMERR_MISSING_END_DIRECTIVE = -129
| #FASMERR_UNEXPECTED_INSTRUCTION = -130
| #FASMERR_EXTRA_CHARACTERS_ON_LINE = -131
| #FASMERR_SECTION_NOT_ALIGNED_ENOUGH = -132
| #FASMERR_SETTING_ALREADY_SPECIFIED = -133
| #FASMERR_DATA_ALREADY_DEFINED = -134
| #FASMERR_TOO_MANY_REPEATS = -135
| #FASMERR_SYMBOL_OUT_OF_SCOPE = -136
| #FASMERR_USER_ERROR = -140
| #FASMERR_ASSERTION_FAILED = -141
| DataSection
| fasm_dll: IncludeBinary "FASM.dll"
| EndDataSection
| Prototype.l fasm_GetVersion()
| Prototype.l fasm_Assemble(*lpszSource, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Prototype.l fasm_AssembleFile(*lpszSourceFile, *lpChunk, dwMemorySize.l, dwPassesLimit = 100, hDisplayPipe = #Null)
| Prototype.l fasm_Procedure()
| Global fasm_GetVersion .fasm_GetVersion = 0
| Global fasm_Assemble .fasm_Assemble = 0
| Global fasm_AssembleFile.fasm_AssembleFile = 0
| Global fasm_hLibrary = 0
| Procedure fasm_init()
| fasm_hLibrary = LoadLibraryM(?fasm_dll)
| If(fasm_hLibrary)
| fasm_GetVersion = GetProcAddressM(fasm_hLibrary, "fasm_GetVersion")
| fasm_Assemble = GetProcAddressM(fasm_hLibrary, "fasm_Assemble")
| fasm_AssembleFile = GetProcAddressM(fasm_hLibrary, "fasm_AssembleFile")
| ProcedureReturn 1
| EndIf
| EndProcedure
| Procedure fasm_close()
| If(fasm_hLibrary)
| FreeLibraryM(fasm_hLibrary)
| fasm_GetVersion = 0
| fasm_Assemble = 0
| fasm_AssembleFile = 0
| EndIf
| EndProcedure
| Procedure fasm_Compile(*lpszSource, *lpdwBufferSize = 0)
| Protected result = 0
| Protected chunkSize.l = 4096
| Protected *line.LINE_HEADER = 0
| Protected *lpOut.FASM_STATE = AllocateMemory(chunkSize)
| If(*lpOut)
| Protected assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
| If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
| Debug "Error"
| Debug *lpOut\error_code
| *line = *lpOut\error_line
| Debug *line\line_number
| Else
| While(assemblerResult = #FASM_OUT_OF_MEMORY)
| chunkSize + 1024
| *lpOut.FASM_STATE = ReAllocateMemory(*lpOut, chunkSize)
| assemblerResult.l = fasm_Assemble(*lpszSource, *lpOut, SizeOf(FASM_STATE) + chunkSize)
| If(assemblerResult <> #FASM_OK And assemblerResult <> #FASM_OUT_OF_MEMORY)
| Debug "Error"
| Debug *lpOut\error_code
| *line = *lpOut\error_line
| Debug *line\line_number
| Break
| EndIf
| Wend
| If(assemblerResult = #FASM_OK)
| *vm = VirtualAlloc_(#Null, *lpOut\output_length, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
| If(*vm)
| CopyMemory(*lpOut\output_data, *vm, *lpOut\output_length)
| If(*lpdwBufferSize)
| PokeL(*lpdwBufferSize, *lpOut\output_length)
| EndIf
| result = *vm
| EndIf
| EndIf
| EndIf
| FreeMemory(*lpOut)
| EndIf
| ProcedureReturn result
| EndProcedure
| Procedure fasm_Free(*lpvm)
| VirtualFree_(*lpvm, 0, #MEM_RELEASE)
| EndProcedure
| Import "user32.lib"
| MessageBoxA(hWnd.l, szMessage.s, szTitle.s, dwFlags.l)
| EndImport
| If(fasm_init())
| ; works
| asm.s + "use32" + #LF$
| asm.s + "org 100h" + #LF$
| asm.s + "xor eax, eax" + #LF$
| asm.s + "mov eax, 100" + #LF$
| asm.s + "add eax, 20" + #LF$
| asm.s + "ret" + #LF$
| flags = #MB_YESNO | #MB_ICONINFORMATION
| hWnd = 0
| szTitle.s = "Hello World!!"
| szMessage.s = "This function was executed through an FASM assembler via PureBasic! 0_o"
| hwnd = 0
| pfunc = @MessageBoxA()
| asm2.s + "use32" + #LF$
| asm2.s + "org 100h" + #LF$
| asm2.s + "mov [esp+12], dword " + Str(flags) + "" + #LF$
| asm2.s + "mov [esp+08], dword " + Str(@szTitle) + #LF$
| asm2.s + "mov [esp+04], dword " + Str(@szMessage) + #LF$
| asm2.s + "mov [esp+00], dword " + Str(hwnd) + #LF$
| asm2.s + "xor eax, eax" + #LF$
| asm2.s + "mov ecx, dword " + Str(@MessageBoxA()) + "" + #LF$
| asm2.s + "call ecx" + #LF$
| asm2.s + "ret" + #LF$
| dwSize.l = 0
| ; works, returns 120
| *myMessageBox.fasm_Procedure = fasm_Compile(@asm, @dwSize)
| If(*myMessageBox)
| Debug *myMessageBox()
| fasm_Free(*myMessageBox)
| EndIf
| ; Doesn't work, tries interpreting the MessageBoxA result as memory address?
| *myMessageBox.fasm_Procedure = fasm_Compile(@asm2, @dwSize)
| If(*myMessageBox)
| Debug *myMessageBox()
| fasm_Free(*myMessageBox)
| EndIf
| EndIf

_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

wilbert

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:21 pm

Enthusiast

Joined: Sun Aug 08, 2004 5:21 am
Posts: 751
Location: Netherlands

What is LoadLibraryM ?
I get an error message on that.

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:25 pm

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

LoadLibraryM is a procedure from the LoadDllMemory library in PBOSL
http://pbosl.purearea.net/index.php?site=Libs
It allows you to load a library from a memory buffer (e.g. a IncludeBinary label) and
call its functions.
_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

wilbert

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:33 pm

Enthusiast

Joined: Sun Aug 08, 2004 5:21 am
Posts: 751
Location: Netherlands

Got it
Not about your problem, simply push your variables like this
Code:
asm2.s + "push dword " + Str(flags) + "" + #LF$
asm2.s + "push dword " + Str(@szTitle) + #LF$
asm2.s + "push dword " + Str(@szMessage) + #LF$
asm2.s + "push dword " + Str(hwnd) + #LF$
instead of using the mov instruction.
Windows internal calls are usually stdcall meaning that the called procedure cleans up the stack.
So after the procedure is done, it adjusts the stack pointer for the four dwords you placed on the stack but since your code didn't change the stack pointer, it crashes.

Top |

jack

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:36 pm

Addict

Joined: Fri Apr 25, 2003 11:10 pm
Posts: 804

yes, I just found out the same thing.

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:37 pm

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

Ahh great, that works, thanks mate! The additional info is appreciated too!
Awesome, I like this haha!
_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

jack

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 2:53 pm

Addict

Joined: Fri Apr 25, 2003 11:10 pm
Posts: 804

Trond posted some code to compile expressions to asm that you may find interesting viewtopic.php?f=7&t=18257&start=30
he also started compiler tutorial somewhere.

Top |

Crusiatus Black

Post subject: Re: Real-time machine-code execution Posted: Tue Sep 04, 2012 3:25 pm

Enthusiast

Joined: Mon May 12, 2008 1:25 pm
Posts: 139
Location: The Netherlands

Cool, that's a fun read! Thanks. With this FASM dll one could execute the generated code!
_________________
Bas Groothedde,
Imagine Programming
I live in a philosophical paradoxal randome filled with enigma's!

Top |

DoctorLove

Post subject: Re: Real-time machine-code execution Posted: Wed Sep 05, 2012 9:58 am

User

Joined: Sat Mar 06, 2010 2:55 pm
Posts: 57

Well, im doing it all with http://www.oxygenbasic.org/
Its a simple DLL which compiles and execute basic code on the fly.
The language is Mature and basic to learn.
MAC osx and Linux are in the making.
Im sold to it.

Top |

Display posts from previous: Sort by

| [ 19 posts ] | Go to page 1, 2 Next

All times are UTC + 1 hour

#### Who is online

Users browsing this forum: No registered users and 10 guests

| You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum

Search for:

Jump to:

Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye