pixelsearch Posted June 2, 2023 Share Posted June 2, 2023 @Andreik I tried some asm these last days 1) First of all, I downloaded the last stable version 2.16.01 of nasm (netwide assembler) which is free, from the original nasm website and simply placed nasm.exe in a new folder C:\nasm The goal was to be able to "quickly" compile an .asm program and grab its corresponding .obj file, to use automatically its inner binary code with AutoIt DllCallAddress function, as you did in your 1st post. Then we can modify the asm code directly from the AutoIt Edit control, compile and test again etc... all this without leaving the script, while using 2 buttons named "Compile" and "Test code"2) To do that, I scripted a basic pattern (reusable when needed), a sort of "quick nasm compiler/tester with AutoIt" :expandcollapse popup #include <Array.au3> ; during tests #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <SendMessage.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) ;0=no (default), 1=require pre-declaration Opt("GUICloseOnESC", 0) ;1=ESC closes (default), 0=ESC won't close Global $g_Nasm_Path = "C:\nasm\", $g_Nasm_Exe = $g_Nasm_Path & "nasm.exe", $g_File_Err = $g_Nasm_Path & "nasmerr.err" Global $g_File_Asm = $g_Nasm_Path & "test.asm", $g_File_Obj = $g_Nasm_Path & "test.obj", $g_File_Lst = $g_Nasm_Path & "test.lst" Global $g_iGui_W = 900, $g_iGui_H = 600 Global $g_hGui = 0, $g_idEdit, $g_sAsmJustCompiled, $g_bJustCompiled, $g_sHexCode ; In case of global variables, add them here ; ... Main() ;============================================ Func Main() If Not FileExists($g_Nasm_Exe) Then Exit MsgBox($MB_TOPMOST, "File doesn't exist", $g_Nasm_Exe) $g_hGui = GUICreate("Nasm test (v1)", $g_iGui_W, $g_iGui_H, -1, -1, _ BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX), _ $WS_EX_ACCEPTFILES) ; accept to maximize & resize the GUI, also accept drag & drop $g_idEdit = GUICtrlCreateEdit("", 1, 1, _ $g_iGui_W - 2, $g_iGui_H - 100, _ BitOR($ES_WANTRETURN, $WS_VSCROLL, $ES_AUTOVSCROLL)) ; no hozizontal scrollbar ; or if we want horizontal scrollbar : BitOR($GUI_SS_DEFAULT_EDIT)) GUICtrlSetFont(-1, 11, 400, 0, "Lucida Console") GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; drag & drop accepted in the edit control (it will accept .asm file content) GUICtrlSendMsg($g_idEdit, $EM_LIMITTEXT, -1, 0) ; added to allow unlimited text size in edit control _SetTabStops($g_idEdit, 14) ; 14 corresponds approx. to 4 characters width (as my Scite) in this Standard Edit control with this font Local $idCompile = GUICtrlCreateButton("Compile", 100, $g_iGui_H - 70 , 80, 30) Local $idTest = GUICtrlCreateButton("Test code", 250, $g_iGui_H - 70 , 80, 30) GUICtrlSetState($idTest, $GUI_DISABLE) GUISetState(@SW_SHOW, $g_hGui) ; Reload eventual .asm test file If FileExists($g_File_Asm) Then GUICtrlSetData($g_idEdit, FileRead($g_File_Asm)) EndIf While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE If MsgBox(BitOr($MB_YESNO, $MB_TOPMOST, $MB_ICONQUESTION, $MB_DEFBUTTON2), _ "Attention", "Quit the script ?", 0, $g_hGui) = $IDYES Then If FileExists($g_File_Asm) Then ; keep a backup, who knows... FileMove($g_File_Asm, $g_File_Asm & "_bak", 1) ; $FC_OVERWRITE (1) = overwrite existing files. EndIf _Write_Asm() ExitLoop ; While 1 EndIf Case $idCompile GUICtrlSetState($idCompile, $GUI_DISABLE) ; prevent accidental double click on the button GUICtrlSetState($idTest, $GUI_DISABLE) $g_bJustCompiled = False _Compile() If $g_bJustCompiled Then GUICtrlSetState($idTest, $GUI_ENABLE) GUICtrlSetState($idCompile, $GUI_ENABLE) Case $idTest GUICtrlSetState($idTest, $GUI_DISABLE) ; prevent accidental double click on the button GUICtrlSetState($idCompile, $GUI_DISABLE) If $g_sAsmJustCompiled <> StringStripWS(GUICtrlRead($g_idEdit), 1 + 2) Then ; 1=strip leading white space, 2=strip trailing white space MsgBox($MB_TOPMOST, "Watch out", "Asm code has changed, please compile", 0, $g_hGui) Else _Test() EndIf GUICtrlSetState($idCompile, $GUI_ENABLE) GUICtrlSetState($idTest, $GUI_ENABLE) Case $GUI_EVENT_DROPPED If @GUI_DragId = -1 Then ; -1 means dragged from a file (only alternative is to drag from... Listview item : help file) ; If StringRight(@GUI_DragFile, 4) <> ".asm" Or StringRight(@GUI_DragFile, 4) <> ".txt" Then If StringRight(@GUI_DragFile, 4) <> ".asm" Then ; GuiCtrlSendMsg($g_idEdit, $EM_SETREADONLY, 1, 0) ; read-only (too late, name of bad file extension already pasted in edit control) MsgBox($MB_TOPMOST, "Drag & Drop", _ @GUI_DragFile & " does not have an .asm extension", 0, $g_hGui) ; GuiCtrlSendMsg($g_idEdit, $EM_SETREADONLY, 0, 0) ; not read-only Else GUICtrlSetData(@GUI_DropId, FileRead(@GUI_DragFile)) EndIf EndIf EndSwitch WEnd ; in case of global structures in the script, release them here (not mandatory but why not) ; ... GUIDelete($g_hGui) EndFunc ;==>Main() ;============================================ Func _Compile() _Write_Asm() If @error Then Return ; Local $sCommand = " /c C:\nasm\nasm.exe -Z C:\nasm\nasmerr.err -l C:\nasm\test.lst -f win32 C:\nasm\test.asm" Local $sCommand = " /c " & $g_Nasm_Exe & " -Z " & $g_File_Err & " -l " & $g_File_Lst & " -f win32 " & $g_File_Asm Local $iRet = RunWait(@ComSpec & $sCommand, $g_Nasm_Path, @SW_HIDE) ; Help file RunWait : runs an external program and pauses script execution until the program finishes. ; Return Value : ; Success: the exit code of the program that was run. ; Failure: sets the @error flag to non-zero. Select Case @error MsgBox($MB_TOPMOST, "RunWait", "AutoIt error, please check AutoIt code", 0, $g_hGui) Return Case $iRet MsgBox($MB_TOPMOST, "Nasm compile : ERROR", FileRead($g_File_Err), 0, $g_hGui) Return Case Else ; get binary code from nasm list file Local $sFile_Lst = FileRead($g_File_Lst) Local $aArray = StringRegExp($sFile_Lst, '(?m)^.{16}([[:xdigit:]]{2,})', 3) ; according to $g_File_Lst format If @error Then MsgBox($MB_TOPMOST, '$aArray - StringRegExp', _ 'error = ' & @error & (@error = 1 ? ' (no matches)' : ' (bad pattern)'), 0, $g_hGui) Return EndIf ; get binary code from nasm obj file (preparing a double check) Local $hFile_Obj = FileOpen($g_File_Obj, 0 + 16) ; $FO_READ = 0 , $FO_BINARY = 16 If $hFile_Obj = -1 Then MsgBox($MB_TOPMOST, "FileOpen error", $g_File_Obj & " could not be opened", 0, $g_hGui) Return EndIf Local $aArray2 = StringRegExp(FileRead($hFile_Obj), '000020005060(.+)2E66696C6500', 3) ; according to $g_File_Obj format If @error Then MsgBox(0, '$aArray2 - StringRegExp', _ 'error = ' & @error & (@error = 1 ? ' (no matches)' : ' (bad pattern)'), 0, $g_hGui) FileClose($hFile_Obj) Return EndIf FileClose($hFile_Obj) ; double check binary code extracted from nasm list file with binary code found in nasm obj file $g_sHexCode = "" For $i = 0 To Ubound($aArray) - 1 $g_sHexCode &= $aArray[$i] Next If $g_sHexCode <> $aArray2[0] Then MsgBox($MB_TOPMOST, "Double check error", "Binary code is different between these 2 files :" & @crlf & _ $g_File_Lst & @crlf & _ $g_File_Obj, 0, $g_hGui) $g_sHexCode = "" Return Else MsgBox($MB_TOPMOST, "Nasm compile : done", $sFile_Lst, 0, $g_hGui) ; _ArrayDisplay($aArray) EndIf EndSelect $g_sAsmJustCompiled = StringStripWS(GUICtrlRead($g_idEdit), 1 + 2) ; 1=strip leading white space, 2=strip trailing white space $g_bJustCompiled = True EndFunc ;==>_Compile ;============================================ Func _Write_Asm() Local $hFile_Asm = FileOpen($g_File_Asm, 2) ; 2 = Write mode (erase previous contents) If $hFile_Asm = -1 Then ClipPut(GUICtrlRead($g_idEdit)) MsgBox($MB_TOPMOST, "FileOpen error", _ $g_File_Asm & " could not be opened" & @crlf & _ "(Asm code has been copied to the Clipboard)" , 0, $g_hGui) Return SetError(1, 0, 0) Else FileWrite($hFile_Asm, GUICtrlRead($g_idEdit)) FileClose($hFile_Asm) EndIf EndFunc ;==>_Write_Asm ;============================================ Func _SetTabStops($hWnd, $iTabStops) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) ; Next line _SendMessage based on _GUICtrlEdit_SetTabStops / _GUICtrlRichEdit_SetTabStops, with "uint*" instead of "struct*" of course. _SendMessage($hWnd, $EM_SETTABSTOPS, 1, $iTabStops, 0, "wparam", "uint*") EndFunc ;==>_SetTabStops ;============================================ Func _Test() If $g_bJustCompiled Then ; only once after each successful compile. ; set/reset functions here. ; ... $g_bJustCompiled = False EndIf ; launch function tests then display results here. ; ... MsgBox($MB_TOPMOST, "Test", "Done", 0, $g_hGui) EndFunc ;==>_Test3) Now we can add some code to the pattern, for example :expandcollapse popup ; 1) if you got Global variables, place them at the beginning of program, before Main() ; ===================================================================================== Global $g_tData = DllStructCreate('int Data[100000]'), $g_NbElem ... ; 2) replace the _Test() function of the pattern with your own _Test() function ; ============================================================================= Func _Test() If $g_bJustCompiled Then ; only once after each successful compile. ; set/reset functions here. FillStruct($g_tData) ; fill it with 0xFFFFFFFF everywhere LoadSomeTestNumbers2($g_tData) ; this will also reset $g_NbElem (+++) $g_bJustCompiled = False EndIf ; launch function tests then display results here. Local $Minimum = GetMinimum($g_tData) WriteNumber($g_tData, $Minimum) MsgBox($MB_TOPMOST, "Minimum", $Minimum, 0, $g_hGui) EndFunc ;==>_Test ... ; 3) place your own functions at the end of the script ; ==================================================== Func FillStruct(ByRef $tStruct) Local $Code = Binary('0x8B7424048B4C2408C706FFFFFFFF83C604E2F5C20800') ; Andreik's original Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4) EndFunc Func LoadSomeTestNumbers2(ByRef $tStruct) $g_NbElem = 10000 Local $aNumbers[$g_NbElem] For $Index = 10 To ($g_NbElem - 1) + 10 ; 10000 times (from 10 To 10009) WriteNumber($tStruct, $Index) Next EndFunc Func GetMinimum(ByRef $tStruct) Local $Code = Binary('0x' & $g_sHexCode) Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) ;~ Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', $g_NbElem) ; ok too here... $g_NbElem += 1 ; ...but then, don't forget to increment $g_NbElem ! Return $aCall[0] EndFunc Func WriteNumber(ByRef $tStruct, $Minimum) Local $Code = Binary('0x8B7424048B4C24088B54240CAD83F8FF7409E2F8B8FFFFFFFFEB088956FCB800000000C20C00') ; Andreik's original Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $Minimum) Return $aCall[0] EndFunc Here is a display of the minimalist GUI : Here are some basic .asm codes I tested, trying to get correct results when dealing with signed integers > 7FFFFFFFexpandcollapse popup ;============================================ ; https://www.autoitscript.com/forum/topic/210242-help-with-best-way-to-do-this-function/?do=findComment&comment=1518466 ; original andreik asm code starting search from 0 (will return a minimum = 0 which is correct... ; as elements of structure go from 10 to 10009) mov esi, [esp + 4] mov ecx, [esp + 8] ; counter for LOOP/LOOPcc xor edx, edx ; blanks edx (same as mov edx, 0) next: lodsd cmp eax, edx je increase loop next jmp exit increase: mov esi, [esp + 4] mov ecx, [esp + 8] inc edx jmp next exit: mov eax, edx ret 8 ============================================ ; https://www.autoitscript.com/forum/topic/210242-help-with-best-way-to-do-this-function/?do=findComment&comment=1518527 ; andreik asm code + my change starting search from 10 (will return a minimum = 10010 which is correct... ; ...as elements of structure go from 10 to 10009) mov esi, [esp + 4] mov ecx, [esp + 8] ; xor edx, edx ; blanks edx (same as mov edx, 0) mov edx, 10 next: lodsd cmp eax, edx je increase loop next jmp exit increase: mov esi, [esp + 4] mov ecx, [esp + 8] inc edx jmp next exit: mov eax, edx ret 8 ============================================ ; https://stackoverflow.com/questions/42795616/unsigned-integers-in-assembly ; search lowest value found in test elements (10 to 10009 => 10) and return it in eax (e.g. AutoIt $aCall[0]) ; remember that integers starting from 080000000h (-2147483647) to 0FFFFFFFFh (-1) are signed integers, so... ; ...if we mov edx, 0FFFFFFFFh and want it to be an unsigned integer, then some jump instructions has to... ; ...be changed : no more jg, jl, etc... (signed interpretation) but ja, jb, etc... (unsigned interpretation) ; testing the lowest value of test elements (which are integers from 10 to 10009) depending on an... ; initial mov edx, ... (test also the whole structure elements which contain lots of 0FFFFFFFFh !) ; 000000000h = 0 ; 07FFFFFFFh = 2147483647 ; 080000000h = -2147483648 ; 080000001h = -2147483647 ; 0FFFFFFFEh = -2 ; 0FFFFFFFFh = -1 mov esi, [esp + 4] mov ecx, [esp + 8] ; counter for LOOP/LOOPcc ; mov edx, 000000000h ; then jl found_lower => 0 (good) and jb found_lower => 0 (good) ... ; ... when loop only in test elements (which seems the best way to loop) ; mov edx, 000000000h ; then jl found_lower => -1 (bad) and jb found_lower => 0 (good) ... ; ... when loop in test elements + all remaining elements of the structure (as 0FFFFFFFFh will be found !) ; mov edx, 07FFFFFFFh ; then jl found_lower => 10 (good) and jb found_lower => 10 (good) ... ; ... when loop only in test elements (which seems the best way to loop) ; mov edx, 07FFFFFFFh ; jl found_lower => -1 (bad) but jb found_lower => 10 (good) ... ; ... when loop in test elements + all remaining elements of the structure (as 0FFFFFFFFh will be found !) ; Below, same result if test on panel elements or on the whole structure elements (including panel elements) ; mov edx, 080000000h ; then jl found_lower => -2147483648 (bad) but jb found_lower => 10 (good) ; mov edx, 080000001h ; then jl found_lower => -2147483647 (bad) but jb found_lower => 10 (good) ; mov edx, 0FFFFFFFEh ; then jl found_lower => -2 (bad) but jb found_lower => 10 (good) mov edx, 0FFFFFFFFh ; then jl found_lower => -1 (bad) but jb found_lower => 10 (good) find_lowest: lodsd cmp eax, edx ; jl found_lower ; bad result for signed integers 080000000h to 0FFFFFFFFh jb found_lower ; good result for unsigned integers 080000000h to 0FFFFFFFFh continueloop: loop find_lowest jmp exit found_lower: mov edx, eax jmp continueloop exit: mov eax, edx ; returned to AutoIt $aCall[0] ret 8 ===================================== ; several clicks on Test button will display the minimum values > test elements (which go from 10 to 10009) mov esi, [esp + 4] ; 1st AutoIt parameter (first test element of AutoIt structure) mov ecx, [esp + 8] ; 2nd AutoIt parameter (counter for LOOP/LOOPcc) mov edx, 0FFFFFFFFh ; watch out as -1 if treated as signed integer (by jg, jl, etc...) find_lowest: lodsd ; the "no-operand" syntax (esi is the source operand, eax the destination operand) cmp eax, edx ; jl found_lower ; 0 bad (as -1 first time, then only 1 inc edx => 0) then 1, 2... (all bad) jb found_lower ; 10010 good (1st number > 10 when test elements go from 10 to 10009) then 10011, 10012... continueloop: loop find_lowest jmp search_empty found_lower: mov edx, eax jmp continueloop search_empty: mov esi, [esp + 4] mov ecx, [esp + 8] inc edx next: lodsd cmp eax, edx je search_empty loop next mov eax, edx ; eax content returned to AutoIt $aCall[0] ret 8 ; 8 to remove both parameters from stack It's easy to copy each one of the asm code and paste it directly in the Edit control of the Gui, click compile and test etc... Maybe this AutoIt pattern could be helpful for some users (like me) to discover and test some asm instructions. Thanks for reading Andreik 1 Link to comment Share on other sites More sharing options...
Andreik Posted June 2, 2023 Share Posted June 2, 2023 @pixelsearch It's good that you are practicing. I usually use FASM, a well maintained compiler, available as DLL also (110 kb) so it can be loaded from memory and can produce binary code very fast and without any other dependecies. Ahh and there is an UDF for inline FASM which is also available with an OOP like syntax. Here is a simple example, I think from ward's UDF: Func Demo2() ; Demo 2: Read Time-Stamp Counter $F.Reset() $F.Add("use32") $F.Add("push ebp") $F.Add("mov ebp, esp") $F.Add("rdtsc") $F.Add("mov ecx, [ebp + 08]") $F.Add("mov [ecx], edx") $F.Add("pop ebp") $F.Add("ret 4") ConsoleWrite(String($F.GetBinary()) & @CRLF) Local $Ret = MemoryFuncCall("uint", $F.GetFuncPtr(), "uint*", 0) MsgBox(0, "Demo 2: Read Time-Stamp Counter", "RDTSC = " & Hex($Ret[1]) & Hex($Ret[0], 8)) Return Hex($Ret[1]) & Hex($Ret[0], 8) EndFunc Isn't nice to write asm directly in AutoIt without external dependencies? pixelsearch 1 When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Champak Posted June 6, 2023 Author Share Posted June 6, 2023 @Andreik Hi, two things 1/ I don't understand how to update the code to have the minimum value be 1. I've been staring at your follow up post and pixelsearch's example where he got it to start at 2 for the past 20 min and can't figure out how to translate it and implement it in my code to start at 1. 2/ I don't understand Global $tData = DllStructCreate('int Data[20000]') and how to work with it later as I expand. Is that simply the max value of the array that I will be working with, so for arguments sake if my array is up to 50,000 I would then increase that to 50,000?  Thanks. Link to comment Share on other sites More sharing options...
Andreik Posted June 6, 2023 Share Posted June 6, 2023 (edited) 1. Just replace the first line of the function GetMinimum() with the code below. Local $Code = Binary('0x8B7424048B4C2408BA01000000AD39D07404E2F9EB0B8B7424048B4C240842EBEC89D0C20800') 2. That's true. Global $tData = DllStructCreate('int Data[50000]') The code above will create a structure that can hold 50k integers and nothing has to be changed in the code. Edit: to test the code probably you should replace also in LoadSomeTestNumbers() the content of $aNumbers. Instead of 1 just write a different number and let the program identify 1 as minimum. Func LoadSomeTestNumbers($cListView, $tStruct) Local $aNumbers[10] = [15, 1, 6, 5, 7, 9, 3, 8, 12, 25] For $Index = 0 To 9 GUICtrlCreateListViewItem($aNumbers[$Index], $cListView) WriteNumber($tData, $aNumbers[$Index]) Next EndFunc Edit#2: you can also have a more specialized function that will accept a new parameter $iMinimum so you can indicate from what number do you want to search for your minimum value. So it doesn't need to be 0 or 1 but anything you want and can be just an optional parameter. Func GetMinimum($tStruct, $iMinimum = 1) Local $Code = Binary('0x8B7424048B4C24088B54240CAD39D07404E2F9EB0B8B7424048B4C240842EBEC89D0C20C00') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $iMinimum) Return $aCall[0] EndFunc  Edited June 6, 2023 by Andreik Champak 1 When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Champak Posted June 6, 2023 Author Share Posted June 6, 2023 Thank you sir Link to comment Share on other sites More sharing options...
Champak Posted July 24, 2023 Author Share Posted July 24, 2023 Just came across this FWIW if there is a simple fix...no biggie, if the lowest number is 100 it returns 1...even though 1 is already used. I have to hit enter again for it to return 101. It might have been a hickup because I didn't run any tests to reproduce it after it happened. Beyond that it's been perfect. Link to comment Share on other sites More sharing options...
Andreik Posted July 24, 2023 Share Posted July 24, 2023 (edited) I am not sure if I understand what issue do you have. Did you have all numbers up to 100 already allocated (lowest number 100) and the next number returned it's 1 instead of 101? If this is the case you have a problem in your code logic. The code below allocate all numbers up to 100, so 100 it's the lowest number and when I click on 100th cell the next number generated it's 101, as expected. expandcollapse popup#include <WinAPIDiag.au3> Global $hListView, $cListView Global $tData = DllStructCreate('int Data[20000]') $hMain = GUICreate('Sample code', 400, 400) $cListView = GUICtrlCreateListView('Numbers', 10, 10, 380, 380, 0x0C, 0x21) ; LVS_SINGLESEL, LVS_SHOWSELALWAYS, LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT $hListView = GUICtrlGetHandle($cListView) GUISetState(@SW_SHOW, $hMain) FillStruct($tData) ; Allocate first 100 numbers For $Index = 1 To 100 GUICtrlCreateListViewItem($Index, $cListView) WriteNumber($tData, $Index) Next GUIRegisterMsg(0x004E, 'WM_NOTIFY') Do Sleep(10) Until GUIGetMsg() = -3 ; GUI_EVENT_CLOSE Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $iCode = DllStructGetData($tNMHDR, "Code") If $hListView = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) And $iCode = -2 Then ; NM_CLICK Local $tNMITEMACTIVATE = DllStructCreate($tagNMITEMACTIVATE, $lParam) ; When I click a particular cell (let's say 100th cell of the listview) If DllStructGetData($tNMITEMACTIVATE, 'Index') = 99 Then Local $Minimum = GetMinimum($tData) GUICtrlCreateListViewItem($Minimum, $cListView) WriteNumber($tData, $Minimum) EndIf EndIf Return 'GUI_RUNDEFMSG' EndFunc Func FillStruct($tStruct) Local $Code = Binary('0x8B7424048B4C2408C706FFFFFFFF83C604E2F5C20800') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4) EndFunc Func GetMinimum($tStruct, $iMinimum = 1) Local $Code = Binary('0x8B7424048B4C24088B54240CAD39D07404E2F9EB0B8B7424048B4C240842EBEC89D0C20C00') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $iMinimum) Return $aCall[0] EndFunc Func WriteNumber($tStruct, $Minimum) Local $Code = Binary('0x8B7424048B4C24088B54240CAD83F8FF7409E2F8B8FFFFFFFFEB088956FCB800000000C20C00') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $Minimum) Return $aCall[0] EndFunc  Edited July 24, 2023 by Andreik When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Champak Posted July 25, 2023 Author Share Posted July 25, 2023 (edited) Thanks, you're right, someone deleted ID 1 while running tests which I knew I put in the DB and thought it was still there. Needless to say that ability will be locked. Edited July 25, 2023 by Champak Link to comment Share on other sites More sharing options...
Champak Posted April 14 Author Share Posted April 14 Hi, @Andreik, is there a way to delete a number from the data structure? Link to comment Share on other sites More sharing options...
Andreik Posted April 14 Share Posted April 14 Something like this? #include <WinAPIDiag.au3> Global $tData = DllStructCreate('int Data[20]') FillStruct($tData) DllStructSetData($tData, 'Data', 22, 6) DllStructSetData($tData, 'Data', 23, 9) DllStructSetData($tData, 'Data', 25, 11) DllStructSetData($tData, 'Data', 25, 17) _WinAPI_DisplayStruct($tData, 'int Data[20]') DeleteNumber($tData, 25) _WinAPI_DisplayStruct($tData, 'int Data[20]') Func FillStruct($tStruct) Local $Code = Binary('0x8B7424048B4C2408C706FFFFFFFF83C604E2F5C20800') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4) EndFunc Func DeleteNumber($tStruct, $iValue) Local $Code = Binary('0x8B7424048B4C24088B54240CAD39D07507C746FCFFFFFFFFE2F2C20C00') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $iValue) EndFunc  When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Champak Posted April 19 Author Share Posted April 19 (edited) Yes, that's it exactly thanks. One more another thing...I tried to figure it out myself, but I don't understand how this is working...particularly how the Binary $Code is created in the first place, where does that string come from. Or what to search for exactly to figure this out. Anyway, can you give me a search function to search for how many of a particular value are in the structure (I've expanded the use of this)? And also tell me what exactly I can read up on, or what to search for, to try and learn about this and coming up binary strings necessary to do things I want? Thanks Edited April 19 by Champak Link to comment Share on other sites More sharing options...
Andreik Posted April 19 Share Posted April 19 (edited) 7 hours ago, Champak said: And also tell me what exactly I can read up on, or what to search for, to try and learn about this and coming up binary strings necessary to do things I want? Assembly. I usually use FASM but you can use whatever flavor you like. 7 hours ago, Champak said: One more another thing...I tried to figure it out myself, but I don't understand how this is working...particularly how the Binary $Code is created in the first place, where does that string come from. 8B 74 24 04 mov esi, [esp+4] ; ESI = pointer to the data struct 8B 4C 24 08 mov ecx, [esp+8] ; ECX = number of items in the struct 8B 54 24 0C mov edx, [esp+12] ; EDX = value to be deleted next: AD lodsd ; Load dword at address DS:ESI into EAX. ESI is incremented by 4. 39 D0 cmp eax, edx ; Compare data loaded in EAX with the value that you intend to delete 75 07 jne skip ; If is different then skip the overwrite operation (with default value) C7 46 FC FF FF FF FF mov DWORD PTR [esi-4], 0xffffffff ; Otherwise overwrite previously compared data with default value skip: E2 F2 loop next ; Loop the process until every item in the struct is verified C2 0C 00 ret 12 ; Return from function  7 hours ago, Champak said: Anyway, can you give me a search function to search for how many of a particular value are in the structure (I've expanded the use of this)? This is possible but it won't break the original functionality, since you tried to dinamically obtain a new minimum (and distinct) value that was not allocated yet? Global $tData = DllStructCreate('int Data[20]') FillStruct($tData) DllStructSetData($tData, 'Data', 22, 6) DllStructSetData($tData, 'Data', 23, 9) DllStructSetData($tData, 'Data', 25, 11) DllStructSetData($tData, 'Data', 25, 17) ConsoleWrite("Items containing the value 25: " & CountValue($tData, 25) & @CRLF) ConsoleWrite("Empty items: " & CountValue($tData, -1) & @CRLF) Func FillStruct($tStruct) Local $Code = Binary('0x8B7424048B4C2408C706FFFFFFFF83C604E2F5C20800') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4) EndFunc Func CountValue($tStruct, $iValue) Local $Code = Binary('0x8B7424048B4C24088B54240C31DBAD39D0750143E2F889D8C20C00') Local $iSize = BinaryLen($Code) Local $tCode = DllStructCreate('byte Code[' & $iSize & ']') DllStructSetData($tCode, 'Code', $Code) Local $aCall = DllCallAddress('int', DllStructGetPtr($tCode), 'ptr', DllStructGetPtr($tStruct), 'int', DllStructGetSize($tStruct) / 4, 'int', $iValue) Return $aCall[0] EndFunc And here is the ASM code and the corresponding binary data from my Real Time Assembler. Edited April 19 by Andreik When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Champak Posted April 21 Author Share Posted April 21 Thanks. I'll see what I can grasp from this....but it looks worse than regexp lol. argumentum 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now