News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Miscellaneous snippets

Started by jj2007, August 20, 2017, 08:02:31 AM

Previous topic - Next topic

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Dim MyInts() As DWORD
  For_ ct=0 To 999
        mov MyInts(ct), Rand(100)       ; 0...99
  Next
  Open "O", #0, "even.txt"
  Open "O", #1, "odd.txt"
  For_ ct=0 To MyInts(?)-1
        test MyInts(ct), 1
        setne al
        movsx ecx, al
        Print #ecx, Str$("%__i ", MyInts(ct))
  Next
  Close
  PrintLine     "even.txt: ", FileRead$("even.txt"), CrLf$
  Inkey         "odd.txt:  ", FileRead$("odd.txt")
EndOfCode


Output (shortened):even.txt:  86  82  22  78   2  56  36  14  58  46  68  16  84  12  94  42   0  16  90  42   8  94  90  52  92  90  42  60  88  86  10  64  3
8  92  16  24  92  10  46  34  28  66  74  92  88  82  40  44  26  84  94  48  32   8   0  44  68  40  50   0   2  12  38  12  82  80   0  7
2  76   0  74   8   0  76  64   8  28  46  10  48   6  94  90  10  84  68  62   2  82  96   0  98  20  36  12  96  14  98   8  96

odd.txt:   45   7  13  65  51  57  67  25  97  63  23  77  87  95  39  57  33  87  55  99   5  47  69  79  87  67  19  95  83  49  21  85  4
9  53   7  39  25  31  49  83  17  65  29  27  99  61  19  67  67  77  49  61  73  79  29  47  31  95  49  45  55  81  71  29   7  79  65  2
3  89  93  19  81  17  19  87  83  63  93  25  75  51  79  75  99   7  55  17  19  57  45  33  83  81  87  51  75  81  79  55  93

jj2007

Ever tried to kill the current executable? It's not that straightforward, for security reasons, but it can be done with little helpers:include \masm32\include\masm32rt.inc ; pure Masm32

.data?
ThisExe db MAX_PATH dup(?)

.code
start:
  mov edi, offset ThisExe
  invoke lstrcpy, edi, chr$("KillMe.exe ")
  invoke lstrcat, edi, rv(GetCommandLine)  ; this returns the path of the current exe
  invoke WinExec, edi, SW_MINIMIZE
  add edi, 11 ; advance to compensate for <KillMe.exe >
  print "check your disk to see if "
  print edi
  print " was killed"
  exit

end start


Source and binaries attached, must sit in the same folder as the current exe.

jj2007

Playing with inline assembly in FreeBasic, source attached; see discussion. Watch out for the red calls below...

Function LeapYearJ(ByVal yea As ULong) As ULong
Asm
  mov ecx, dword ptr [yea]
  test ecx, 3
  setz al
  jne 0f
  mov eax, ecx
  cdq
  push 100
  idiv dword ptr [esp] ' 0, 4, 8, ..., 96, 0
  test edx, edx ' mod 100=0 should set zero flag
  jne 1f
  mov eax, ecx
  cdq
  push 400
  idiv dword ptr [esp]
  pop eax
  dec edx '*** invert the zero flag ***
  sets dl ' sign set if edx was zero
  test dl, dl
1:
  pop eax
  setnz al
0:
  movsx eax, al
  mov [function], eax ' MichaelW
End Asm
End Function

...
for i = 1 to years ' assembly function, inlined by compiler
asm int 3 ' forum
lyears=lyears+LeapYearJ(i)
asm nop
asm nop
asm nop
asm nop
next


