MCode4GCC -- C/C++ to MCode Generator - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=4642
MCode Tutorial (Compiled Code in AHK) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=32
MCode tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=11&t=116
- I have created a stand-alone script to convert C++ code to machine code.
- I have assumed that you can strip trailing 0x90 bytes from the end of machine code. Is this correct?
- Does it make a difference speed-wise whether you define the C++ function as Cdecl or Stdcall?
- I based the command-line text off of joedf's script, can anyone explain the role of vPathTempX and 2>, or indicate any good sources re. the command-line text. (The GCC documentation is quite hard to follow.)
- Any suggestions for different command-line parameters to use would be welcome.
- Any comments are welcome. Thanks.
Code: Select all
;to download TDM-GCC 64-bit version:
;TDM-GCC : Download
;http://tdm-gcc.tdragon.net/download
;based on:
;MCode4GCC -- C/C++ to MCode Generator - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=4642
;links:
;Using the GNU Compiler Collection (GCC): Invoking GCC
;https://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html
;InBuf function currently 32-bit only (machine code binary buffer searching) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=28393&p=219717#p219717
;==================================================
;q:: ;C++ to machine code via TDM-GCC
vPathTempPart := A_Desktop "\z gcc temp"
vPathCp := "C:\TDM-GCC-64\bin\gcc.exe"
if !FileExist(vPathCp)
{
MsgBox, % "error: file not found:`r`n" vPathCp
return
}
;vCode := JEE_GetSelectedText()
vCode := Clipboard
if (vCode = "")
{
MsgBox, % "error: no C++ code"
return
}
if 0
vCode = ;continuation section
(Join`r`n
int TheAnswerToEverything() {
return 42;
}
)
vFlags:= "-O3 "
vList := "32,64"
Loop, Parse, vList, % ","
{
vBits := A_LoopField
vMCode := "vMCode" vBits
vAsm := TdmGccCppToAsm(vCode, vPathCp, vFlags " -m" vBits, vPathTempPart, vLog)
;MsgBox, % vAsm
%vMCode% := TdmGccAsmToMCode(vAsm)
while RegExMatch(%vMCode%, "90$")
%vMCode% := SubStr(%vMCode%, 1, -2)
%vMCode% := Hex2Base64(%vMCode%)
%vMCode% := Trim(%vMCode%, "`r`n")
;MsgBox, % vLog
}
;vOutput := vMCode32 "`r`n" vMCode64
vOutput := "2,x86:" vMCode32 ",x64:" vMCode64
Clipboard := vOutput
MsgBox, % vOutput
return
;==================================================
;e.g.
/*
// set first ANSI character
int stringwrite(char *str)
{
str[0] = 123;
return 1;
}
*/
;x32 and x64 hex
;8B442404C6007BB801000000C3909090
;B801000000C6017BC390909090909090
;x32 and x64 hex (trailing 90s stripped)
;8B442404C6007BB801000000C3
;B801000000C6017BC3
;x32 and x64 base64 (trailing 90s stripped)
;2,x86:i0QkBMYAe7gBAAAAww==,x64:uAEAAADGAXvD
;==================================================
Hex2Base64(hex) {
sz:=StringToBinary(b,hex)
Base64enc(out,b,sz)
VarSetCapacity(out,-1) ; Strip everything after first null byte
;return SubStr(out,1,sz) ; Strip garbage at the end
return out
}
;http://www.autohotkey.com/board/topic/85709-base64enc-base64dec-base64-encoder-decoder/
Base64enc( ByRef OutData, ByRef InData, InDataLen ) { ; by SKAN
DllCall("Crypt32.dll\CryptBinaryToString" (A_IsUnicode?"W":"A")
,UInt,&InData,UInt,InDataLen,UInt,1,UInt,0,UIntP,TChars,"CDECL Int")
VarSetCapacity(OutData,Req:=TChars*(A_IsUnicode?2:1))
DllCall("Crypt32.dll\CryptBinaryToString" (A_IsUnicode?"W":"A")
,UInt,&InData,UInt,InDataLen,UInt,1,Str,OutData,UIntP,Req,"CDECL Int")
Return TChars
}
; BinaryToString() / StringToBinary() from laszlo, updated by joedf
; http://ahkscript.org/forum/viewtopic.php?p=304556#304556
; fmt = 1:base64, 4:hex-table, 5:hex+ASCII, 10:offs+hex, 11:offs+hex+ASCII, 12:raw-hex
StringToBinary(ByRef bin, hex, fmt=12) { ; return length, result in bin
DllCall("Crypt32.dll\CryptStringToBinary","Str",hex,"UInt",StrLen(hex),"UInt",fmt,"UInt",0,"UInt*",cp,"UInt",0,"UInt",0,"CDECL UInt") ; get size
VarSetCapacity(bin,cp)
DllCall("Crypt32.dll\CryptStringToBinary","Str",hex,"UInt",StrLen(hex),"UInt",fmt,"UInt",&bin,"UInt*",cp,"UInt",0,"UInt",0,"CDECL UInt")
Return cp
}
;==================================================
TdmGccCppToAsm(vCode, vPathCP, vFlags:="", vPathTempPart:="", ByRef vLog:="")
{
if (vPathTempPart = "")
vPathTempPart := A_Desktop "\z gcc temp"
SplitPath, vPathTempPart,, vPathTempDir
if !FileExist(vPathTempDir)
FileCreateDir, % vPathTempDir
if !FileExist(vPathTempDir)
{
MsgBox, % "error: dir not found:`r`n" vPathTempDir
Exit
}
vPathTempSource := vPathTempPart " source.c"
vPathTempAsm := vPathTempPart " asm"
vPathTempX := vPathTempPart " x"
vPathTempLog := vPathTempPart " log"
FileAppend, % vCode "`r`n", % "*" vPathTempSource
if !FileExist(vPathCP)
return 0
EnvGet, vEnvPath, Path
SplitPath, vPathCP,, vDirCP
EnvSet, Path, % vDirCP
;MsgBox, %ComSpec% /c %vPathCP% %vFlags% -Wa`,-aln="%vPathTempAsm%" "%vPathTempSource%" -o "%vPathTempX%" 2> "%vPathTempLog%",, UseErrorLevel Hide
RunWait, %ComSpec% /c %vPathCP% %vFlags% -Wa`,-aln="%vPathTempAsm%" "%vPathTempSource%" -o "%vPathTempX%" 2> "%vPathTempLog%",, UseErrorLevel Hide
vErrorCP := ErrorLevel
EnvSet, Path, % vEnvPath
if (vErrorCP = "ERROR")
return 0
FileRead, vAsm, % vPathTempAsm
FileRead, vLog, % vPathTempLog
;MsgBox, % vAsm
;MsgBox, % vLog
FileDelete, % vPathTempSource
FileDelete, % vPathTempAsm
FileDelete, % vPathTempX
FileDelete, % vPathTempLog
return vAsm
}
;==================================================
TdmGccAsmToMCode(vAsm, vDoClean:=1)
{
if vDoClean
{
vAsm2 := vAsm, vAsm := ""
Loop, Parse, vAsm2, `n, `r
{
if InStr(A_LoopField, ".ident " """" "GCC: (GNU)")
break
vAsm .= A_LoopField "`n"
}
}
vPos := 1, vMatch := "", vOutput := ""
;old-style (to variables)
;while vPos := RegExMatch(vAsm, "`ami)^\s*\d+(\s[\dA-F]{4}\s|\s{6})([\dA-F]+)", vMatch, vPos+StrLen(vMatch))
; MsgBox, % vMatch2
;while vPos := RegExMatch(vAsm, "`ami)^\s*\d+(\s[\dA-F]{4}\s|\s{6})([\dA-F]+)", vMatch, vPos+StrLen(vMatch))
; vOutput .= vMatch2
;new-style (to RegExMatch object)
;while vPos := RegExMatch(vAsm, "O`ami)^\s*\d+(\s[\dA-F]{4}\s|\s{6})([\dA-F]+)", oMatch, vPos+StrLen(oMatch.0))
; MsgBox, % oMatch.2
while vPos := RegExMatch(vAsm, "O`ami)^\s*\d+(\s[\dA-F]{4}\s|\s{6})([\dA-F]+)", oMatch, vPos+StrLen(oMatch.0))
vOutput .= oMatch.2
return vOutput
}
;==================================================