[2.0-a104] Simple InLine Asm

Post your working scripts, libraries and tools.
xroot
Posts: 40
Joined: 21 Jun 2019, 08:45

[2.0-a104] Simple InLine Asm

Post by xroot » 13 Sep 2019, 11:09

The simplest way I found to do inline ASM was to put opcodes and Mnemonics you use a lot in a Map.(see opcode.ahk)
When you add your own opcodes one important thing to remember is uniqueness. Example, the "ret" opcode.
How to distinguish "ret 4" from "ret"?
The Map:
opCode["ret word"] := "C2"
opCode["ret"] := "C3"
Usage:
,"ret word",8 ;C20800
,"ret" ;C3

Here is an example that calls AHK Function from Asm.

Code: Select all

#Include opcodes.ahk

Msg_Box(p1,p2,p3){
    Return &MsgBox(StrGet(p1),StrGet(p2),StrGet(p3))
}

; deBug := "`n"

pMB := CallbackCreate("Msg_Box")

flg := "ari iconi"
tit := "Call AHK Function With Asm Code"
txt := "AutoHotkey language bears some similarities to several other scripting languages but also has its own unique strengths and pitfalls."

Asm "push",&flg                 ;68408D3500
   ,"push",&tit                 ;68C08D3500
   ,"push",&txt                 ;6848123400
   ,"mov eax",pMB               ;B8782A3700
   ,"call eax"                  ;FFD0
   ,"ret"                       ;C3

msgbox StrGet(DllCall(bAsm.Ptr)),"Return Code","4160 t1"
When you first run your code remove comment from line. ; deBug := "`n"
Then paste by "column mode" next to your opcodes, this will show any errors.

Under "Scripts and Functions" in the AHK forum there is a post called "Examples of Non-Standard GUIs (ActiveX, GDI, etc.)".
Maybe this next example could be a Non-Standard Gui.

It is a modal dialog box from a dialog box template in memory with ASM.

Code: Select all

#Include winapi.ahk
#Include opcodes.ahk

No_FocusDots(hWin,uMsg,wParam,lParam,uIdSubclass,dwRefData){
    If(uMsg=WM_SETFOCUS)
        Return
    Return DefSubclassProc(hWin,uMsg,wParam,lParam)
}

Msg_Loop(hWin,uMsg,wParam,lParam){
    Switch(uMsg){
        Case WM_PAINT:
            BeginPaint hWin,ps.Buf
            DrawText hDC,winBody,ps.rcPaint,DT_CENTER
            EndPaint hWin,ps.Buf
        Case WM_INITDIALOG:
            hDC    := GetDC(hWin)
            hBnd   := GetDlgItem(hWin,ButtonID)
            hFont  := CreateFont(30,,,,800,,true,,,,,4,,"Times New Roman")
            NoDots := CallbackCreate("No_FocusDots")
            SelectObject hDC,hFont
            SetTextColor hDC,0x00ffff  ; Yellow
            SetBkColor hDC,0x800000    ; Navy
            SendMessage WM_SETICON,0,LoadImage(0,"crapper.ico",IMAGE_ICON),hWin
            SendMessage WM_SETFONT,hFont,true,hBnd
            SetWindowSubclass hBnd,NoDots,ButtonID
        Case WM_CTLCOLORDLG:
            Return Navy
        Case WM_COMMAND:
            If(wParam=IDCANCEL Or wParam=ButtonID){
                DeleteObject hFont
                ReleaseDC hWin,hDC
                RemoveWindowSubclass hBnd,NoDots,ButtonID
                EndDialog hWin,wParam
            }
    }
    Return
}

; MAIN INLINE ASM CODE AHK 2.0-a104 U32
; Creates a modal dialog box from a dialog box template in memory.

; deBug := "`n"

global ps       := new PAINTSTRUCT
global hDC      := 0
global ButtonID := 69
global Navy     := CreateSolidBrush(0x800000)
global winBody  := "`nInLine Asm Dialog Box`nWith No Focus Dots On Button"

Tit     := "AHK = Test ASM DialogBox"
Fnt     := "MS Sans Serif"
Quit    := "Q u i t"
DlgSize := 512
FntSize := 10
TitLen  := StrLen(Tit)+1
FntLen  := StrLen(Fnt)+1
QuitLen := StrLen(Quit)+1
bTit    := BufferAlloc(TitLen)
bFnt    := BufferAlloc(FntLen)
bQuit   := BufferAlloc(QuitLen)

StrPut Tit,bTit,"cp0"
StrPut Fnt,bFnt,"cp0"
StrPut Quit,bQuit,"cp0"

style    := WS_VISIBLE|WS_SYSMENU|WS_CAPTION|DS_CENTER|DS_SETFONT
xstyle   := WS_EX_CLIENTEDGE
c1Style  := WS_VISIBLE|WS_TABSTOP|BS_DEFPUSHBUTTON
c1XStyle := 0

x := 0,y := 0,w := 250,h := 180,ctlcnt := 1
cx1 := 180,cy1 := 140,cw1 := 50,ch1 := 25

pK32                    := LoadLibrary("kernel32")
pU32                    := LoadLibrary("user32")
pGlobalAlloc            := GetProcAddress(pK32,"GlobalAlloc")
pGlobalFree             := GetProcAddress(pK32,"GlobalFree")
pMultiByteToWideChar    := GetProcAddress(pK32,"MultiByteToWideChar")
pDialogBoxIndirectParam := GetProcAddress(pU32,"DialogBoxIndirectParamW")
MsgLoop                 := CallbackCreate("Msg_Loop")