00407C20        �> �CC                �int3
00407C21        �. �8B45 D0           �mov eax, [ebp-30]
00407C24        �. �8945 D8           �mov [ebp-28], eax
00407C27        �. �C745 DC 00000000  �mov dword ptr [ebp-24], 0
00407C2E        �. �C70424 24A04000   �mov dword ptr [esp], offset 0040A02 ; ASCII "C:\FreeBasic\tmp\TmpFile.bas"
00407C35        �. �E8 169EFFFF       �call 00401A50                       ; �TmpFile.00401A50
00407C3A        �. �56                �push esi                            ; �Arg1
00407C3B        �. �8945 C0           �mov [ebp-40], eax                   ; �
00407C3E        �. �C70424 80A04000   �mov dword ptr [esp], offset 0040A08 ; �ASCII "LEAPYEARJ"
00407C45        �. �E8 669EFFFF       �call 00401AB0                       ; �TmpFile.00401AB0
00407C4A        �. �57                �push edi
00407C4B        �. �8945 BC           �mov [ebp-44], eax
00407C4E        �. �8B4D D8           �mov ecx, [ebp-28]
00407C51        �. �F7C1 03000000     �test ecx, 00000003
00407C57        �. �0F94C0            �setz al
00407C5A        �.�75 22             �jnz short 00407C7E
00407C5C        �. �89C8              �mov eax, ecx
00407C5E        �. �99                �cdq
00407C5F        �. �6A 64             �push 64
00407C61        �. �F73C24            �idiv dword ptr [esp]
00407C64        �. �85D2              �test edx, edx
00407C66        �.�75 12             �jnz short 00407C7A
00407C68        �. �89C8              �mov eax, ecx
00407C6A        �. �99                �cdq
00407C6B        �. �68 90010000       �push 190
00407C70        �. �F73C24            �idiv dword ptr [esp]
00407C73        �. �58                �pop eax
00407C74        �. �4A                �dec edx
00407C75        �. �0F98C2            �sets dl
00407C78        �. �84D2              �test dl, dl
00407C7A        �> �58                �pop eax
00407C7B        �. �0F95C0            �setnz al
00407C7E        �> �0FBEC0            �movsx eax, al
00407C81        �. �8945 DC           �mov [ebp-24], eax
00407C84        �. �8B7D BC           �mov edi, [ebp-44]
00407C87        �. �893C24            �mov [esp], edi
00407C8A        �. �E8 219EFFFF       �call 00401AB0                       ; �TmpFile.00401AB0
00407C8F        �. �50                �push eax                            ; �Arg1
00407C90        �. �8B45 C0           �mov eax, [ebp-40]                   ; �
00407C93        �. �890424            �mov [esp], eax                      ; �
00407C96        �. �E8 B59DFFFF       �call 00401A50                       ; �TmpFile.00401A50
00407C9B        �. �50                �push eax                            ; �Arg1
00407C9C        �. �8B45 DC           �mov eax, [ebp-24]                   ; �
00407C9F        �. �0145 D4           �add [ebp-2C], eax                   ; �
00407CA2        �. �90                �nop                                 ; �
00407CA3        �. �90                �nop                                 ; �
00407CA4        �. �90                �nop                                 ; �
00407CA5        �. �90                �nop                                 ; �
00407CA6        �. �8B45 D0           �mov eax, [ebp-30]                   ; �
00407CA9        �. �40                �inc eax                             ; �
00407CAA        �. �8945 D0           �mov [ebp-30], eax                   ; �
00407CAD        �. �3D 80969800       �cmp eax, 989680                     ; �
00407CB2        �.�0F86 68FFFFFF     �jbe 00407C20                        ; �

jj2007

Build it, then drag an archive over the exe:

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  UnzipInit CL$()
  .if !Sign?
        For_ ecx=0 To edx-1
                PrintLine Files$(ecx)
        Next

  .endif
  Inkey CrLf$, "Now copy the names from the console menu"
EndOfCode


Output e.g. from the COM interface archive:
GetComInterface.asc
GetComInterface.dll

aw27

Quote from: jj2007 on November 10, 2017, 09:39:13 PM
Ever tried to kill the current executable? It's not that straightforward, for security reasons, but it can be done with little helpers:include \masm32\include\masm32rt.inc ; pure Masm32

.data?
ThisExe db MAX_PATH dup(?)

.code
start:
  mov edi, offset ThisExe
  invoke lstrcpy, edi, chr$("KillMe.exe ")
  invoke lstrcat, edi, rv(GetCommandLine)  ; this returns the path of the current exe
  invoke WinExec, edi, SW_MINIMIZE
  add edi, 11 ; advance to compensate for <KillMe.exe >
  print "check your disk to see if "
  print edi
  print " was killed"
  exit

end start


Source and binaries attached, must sit in the same folder as the current exe.

Come on, JJ  :badgrin: :badgrin:

Try this instead: http://masm32.com/board/index.php?topic=6713.0

jj2007

This should work but it doesn't :(

It builds fine and returns S_OK, no error, but it does not set the wallpaper. MSDN says it's supported for XP and earlier - seriously? But even on XP it has no effect.

