News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

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
  Let esi=FileRead$(CL$())
  Let edi="SendMessage"         ; just a proposal
  .While 1
        PrintLine "Hit Escape, Return to exit", Space$(40)
        Let edi=Input$("Search for ", edi)
        .Break .if !Len(edi)
        xor ebx, ebx
        NextMatch:
        inc ebx
        .if !Instr_(ebx, esi, edi, 1)
                PrintLine "No match for [", edi, "]                 "
        .else
                mov ebx, edx
                xchg eax, ecx
                sub ecx, 4*16
                ConsoleColor cBlue
                Print HexDump$(ecx, 64)
                ConsoleColor cWhite
                add ecx, 4*16
                .Repeat
                                PrintLine HexDump$(ecx)
                                add ecx, 512
                                Inkey "more? (Return: continue, F3: next match)", Cr$
                                cmp eax, VK_F3
                                je NextMatch
                .Until eax!=13
                ConsoleColor
        .endif
  .Endw
EndOfCode


Output:
Hit Escape, Return to exit
Search for SendMessage
002A899C  6E 65 64 09 65 71 75 20 73 64 77 6F 72 64 20 70 ned.equ sdword p
002A89AC  74 72 20 0D 0A 73 74 61 63 6B 09 65 71 75 20 3C tr ..stack.equ <
002A89BC  44 57 6F 72 64 20 50 74 72 20 5B 65 73 70 5D 3E DWord Ptr [esp]>
002A89CC  0D 0A 73 6D 09 65 71 75 20 69 6E 76 6F 6B 65 20 ..sm.equ invoke
002A89DC  53 65 6E 64 4D 65 73 73 61 67 65 2C 20 0D 0A 4C SendMessage, ..L
002A89EC  61 73 74 46 69 6C 65 4E 61 6D 65 24 09 65 71 75 astFileName$.equ
002A89FC  20 6F 66 66 73 65 74 20 77 66 64 2E 63 46 69 6C  offset wfd.cFil
002A8A0C  65 4E 61 6D 65 0D 0A 4C 61 73 74 46 69 6C 65 53 eName..LastFileS
002A8A1C  69 7A 65 09 65 71 75 20 77 66 64 2E 6E 46 69 6C ize.equ wfd.nFil
002A8A2C  65 53 69 7A 65 4C 6F 77 0D 0A 77 43 72 4C 66 24 eSizeLow..wCrLf$
002A8A3C  09 65 71 75 20 6F 66 66 73 65 74 20 77 43 72 4C .equ offset wCrL
002A8A4C  66 5F 74 78 74 0D 0A 77 4C 66 24 09 65 71 75 20 f_txt..wLf$.equ
002A8A5C  6F 66 66 73 65 74 20 77 4C 66 5F 74 78 74 0D 0A offset wLf_txt..
002A8A6C  77 54 62 24 09 65 71 75 20 6F 66 66 73 65 74 20 wTb$.equ offset
002A8A7C  77 54 61 62 5F 74 78 74 0D 0A 43 72 4C 66 09 65 wTab_txt..CrLf.e
002A8A8C  71 75 20 31 33 2C 31 30 0D 0A 0D 0A 4D 62 45 76 qu 13,10....MbEv
002A8A9C  43 74 3D 30 0D 0A 45 6E 64 4F 66 43 6F 64 65 20 Ct=0..EndOfCode
002A8AAC  4D 41 43 52 4F 20 61 72 67 64 0D 0A 20 20 69 66 MACRO argd..  if
002A8ABC  65 20 4D 62 45 78 69 74 0D 0A 09 45 78 69 74 20 e MbExit...Exit
002A8ACC  61 72 67 64 0D 0A 20 20 65 6E 64 69 66 0D 0A 20 argd..  endif..
002A8ADC  20 69 66 20 54 63 6C 43 74 43 20 67 74 20 31 0D  if TclCtC gt 1.
002A8AEC  0A 09 54 72 79 43 61 74 63 68 45 6E 64 0D 0A 20 ..TryCatchEnd..
002A8AFC  20 65 6E 64 69 66 0D 0A 20 20 69 66 20 4D 62 45  endif..  if MbE
002A8B0C  76 43 74 0D 0A 09 47 75 69 45 6E 64 20 30 0D 0A vCt...GuiEnd 0..
002A8B1C  20 20 65 6E 64 69 66 0D 0A 20 20 69 66 20 4D 62   endif..  if Mb
002A8B2C  4E 61 54 69 43 74 20 61 6E 64 20 31 0D 0A 09 65 NaTiCt and 1...e
002A8B3C  63 68 6F 0D 0A 09 65 63 68 6F 20 23 23 23 20 63 cho...echo ### c
002A8B4C  68 65 63 6B 20 79 6F 75 72 20 4E 61 6E 6F 54 69 heck your NanoTi
002A8B5C  6D 65 72 20 63 61 6C 6C 73 20 23 23 23 0D 0A 20 mer calls ###..
002A8B6C  20 65 6E 64 69 66 0D 0A 20 20 65 6E 64 20 73 74  endif..  end st
002A8B7C  61 72 74 0D 0A 45 4E 44 4D 0D 0A 43 6C 65 61 72 art..ENDM..Clear
002A8B8C  4C 61 73 74 45 72 72 6F 72 20 4D 41 43 52 4F 0D LastError MACRO.
002A8B9C  0A 20 20 69 66 20 75 73 65 64 65 62 0D 0A 09 70 .  if usedeb...p
002A8BAC  75 73 68 61 64 0D 0A 09 69 6E 76 6F 6B 65 20 53 ushad...invoke S
002A8BBC  65 74 4C 61 73 74 45 72 72 6F 72 2C 20 30 0D 0A etLastError, 0..
002A8BCC  09 70 6F 70 61 64 0D 0A 20 20 65 6E 64 69 66 0D .popad..  endif.