; SetUp DialogBox
Asm "push esi"                                    ;56
   ,"push edi"                                    ;57
   ,"push",DlgSize                                ;6800020000
   ,"push byte",GPTR                              ;6A40
   ,"mov eax",pGlobalAlloc                        ;B8D651FE76
   ,"call eax"                                    ;FFD0
   ,"mov esi,eax"                                 ;8BF0
   ,"mov edi,esi"                                 ;8BFE
   ,"mov dword ptr[edi]",style                    ;C7074008C810
   ,"mov dword ptr[edi+4]",xstyle                 ;C7470400020000
   ,"mov word ptr[edi+8]",ctlcnt                  ;66C747080100
   ,"mov word ptr[edi+0A]",x                      ;66C7470A0000
   ,"mov word ptr[edi+0C]",y                      ;66C7470C0000
   ,"mov word ptr[edi+0E]",w                      ;66C7470EFA00
   ,"mov word ptr[edi+10]",h                      ;66C74710B400
   ,"add edi,byte",22                             ;83C716
   ,"push byte",TitLen                            ;6A1F
   ,"push edi"                                    ;57
   ,"push byte",-1                                ;6AFF
   ,"push",bTit.Ptr                               ;6878F0B000
   ,"push byte",1                                 ;6A01
   ,"push byte",0                                 ;6A00
   ,"call",160                                    ;E893000000    jmp_MultiByteToWideChar
   ,"add edi,byte",TitLen*2                       ;83C73E
   ,"mov word ptr[edi]",FntSize                   ;66C7070C00
   ,"add edi,byte",2                              ;83C702
   ,"push byte",FntLen                            ;6A0E
   ,"push edi"                                    ;57
   ,"push byte",-1                                ;6AFF
   ,"push",bFnt.Ptr                               ;68085DB000
   ,"push byte",1                                 ;6A01
   ,"push byte",0                                 ;6A00
   ,"call",130                                    ;E875000000    jmp_MultiByteToWideChar
   ,"add edi,byte",FntLen*2                       ;83C71C
; SetUp Button
;    align_4
   ,"add edi,byte",3                              ;83C703
   ,"and edi,byte",-4                             ;83E7FC

   ,"mov dword ptr[edi]",c1Style                  ;C70701000110
   ,"mov dword ptr[edi+4]",c1XStyle               ;C7470400000000
   ,"mov word ptr[edi+8]",cx1                     ;66C747085A00
   ,"mov word ptr[edi+0A]",cy1                    ;66C7470A3200
   ,"mov word ptr[edi+0C]",cw1                    ;66C7470C3200
   ,"mov word ptr[edi+0E]",ch1                    ;66C7470E0F00
   ,"mov word ptr[edi+10]",ButtonID               ;66C747104500
   ,"mov word ptr[edi+12]",-1                     ;66C74712FFFF
   ,"mov word ptr[edi+14]",Button                 ;66C747148000
   ,"add edi,byte",22                             ;83C716
   ,"push byte",QuitLen                           ;6A05
   ,"push edi"                                    ;57
   ,"push byte",-1                                ;6AFF
   ,"push",bQuit.ptr                              ;68880AA800
   ,"push byte",1                                 ;6A01
   ,"push byte",0                                 ;6A00
   ,"call",44                                     ;E81F000000    jmp_MultiByteToWideChar
   ,"add edi,byte",QuitLen*2                      ;83C70A
;    align_2
   ,"add edi,byte",1                              ;83C701
   ,"and edi,byte",-2                             ;83E7FE

   ,"add edi,byte",2                              ;83C702
; Call DialogBox
   ,"push byte",0                                 ;6A00
   ,"push",MsgLoop                                ;6818F1B000
   ,"push byte",0                                 ;6A00
   ,"push esi"                                    ;56
   ,"push byte",0                                 ;6A00
   ,"mov eax",pDialogBoxIndirectParam             ;B8F3D67676
   ,"call eax"                                    ;FFD0
   ,"push eax"                                    ;50
; Free Memory
   ,"push esi"                                    ;56
   ,"mov eax",pGlobalFree                         ;B8485F8375
   ,"call eax"                                    ;FFD0
   ,"pop eax"                                     ;58
   ,"pop edi"                                     ;5F
   ,"pop esi"                                     ;5E
   ,"ret"                                         ;C3
; Jmp_MultiByteToWideChar
   ,"jmp dword ptr[?]",&pMultiByteToWideChar      ;FF25E4E4B200

; Call Asm
DllCall bAsm.Ptr

FreeLibrary pU32
FreeLibrary pK32

; msgbox A_LastError,"Asm Return","t1"
Here are the Include files, please enjoy:
Includes.zip
(6.32 KiB) Downloaded 173 times

User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [2.0-a104] Simple InLine Asm

Post by nnnik » 13 Sep 2019, 12:56

Interesting concept :)
Recommends AHK Studio

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: [2.0-a104] Simple InLine Asm

Post by lexikos » 18 Sep 2019, 03:27

Return &MsgBox(...)
In general, the address of a string returned by a function should never be used outside of the expression that called the function.
The address operator can be used with other strings such as &"string", &(x . y) or &A_LoopField, with limitations:
• The addressed memory should never be modified, such as by passing it to a DllCall output parameter.
• An address taken from a temporary value (including one returned by a built-in variable) should be considered valid only until evaluation of the expression or function call statement completes. After this, the memory may be reused for something else.
MsgBox returns the address of a C string constant, so it is relatively safe; but most other functions do not work that way.

Temporary strings typically exist in the "deref buffer", which may be freed when the function returns, or in stack memory, which may be overwritten after the expression evaluator returns.

Post Reply

Return to “Scripts and Functions (v2)”