include \masm32\MasmBasic\MasmBasic.inc
include IActiveDesktop.inc      ; IActiveDesktop STRUCT, CLSID_ActiveDesktop, IID_IActiveDesktop (attached)
.code
SetMyWallpaper proc pDesktopImg  ; adapted from johnsa's code
LOCAL pAD
  invoke CoCreateInstance, addr CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, addr IID_IActiveDesktop, addr pAD
  .if eax==S_OK
       CoInvoke pAD, IActiveDesktop.SetWallpaper, pDesktopImg, 0
       deb 4, "SetWp", $Err$()         ; OK, operation completed - but no effect
       CoInvoke pAD, IActiveDesktop.Release
  .endif
  ret
SetMyWallpaper endp
  Init
  If_ Not rv(CoInitializeEx, 0, COINIT_APARTMENTTHREADED) Then invoke SetMyWallpaper, wChr$("\Masm32\examples\exampl04\car\car.jpg")
  invoke CoUninitialize
EndOfCode

Vortex

Hi Jochen,

Can you try the attached sample?

jj2007

Hi Erol,
Your example changed slightly the position of the existing wallpaper, but the old image remained...
To be continued ;-)

Vortex

Hi Jochen,

Not sure but maybe specifying the full path of the image can solve the problem.

WSTR        DesktopImg,"test.bmp"
.
.
coinvoke    pAD,IActiveDesktop,SetWallpaper,OFFSET DesktopImg,0


GetFullPathName can retrieve the full path.

jj2007

#9
Hi Erol,

Full path works, thanks a lot! Now I'll try my version 8)

P.S.: It works ;)

include \masm32\MasmBasic\MasmBasic.inc
include IActiveDesktop.inc      ; IActiveDesktop STRUCT, CLSID_ActiveDesktop, IID_IActiveDesktop
.code
SetMyWallpaper proc pDesktopImg         ; adapted from Vortex and johnsa's code
LOCAL pAD, wpo:WALLPAPEROPT
  ClearLocals
  .if !rv(CoCreateInstance, addr CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, addr IID_IActiveDesktop, addr pAD)
        add wpo.dwSize, WALLPAPEROPT
        add wpo.dwStyle, WPSTYLE_CENTER or WPSTYLE_STRETCH
        CoInvoke pAD, IActiveDesktop.SetWallpaper, wRec$(pDesktopImg), 0
        CoInvoke pAD, IActiveDesktop.SetWallpaperOptions, addr wpo, 0
        CoInvoke pAD, IActiveDesktop.ApplyChanges, AD_APPLY_ALL
        CoInvoke pAD, IActiveDesktop.Release
  .endif
  ret
SetMyWallpaper endp
  Init
  Let esi=wCL$()
  .if !rv(CoInitializeEx, 0, COINIT_APARTMENTTHREADED)
        wMsgBox 0, esi, "Set as wallpaper?", MB_OKCANCEL or MB_ICONQUESTION
        If_ eax==IDOK Then <invoke SetMyWallpaper, Qtrim$(Utf8$(esi))>
        invoke CoUninitialize
  .endif
EndOfCode


Full project attached, including a really nice wallpaper - a very special view of a European city. Extract all files to a folder, then drag the jpg over the exe :biggrin:

jj2007

I am testing a new syntax for Delay and would appreciate some results for other Windows versions:

include \masm32\MasmBasic\MasmBasic.inc         ; download
uselib ntdll
  SetGlobals resMin, resMax, resCurrent
  Init
  invoke NtQueryTimerResolution, addr resMin, addr resMax, addr resCurrent
  deb 4, "Timer resolution", resMin, resMax, resCurrent

  PrintLine CrLf$, "These lines should print about one second after the start, at ", fTime$(0, "HH:mm:??.123"), " millisecs"
  For_ ecx=0 To 4
        Delay Rand(500)         ; sleep 0..499 milliseconds
        NanoTimer()
        PrintLine fTime$(0, "HH:mm:ss.fff"), Tb$, "started"
        Delay until fTime$(s:1, "HH:mm:ss.123")         ; use time$(current plus one second)
        PrintLine fTime$(0, "HH:mm:ss.fff "), Tb$, NanoTimer$(), " passed", CrLf$
  Next
  Inkey Str$("This is Windows version %i", MbWinVersion()), Str$(".%i", ecx)
