Jump to content

The Embedded Flat Assembler (FASM) UDF


Ward
 Share

Recommended Posts

This UDF is similar to my previous Inline Assembly UDF, but only better. Because this one uses flat assembler, a open source and powerful assembler. See http://flatassembler.net/. Thanks to XDa from http://www.opensc.ws/ provide a "fasm.dll". So my job is just easy, warp it using my MemoryDll UDF.

 

The usage is also similar to previously, but a kind of different. FasmGetFuncPtr() will compile the source and return the address ready to be call. And FasmGetBasePtr() only return the base address without compiling and error handling. FasmGetBasePtr() is added for "org" directive.

 

Have fun. Maybe also take a look at AndyG's Fractals script.

 

FASM.zip (55.47K)

Number of downloads: 127

 

2010/03/19 Update Note:

# Embedded FASM version update to v1.68

# Add OOP version using AutoItObject, thanks to AutoItObject-Team

# New examples

# Better error handling, can handle errors in macro now

FASM.zip (141.76K)

Number of downloads: 601

 

2011/06/14 Update Note:

# Embedded FASM version update to v1.69

# AutoItObject UDF version update to v1.2.8.0

# MemoryDLL UDF update to X64 supported version

# New BinaryCall UDF to run a machine code in "Binary" format

# Add FASMServer and FASMServerDemo, demonstrate embedded assembly in AutoIt X64

# Add fast BinaryXOR function (Both X86/X64) as an example (in FASMServerDemo2)

FASM.zip

Edited by Ward

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Link to comment
Share on other sites

Thanks a lot for this sharing this ward. Great little examples too. Very helpful. 5*. :(

Link to comment
Share on other sites

Do you know if there is a way I can pass parameters to the autoit functions?

Link to comment
Share on other sites

Do you know if there is a way I can pass parameters to the autoit functions?

It is easy:

#include "FASM.au3"
Dim $Fasm = FasmInit()
Demo7()

Func Demo7()
    ; Demo 7: Call AutoIt Func From Assembly And Pass Parameters
    $AutoItFunc = DllCallbackRegister("AutoItFunc2", "int", "str;uint;uint")
    FasmReset($Fasm)
    FasmAdd($Fasm, "use32") 
    FasmAdd($Fasm, "org " & FasmGetBasePtr($Fasm))
    FasmAdd($Fasm, "rdtsc")
    FasmAdd($Fasm, "push eax")
    FasmAdd($Fasm, "push edx")
    FasmAdd($Fasm, "push s1")
    FasmAdd($Fasm, "call " & DllCallbackGetPtr($AutoItFunc))
    FasmAdd($Fasm, "ret")
    FasmAdd($Fasm, "s1: db 'RDTSC = %08X%08X', 0")
    ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)
    $Ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm))
    DllCallbackFree($AutoItFunc)
EndFunc

Func AutoItFunc2($String, $Edx, $Eax)
    MsgBox(0, "AutoItFunc", StringFormat($String, $Edx, $Eax))
EndFunc

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Link to comment
Share on other sites

