Author Topic: Inline 64-bit assembly  (Read 466 times)

Vortex

  • Full Member
  • ***
  • Posts: 116
    • View Profile
Inline 64-bit assembly
« on: October 01, 2023, 04:32:08 AM »
Hello,

Some C compilers are not allowing inline 64-bit assembly instructions. A workaround is to define an array of machine code and copying this to a memory portion allowed to execute code.

Code assembled with Poasm V12.00.1 :

Code: [Select]
.code

CallFunc64 PROC function:QWORD,ArgNumb:QWORD,ArrayOfParams:QWORD

NumbOfArgs TEXTEQU <QWORD PTR [rsp+16+136]>
func       TEXTEQU <QWORD PTR [rsp+8+136]>


    sub     rsp,8+16*8                 ; 8 bytes   = stack alignment
                                       ; 16 params = reserve shadow space
                                       ;             for maximum 16 params

;   Store the parameters rcx and rdx in the shadow space
;   as they will be overwritten later

    mov     QWORD PTR [rsp+8+136],rcx  ; store the function
    mov     QWORD PTR [rsp+16+136],rdx ; store the number of args

    mov     rax,r8

    mov     rcx,QWORD PTR [rax]
    add     rax,8

OneArg:

    cmp     rdx,1                      ; rdx -> ArgNumb
    je      finish
       
TwoArgs:

    mov     rdx,QWORD PTR [rax]
    add     rax,8

    cmp     NumbOfArgs,2
    je      finish

ThreeArgs:

    mov     r8,QWORD PTR [rax]
    add     rax,8

    cmp     NumbOfArgs,3
    je      finish

FourArgs:

    mov     r9,QWORD PTR [rax]
    add     rax,8

    cmp     NumbOfArgs,4
    je      finish

MoreArgs:

    mov     r10,32
    sub     NumbOfArgs,4
@@:
    mov     r11,QWORD PTR [rax]
    mov     QWORD PTR [rsp+r10],r11
    add     rax,8
    add     r10,8
    dec     NumbOfArgs
    jnz     @b

finish:

    call    func
   
    add     rsp,8+16*8

    ret

CallFunc64 ENDP

END

The code above accepts 3 parameters. The first is the function to be called from the inline code. The two others are the number of the arguments to be passed to the function and the address of the first element of the paramater array.

Extracting the flat binary code from the object module with the GNU binary tool objcopy. This can be obtained from a MSYS2 installation :

Code: [Select]
objcopy --dump-section .text=CallFunc64.bin CallFunc64.obj
Dumping the binary file CallFunc64.bin with MrBcx's Dump utility :

https://bcxbasiccoders.com/smf/index.php?topic=936.msg4740#msg4740

The BCX code :

Code: [Select]
' Compile only to 64-bit

FUNCTION WINMAIN()

    LOCAL hMod AS HMODULE
    LOCAL ArrayOfParams[6] AS LONGLONG
    LOCAL Asm64 AS void PTR

    ArrayOfParams[0] = (LONGLONG) NULL
    ArrayOfParams[1] = (LONGLONG) "This message box will be destroyed after 4 seconds."
    ArrayOfParams[2] = (LONGLONG) "Hello"
    ArrayOfParams[3] = (LONGLONG) MB_ICONWARNING
    ArrayOfParams[4] = (LONGLONG) LANG_NEUTRAL
    ArrayOfParams[5] = (LONGLONG) 4000 ' Timeout after 4 seconds

    hMod = LOADLIBRARY("user32.dll")

    SET InlineAsm [] AS UCHAR
        72, 129, 236, 136, 0, 0, 0, 72, 137, 140, 36, 144, 0, 0, 0, 72, 137, _
        148, 36, 152, 0, 0, 0, 76, 137, 192, 72, 139, 8, 72, 131, 192, 8, 72, _
        131, 250, 1, 116, 95, 72, 139, 16, 72, 131, 192, 8, 72, 131, 188, 36, _
        152, 0, 0, 0, 2, 116, 77, 76, 139, 0, 72, 131, 192, 8, 72, 131, 188, 36, _
        152, 0, 0, 0, 3, 116, 59, 76, 139, 8, 72, 131, 192, 8, 72, 131, 188, 36, _
        152, 0, 0, 0, 4, 116, 41, 73, 199, 194, 32, 0, 0, 0, 72, 131, 172, 36, _
        152, 0, 0, 0, 4, 76, 139, 24, 78, 137, 28, 20, 72, 131, 192, 8, 73, 131, _
        194, 8, 72, 255, 140, 36, 152, 0, 0, 0, 117, 231, 255, 148, 36, 144, 0, 0, _
        0, 72, 129, 196, 136, 0, 0, 0, 195
    END SET

    Asm64 = VirtualAlloc(NULL, SIZEOF(InlineAsm), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
    memcpy(Asm64, InlineAsm, SIZEOF(InlineAsm))

    ((void (*)())Asm64)(GetProcAddress(hMod, "MessageBoxTimeoutA"), 6, ArrayOfParams)

    VirtualFree(Asm64, 0, MEM_RELEASE)
    FreeLibrary(hMod)

    FUNCTION = 0

END FUNCTION

This application displays a message box destroying itself after 4000 miliseconds. MessageBoxTimeout is an undocumented function :

https://www.codeproject.com/Articles/7914/MessageBoxTimeout-API

With thanks to MrBcx, here is a better method to implement DYNACALL :

https://bcxbasiccoders.com/smf/index.php?topic=952.0

Attached is the project containing the source files and the compiled executable.
« Last Edit: October 01, 2023, 04:53:10 AM by Vortex »