EndOfCode


Output:
Timer resolution
resMin          156001
resMax          5000
resCurrent      10000

These lines should print about one second after the start, at 04:47:??.123 millisecs
04:47:16.057    started
04:47:17.123    1066 ms passed

04:47:17.159    started
04:47:18.123    964 ms passed

04:47:18.191    started
04:47:19.123    932 ms passed

04:47:19.554    started
04:47:20.123    569 ms passed

04:47:20.450    started
04:47:21.123    673 ms passed

This is Windows version 6.1


The new version of the fTime$() macro can display milliseconds using the fff format specifier. See Microsoft: How to: Display Milliseconds in Date and Time Values for details.

felipe

Timer resolution
resMin          156250
resMax          5000
resCurrent      156255

These lines should print about one second after the start, at 23:52:??.123 milli
secs
23:52:37.774    started
23:52:38.123    348 ms passed

23:52:38.161    started
23:52:39.123    962 ms passed

23:52:39.193    started
23:52:40.124    930 ms passed

23:52:40.556    started
23:52:41.123    567 ms passed

23:52:41.451    started
23:52:42.123    672 ms passed

This is Windows version 6.3

From windows 8.1

jj2007

Thanks, Felipe :t
Here are Win10 results:Timer resolution
resMin          156250
resMax          5000
resCurrent      5007

These lines should print about one second after the start, at 09:35:??.123 millisecs
09:35:03.858    started
09:35:04.123    264 ms passed

09:35:04.159    started
09:35:05.123    964 ms passed

09:35:05.191    started
09:35:06.123    931 ms passed

09:35:06.554    started
09:35:07.123    568 ms passed

09:35:07.450    started
09:35:08.123    672 ms passed

This is Windows version 10.0


Note that even after a reboot, the current resolution is 0.5 milliseconds:resMax          5000
resCurrent      5007


Your Windows 8.1 results are still at the 15.6 ms resolution. It seems they changed it definitely with Win10, which makes sense because a) the hardware got faster and b) even an ordinary browser like FF or PaleMoon sets it to 10000 when you visit YouTube.

So has GetTickCount finally become a high resolution timer?

NOPE. Have a look at these GetTickCount results:ticks   systime
   0    10:02:51.678
   0    10:02:51.679
   0    10:02:51.681
   0    10:02:51.682
   0    10:02:51.683
   0    10:02:51.684
   0    10:02:51.686
  15    10:02:51.688
  15    10:02:51.689
  15    10:02:51.690
  15    10:02:51.691
  15    10:02:51.692
  15    10:02:51.693
  15    10:02:51.695
  15    10:02:51.696
  15    10:02:51.697
  15    10:02:51.698
  15    10:02:51.700
  15    10:02:51.701
  15    10:02:51.702
  31    10:02:51.703
  31    10:02:51.705
  31    10:02:51.706


Between each line, there is a Sleep(1), and the high resolution timer shows that the systemtime gets adjusted in one milliseconds increments; but GetTickCount keeps reporting with its low 15.625 ms granularity 8)

Vortex

Hi Jochen,

Here are my results, XP 64-bit :


Timer resolution
resMin          156250
resMax          10000
resCurrent      156250

These lines should print about one second after the start, at 13:11:??.123 milli
secs
13:11:17.531    started
13:11:18.125    591 ms passed

13:11:18.156    started
13:11:19.125    966 ms passed

13:11:19.187    started
13:11:20.125    935 ms passed

13:11:20.562    started
13:11:21.125    560 ms passed

13:11:21.453    started
13:11:22.109    669 ms passed

This is Windows version 5.2

jj2007

Thanks, Erol. So it starts always 2 ms later, 125 instead of 123... ::)

Similar for XP-32, a Virtual Machine:Timer resolution
resMin          100144
resMax          10032
resCurrent      100144

These lines should print about one second after the start, at 11:16:??.123 milli
secs
11:16:29.859    started
11:16:30.129    254 ms passed

11:16:30.159    started
11:16:31.121    963 ms passed

11:16:31.191    started
11:16:32.122    931 ms passed

11:16:32.553    started
11:16:33.124    570 ms passed

11:16:33.454    started
11:16:34.125    669 ms passed

This is Windows version 5.1