Thanks ward. That helped a lot. :(

But now I'm confused on why the data in s1 gets set after the 'ret'. I figured it would be the other way around.

FasmAdd($Fasm, "s1: db 'RDTSC = %08X%08X', 0")
FasmAdd($Fasm, "ret")

Anyway, just another item on the list of "things to read and learn about." Thanks again.

Edited by Beege
Link to comment
Share on other sites

Excellent job again Ward.

Out of curiosity, since FASM supports x64 code ('use64'), what would you say the chances are of someday compiling & integrating a 64-bit DLL. I'm getting well versed in x64 code so I'd be able to provide 64-bit versions of the Examples for ya.

Thanks again for all your work

Ascend4nt

Link to comment
Share on other sites

  • 1 year later...
  • 1 year later...

I like this UDF. It generates very fast and compact code. To see some working examples where it's used to optimize loops and fix x64 issues take a look at this example. See section 1.6 and 1.7. If you have downloaded the examples and want to take a closer look at one of the optimizations go to "OpenGL 1.1TexturesTunnelsutilitiesfasm". I have left the test files (with -a and -b in the names) to optimize loops in "Tunnel effect 2.au3".

When I write assembler source I like to write it in a format like shown in the code boxes.

This is an example with MessageBoxA:

; FASM assembler code

        ; MessageBoxA( hWnd, lpText, lpCaption, uType )

        ; $tData = DllStructCreate( "byte[80];byte[16];handle;ptr[3]" )
        ; Element 3, index 1, offset  96 ( 96) : handle hWnd
        ; Element 4, index 1, offset 100 (104) : ptr    lpText
        ; Element 4, index 2, offset 104 (112) : ptr    lpCaption
        ; Element 4, index 3, offset 108 (120) : ptr    MessageBoxA
        ; (Numbers in brackets are x64 offsets)

        ; Parameters:
        ; [ebp + 08] : uType
        ; [ebp + 12] : $pData

        use32
        push       ebp
        mov        ebp,                esp

        mov        eax,                [ebp + 12]          ; eax is pointer in $tData table

        ; Call MessageBoxA
        ;pusha                                              ; Save registers on stack
        push       dword [ebp +  08]                       ; 4. parameter: uType
        push       dword [eax + 104]                       ; 3. parameter: lpCaption
        push       dword [eax + 100]                       ; 2. parameter: lpText
        push       dword [eax +  96]                       ; 1. parameter: hWnd
        call       dword [eax + 108]                       ; Call MessageBoxA
        ;popa                                               ; Restore registers

        pop        ebp
        ret        08
And the x64 code:

; FASM assembler code

        ; MessageBoxA( hWnd, lpText, lpCaption, uType )

        ; $tData = DllStructCreate( "byte[80];byte[16];handle;ptr[3]" )
        ; Element 3, index 1, offset  96 ( 96) : handle hWnd
        ; Element 4, index 1, offset 100 (104) : ptr    lpText
        ; Element 4, index 2, offset 104 (112) : ptr    lpCaption
        ; Element 4, index 3, offset 108 (120) : ptr    MessageBoxA
        ; (Numbers in brackets are x64 offsets)

        ; Parameters:
        ; rcx : uType
        ; rdx : $pData

        ; x64 function calling convention for parameter passing:
        ; First  parameter: int/ptr -> rcx,  float -> xmm0
        ; Second parameter: int/ptr -> rdx,  float -> xmm1
        ; Third  parameter: int/ptr -> r8,   float -> xmm2
        ; Fourth parameter: int/ptr -> r9,   float -> xmm3
        ; The rest goes onto the stack

        use64

        mov        rax,                rdx                 ; rax is pointer in $tData table

        ; Call MessageBoxA
        sub        rsp,                40                  ; Stack space and alignment
        mov        r9,                 rcx                 ; 4. parameter: uType
        mov        rcx,                qword [rax +  96]   ; 1. parameter: hWnd
        mov        rdx,                qword [rax + 104]   ; 2. parameter: lpText
        mov        r8,                 qword [rax + 112]   ; 3. parameter: lpCaption
        call       qword [rax + 120]                       ; Call MessageBoxA
        add        rsp,                40                  ; Restore stack pointer

        ret
Note that FASM.au3 cannot be run as a 64 bit program. But it certainly can generate 64 bit code. To generate the binary code run MessageBoxA-x64-mk-bin.au3.

This is the AutoIt program to call the assembler functions:

#include "Includes\Utilities.au3"

Opt( "MustDeclareVars", 1 )

Global $hGui = GUICreate( "MessageBoxA demo with FASM", 400, 300 )

Global $pCode, $pData, $tData

GetFasmCode()
GUISetState()
MessageBoxA1()
MessageBoxA2()

Func GetFasmCode()

    ; --- Fasm data ---

    ; MessageBoxA( hWnd, lpText, lpCaption, uType )

    ; Use a struct to pass data from AutoIt to the assembler function. uType will be passed as a parameter.

    $tData = DllStructCreate( "byte[80];byte[16];handle;ptr[3]" )
    ; To make things easier add extra space in tables in the structure until they are 8-bytes aligned. It's also 
    ; nice to have a little bit of extra space. Then you can use this space for an intermediate result, if that
    ; should be necessary. Without the need to change all the offsets. It seems also to be easier to put the
    ; x86/x64 dependant data e.g. handle and ptr in the end of the structure.

    DllStructSetData( $tData, 3, $hGui )                           ; Element 3, index 1, offset  96 ( 96) : handle hWnd
    DllStructSetData( $tData, 4, DllStructGetPtr( $tData, 1 ), 1 ) ; Element 4, index 1, offset 100 (104) : ptr    lpText
    DllStructSetData( $tData, 4, DllStructGetPtr( $tData, 2 ), 2 ) ; Element 5, index 2, offset 104 (112) : ptr    lpCaption
    Local $ptr = GetProcAddress( "user32.dll", "MessageBoxA" )
    DllStructSetData( $tData, 4, $ptr, 3 )                         ; Element 4, index 3, offset 108 (120) : ptr    MessageBoxA
                                                                   ; (Numbers in brackets are x64 offsets)
    $pData = DllStructGetPtr( $tData )

    ; --- Fasm code ---

    Local $sCode, $tCode

    If @AutoItX64 Then
        If Not ReadX64code( "MessageBoxA-x64.bin", "MessageBoxA-x64-mk-bin.au3", $sCode ) Then Exit
    Else
        Local $oFasm = FasmInit()
        If Not ReadFasmCode( "MessageBoxA.asm", $oFasm, $sCode ) Then Exit
        FasmExit( $oFasm )
    EndIf
    $pCode = _MemVirtualAlloc( 0, 128, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE )
    $tCode = DllStructCreate( "byte[128]", $pCode )
    DllStructSetData( $tCode, 1, $sCode )

EndFunc

Func MessageBoxA1()

    SetTextCaption( "This is the first test.", "Test 1" )

    DllCallAddress( "none", $pCode, "uint", 0, "ptr", $pData )

EndFunc

Func MessageBoxA2()

    SetTextCaption( "This is the second test.", "Test 2" )

    Local $aRet = DllCallAddress( "int", $pCode, "uint", 33, "ptr", $pData ), $sText
    If $aRet[0] = 1 Then                               ; 33 = OK + Cancel + Question-mark icon
        $sText = "OK button."
    Else
        $sText = "Cancel button (or close)."
    EndIf
    SetTextCaption( $sText, "Clicked" )
    DllCallAddress( "none", $pCode, "uint", 0, "ptr", $pData )

EndFunc

Func SetTextCaption( $sText, $sCaption )
    ; MessageBoxA( hWnd, lpText, lpCaption, uType )
    ; $tData = DllStructCreate( "byte[80];byte[16];uint[2];handle;ptr[3]" )
    DllStructSetData( $tData, 1, $sText )                          ; Element 1, index 1, offset   0       : byte   $sText
    DllStructSetData( $tData, 1, 0, StringLen( $sText ) + 1 )      ; Null-terminated string
    DllStructSetData( $tData, 2, $sCaption )                       ; Element 2, index 1, offset  80       : byte   $sCaption
    DllStructSetData( $tData, 2, 0, StringLen( $sCaption ) + 1 )   ; Null-terminated string
EndFunc
You find the utility functions GetProcAddress, ReadFasmCode, MakeX64code, ReadX64code and the MessageBoxA files here:

MessageBoxA.7z

Copy BinaryCall.au3, FASM.au3 and MemoryDll.au3 from Ward's UDF to the Includes folder when you extract the 7z-file.

Links

flat assembler

Programmer's Manual

Intel® 64 and IA-32 Architectures Software Developer Manuals

Introduction to 64 Bit Intel Assembly Language

x64 Software Conventions

The Art of Assembly Language

Edited by LarsJ
Link to comment
Share on other sites

  • 2 years later...
Link to comment
Share on other sites

I found FASM.zip on my old XP. Downloaded october 2012.

FASM.zip

File is corrupted ?

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 *

 

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE * IE on Windows 11

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Link to comment
Share on other sites

  • 3 months later...
  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...