more? (Return: continue, F3: next match)

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  SetGlobals left, right, row   ; geeks for geeks: Print string of odd length in 'X' format
  Init
  Let edi="Assembly is a great language"
  .While 1
        Let edi=Input$("\n\n\n\nGimme a string please: ", edi)
        .Break .if !Len(edi)
        Clr left, row
        mov right, eax
        Cls
        .Repeat
                mov edx, left
                movzx eax, byte ptr [edi+edx]
                Print At(left, row) Chr$(eax)
                inc left
                dec right
                mov edx, right
                movzx eax, byte ptr [edi+edx]
                Print At(right, row) Chr$(eax)
                inc row
        .Until right<=0
  .Endw
EndOfCode


A                          e
s                        g
  s                      a
   e                    u
    m                  g
     b                n
      l              a
       y            l

         i        t
          s      a
                e
            a  r
              g
              g
            a  r
                e
          s      a
         i        t

       y            l
      l              a
     b                n
    m                  g
   e                    u
  s                      a
s                        g
A                          e

TimoVJL

So you spotted G-point with MasmBasic 8)
May the source be with you

jj2007

#93
I've got a video converter (DVDVideoSoft) that works fine but it has the bad habit to set the time stamp of the output file to "right now". Fortunately, it creates new file names that contain the original date and time, e.g. C:\Users\Jochen\Videos\VID_20170621_153022.mp4 meaning original file was created 21 June 2017, 15:30:22

Here is a little program that touches the file and sets the time stamp back (source & exe attached, use at your own risk). Just drag any file from the folder over the exe:

include \masm32\MasmBasic\MasmBasic.inc         ; download
  SetGlobals gfMatch$, pathLeft
  Init
  Let gfMatch$=CL$()
  mov pathLeft, Rinstr(eax, "\")
  .Repeat
        inc eax
  .Until byte ptr [eax]<="."
  xchg eax, ecx
  Let gfMatch$=Left$(gfMatch$, pathLeft)+"*"+ecx
  PrintLine gfMatch$
  GetFiles gfMatch$
  deb 4, "matches", eax
  SortFiles                             ; optional: latest files first
  For_ ecx=0 To eax-1
        mov esi, Files$(ecx)
        .if InstrOr(esi, ".mp4" or ".avi" or ".gp", 1)
                PrintLine GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
                .if Instr_(esi, "201")  ; 20160602_170844
                                xchg eax, esi
                                .if byte ptr [esi+8]=="_"
                                        Let edi=Mid$(esi, 7, 2)+"."+Mid$(esi, 5, 2)+"."+Left$(esi, 4)+Spc2$+Mid$(esi, 10, 2)+":"+Mid$(esi, 12, 2)+":"+Mid$(esi, 14, 2)
                                        ; ClearLastError
                                       Touch Files$(ecx), TimeSF(edi)
                                        ; deb 4, "Touch", eax, $Err$()
                                       .if Exist(Files$(ecx))
                                        PrintLine GfDate$(-1), Spc2$, GfTime$(-1)
                                        .endif
                                .else
                                        PrintLine "skipped, unknown date format: ", Tb$, esi
                                .endif
                .else
                                PrintLine "skipped, no 201 detected: ", Tb$, esi
                .endif
        .else
                PrintLine "skipped, not a video file: ", Tb$, esi
        .endif
  Next
  Inkey "ok?"
EndOfCode


Typical output (the second, shorter line shows the changed date):
C:\Users\Jochen\Videos\*.mp4
matches eax             18
07.11.2018  12:27:53    C:\Users\Jochen\Videos\20160602_170844.mp4
02.06.2016  17:08:44
07.11.2018  12:27:42    C:\Users\Jochen\Videos\VID_20170531_195446.mp4
31.05.2017  19:54:46
07.11.2018  12:12:22    C:\Users\Jochen\Videos\VID_20170621_153022.mp4

jj2007

Generates two Million random strings and sorts them using QSort (which is an in-place mergesort).
Source & binaries attached: Extract exe and dll to the same folder, then run the exe. Typical result for a Core i5:
11 s for writing 2 Millon strings
106 ms for reading 5 Million strings
3.2 seconds for sorting 5 Million strings


TimoVJL

#95
With my slow AMD:62 s for writing 2 Millon strings
383 ms for reading 5 Million strings
12. seconds for sorting 5 Million strings

May the source be with you

jj2007

Where has your code gone? I've tested it (attached), and that's a really fast sort, Timo - interesting :t

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  NoTitleCase$ equ <Chr$(".a.an.and.are.as.but.by.for.is.in.or.the.that.")>        ; this is the default, inspired by Lauren Ipsum, but you can use others
  Init 
  Let ecx="World bank and OECD are organisations that - as a rule - i consider very powerful"
  PrintLine ecx
  Inkey TitleCase$(ecx)
EndOfCode


Output:
World bank and OECD are organisations that - as a rule - i consider very powerful
World Bank and OECD are Organisations that - as a Rule - I Consider Very Powerful


Inspired by Munair on the FreeBasic forum :icon14:

jj2007

Just for fun, a little demo showing the use of the PSHUFB instruction, and some macro tricks:
include \masm32\MasmBasic\MasmBasic.inc

SwapBytes MACRO pBytes
  if type(pBytes) eq REAL8
movlps xmm0, pBytes
  else
mov edx, pBytes
movups xmm0, oword ptr [edx]
  endif
  mov eax, esp
  and esp, -16
  push 00010203h ; the magic numbers
  push 04050607h
  push 08090a0bh
  push 0c0d0e0fh
  PSHUFB xmm0, oword ptr [esp] ; shuffle the bytes! (will crash on very old CPUs, sorry...)
  movups oword ptr [esp], xmm0
  if type(pBytes) eq REAL8
fld qword ptr [esp]
xchg eax, esp
EXITM <ST(0)> ; leave the double in the FPU
  else
xchg eax, esp
EXITM <> ; the bytes are in xmm0, but the macro is not used as a function
  endif
ENDM
 
.data
MyReal8 REAL8 1234567890.1234567890
thestring db "!taerg si 23msaM", 0
.data?
SwappedR8 REAL8 ?
out$ db 20 dup(?)

  Init
  PrintLine "Original:", Tb$, offset thestring
  SwapBytes(offset thestring) ; return 16 bytes in xmm0
  movups oword ptr out$, xmm0
  PrintLine "Swapped:", Tb$, offset out$
 
  Print Str$("\nMyReal8  \t%Hf", MyReal8), Str$("\nas BigEndian\t%Hf", SwapBytes(MyReal8)) ; SwapBytes leaves the double in the FPU
  fstp SwappedR8
  Inkey Str$("\nreconverted\t%Hf\n", SwapBytes(SwappedR8)v)
EndOfCode


Note that the macro can be used either as a function:
Print Str$(SwapBytes(MyReal8))

or "standalone":
SwapBytes(offset thestring)

Output:Original:       !taerg si 23msaM
Swapped:        Masm32 is great!

MyReal8         1234567890.1234567
as BigEndian    3.5842524504192598e+246
reconverted     1234567890.1234567

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Dim My$(tab)                          ; create a two-dimensional string array
  For_ ecx=0 To 7
        Let edi=Str$("Test %i\t", ecx)
        Let My$(ecx)=String$(8, edi)    ; create a string with 8 columns
  Next

  For_ ecx=0 To 7
        Let My$(ecx, ecx)="Hello!!"     ; set individual elements
        Let My$(ecx, 7-ecx)="*Ciao*"
  Next
  For_ ecx=0 To 7
        For_ ct=0 To 7
                Print My$(ecx, ct), Spc2$
        Next

        Print
  Next
EndOfCode


Output:Hello!  Test 0  Test 0  Test 0  Test 0  Test 0  Test 0  *Ciao*
Test 1  Hello!  Test 1  Test 1  Test 1  Test 1  *Ciao*  Test 1
Test 2  Test 2  Hello!  Test 2  Test 2  *Ciao*  Test 2  Test 2
Test 3  Test 3  Test 3  Hello!  *Ciao*  Test 3  Test 3  Test 3
Test 4  Test 4  Test 4  *Ciao*  Hello!  Test 4  Test 4  Test 4
Test 5  Test 5  *Ciao*  Test 5  Test 5  Hello!  Test 5  Test 5
Test 6  *Ciao*  Test 6  Test 6  Test 6  Test 6  Hello!  Test 6
*Ciao*  Test 7  Test 7  Test 7  Test 7  Test 7  Test 7  Hello!


Purest assembly :bgrin:

jj2007

Strange - I had forgotten to code the Eof() macro, here it is:

include \masm32\MasmBasic\MasmBasic.inc         ; download

SOMEUDT STRUCT  ; a user-defined type
  mydouble      REAL8 ?
  mydword       DWORD ?
  myfloat       REAL4 ?
SOMEUDT ENDS

MyUDT SOMEUDT <?>

Eof MACRO arg
  push Loc(arg)
  void Lof(arg)
  pop edx
  cmp edx, eax
  exitm <!Sign?>
ENDM

  Init
  Open "O", #1, "TypeTest.udt"
  For_ ecx=101 To 103
       mov MyUDT.mydword, ecx  ; 101, 102, ...
       lea eax, [ecx+900]
       SetFloat MyUDT.myfloat=eax      ; 1001, 1002, ...
       add eax, 9000
       SetFloat MyUDT.mydouble=eax     ; 10001, 10002, ...
       Store #1, MyUDT         ; save UDT to file
  Next
  Close
  Open "I", #1, "TypeTest.udt"
  .Repeat
        Recall #1, MyUDT
        deb 4, "Test", MyUDT.mydouble, MyUDT.myfloat, MyUDT.mydword
  .Until Eof(#1)
  Close
  Inkey CrLf$, "Yep, that's purest assembler ;-)"
EndOfCode



Output:
Test
MyUDT.mydouble  10001.00000000000
MyUDT.myfloat   1001.000
MyUDT.mydword   101

Test
MyUDT.mydouble  10002.00000000000
MyUDT.myfloat   1002.000
MyUDT.mydword   102

Test
MyUDT.mydouble  10003.00000000000
MyUDT.myfloat   1003.000
MyUDT.mydword   103

Yep, that's purest assembler ;-)


P.S.: To get random access to some record, use this before closing the file:

  m2m eax, 1                   ; get record #1
  imul eax, SOMEUDT            ; calculate position in file
  Seek #1, eax
  Recall #1, MyUDT
  deb 4, "Test with Seek", MyUDT.mydouble, MyUDT.myfloat, MyUDT.mydword
  Close

TimoVJL

#101
Quote from: jj2007 on January 13, 2019, 01:58:51 PM
P.S.: To get random access to some record, use this before closing the file:

  m2m eax, 1                   ; get record #1
  imul eax, SOMEUDT            ; calculate position in file
I didn't understood that :icon_rolleyes:
  mov eax, 1
  imul eax, sizeof SOMEUDT

EDIT:
OK
push 1 / pop eax is two bytes shorter.
imul eax, SOMEUDT is same as imul eax, sizeof SOMEUDT
May the source be with you

ragdog

Quote
I didn't understood that :icon_rolleyes:
Code: [Select]

  mov eax, 1
  imul eax, sizeof SOMEUDT

Hello Timo

1 * size of  SOMEUDT structur

jj2007

Quote from: TimoVJL on January 13, 2019, 11:50:18 PM
push 1 / pop eax is two bytes shorter.
imul eax, SOMEUDT is same as imul eax, sizeof SOMEUDT

Yes, as ragdog already noted. It took me years to realise that mov eax, sizeof SOMESTRUCT is the same as mov eax, SOMESTRUCT ;)

And m2m eax, n is simply some bytes shorter for n=-128 ... +127, so I always use it, except perhaps for a really speed-critical innermost loop.

jj2007

include \masm32\MasmBasic\MasmBasic.inc
  Init
  Inkey NoTag$(FileRead$("https://de.wikipedia.org/wiki/Spezial:Zufällige_Seite"))
EndOfCode