Masm32 SDK description, downloads and other helpful links

Main Menu

Miscellaneous snippets

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

Previous topic - Next topic


Quote from: Richard on January 05, 2021, 02:51:40 PMI wish to establish whether or not FreeBASIC DOS version can work with in-line assembly (prefer DOS version at this stage but will also consider windows version which I have used a bit).

Would you be able to supply a very simple FreeBASIC program that uses in-line assembly


That is a question for the FreeBasic forum. I have never touched FB for DOS, so I cannot give you advice on that, sorry...


Note this is the bare minimum - just a demo. No checks, no bells and whistles. Use at your own risk.
GuiParas equ "A full-fledged raw Win32 GUI", icon Ball, b Turquoise ; title, icon, background
GuiMenu equ @File, &Open, &Save, -, E&xit, @Edit, Undo, Copy, Paste ; define a menu (only Open & Save are implemented)
include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl RichEdit, "richedit", CL$() ; load what you find in the commandline
  GuiControl Status, "statusbar"
Event Menu
  Switch_ MenuID
  Case_ 0 ; Open (menu entries start with 0)
  If_ FileOpen$("FB sources=*.bas|Includes=*.bi;*.inc|Resources=*.rc|All files=*.*") Then SetWin$ hRichEdit=FileRead$(FileOpen$())
  Case_ 1 ; Save
  FileWrite CL$(), stream:hRichEdit ; save contents of the RichEdit control
  SetWin$ hStatus=CL$()+" was saved"
OPT_Arg1 ?:\Masm32\MasmBasic\AscUser\OpenSaveFB.asc ; for testing with RichMasm


Just drag the tabbish source over the attached exe.

include \masm32\MasmBasic\         ; download
  Let esi=FileRead$(CL$())
  Let esi=Replace$(esi, Tb$, Space$(8)))
  FileWrite "NoMoreTabs.bas", esi
  ShEx "NoMoreTabs.bas"         ; launch it with ShellExecuteEx

(I don't recommend it, though - I love my tabs and would never exchange them for spaces :badgrin:)


include \masm32\MasmBasic\
  Let esi=FileRead$(99)         ; WarAndPeaceChinese.txt from resource
  Let edi=Utf8$(esi)
  deb 4, "wLen", wLen(esi)      ; Utf-16 chars
  deb 4, "uLen", uLen(edi)      ; Utf-8 chars
  deb 4, "Len", Len(edi)        ; bytes
  uMsgBox 0, edi, "Chinese text as Utf-8:", MB_OK
  wMsgBox 0, esi, "Chinese text as Utf-16:", MB_OK
#include "resource.h"
IDI_APPLICATION ICON    "\\Masm32\\MasmBasic\\icons\\Globe.ico"         // Calc, Disk, Editor, Eye, Globe, MasmBasic, Smiley
01 RT_MANIFEST         "\\Masm32\\MasmBasic\\Res\\XpManifest.xml"
99 RCDATA      "WarAndPeaceChinese.txt"

wLen    eax             526
uLen    eax             525
Len     eax             1449

So that is 1449 vs 2*526 bytes, which means that Utf-8 needs 37.7% more space in memory.
When saving the Utf-8 file, and zipping both together, the packed sizes differ by only 5.5%, though.

Project attached, requires MasmBasic.


Lots of people argue on the web whether Utf-16 is "harmful", and what are the pros and cons of Utf-8 vs Utf-16. As a matter of fact, both work just fine, as demonstrated below with two compound characters that are not in the Basic Multilingual Plane. For Chinese text, the space requirements are very similar, as demonstrated above, for English text, Utf-8 clearly wins, of course.

include \masm32\MasmBasic\
  Let edi="aaa  שָׁ  bbb  𝕥  ccc"         ; two compound characters with 6 and 4 bytes in Utf-8
  PrintLine "Utf-8:", CrLf$, HexDump$(edi, 32)
  Let esi=wRec$(edi)            ; convert to Utf-16
  PrintLine "Utf-16:", CrLf$, HexDump$(esi, 48)
  if 0  ; activate if needed
        lea ecx, [2*wLen(esi)]
        FileWrite "compound.txt", esi, ecx
  uMsgBox 0, edi, "Utf-8:", MB_OK
  wMsgBox 0, esi, "Utf-16:", MB_OK

Output (20 = 32 dec are the spaces):
002BD2B0  61 61 61 20 20 D7 A9 D7 81 D6 B8 20 20 62 62 62 aaa  שָׁ  bbb
002BD2C0  20 20 F0 9D 95 A5 20 20 63 63 63 00 00 00 00 00   𝕥  ccc.....

0028DEF0  61 00 61 00 61 00 20 00 20 00 E9 05 C1 05 B8 05 a.a.a. . .�.�.�.
0028DF00  20 00 20 00 62 00 62 00 62 00 20 00 20 00 35 D8  . .b.b.b. . .5�
0028DF10  65 DD 20 00 20 00 63 00 63 00 63 00 00 00 00 00 e� . .c.c.c.....


Data come from the Allgemeine Ortskrankenkasse (AOK) Berlin. The graph shows how many employees went on sick leave because they tested CoVid-19 positive.

GuiParas equ "Covid by profession", w1200, h630, b Grey, icon Plot
include \masm32\MasmBasic\Res\MbGui.asm
  SetGlobals language=2 ; default is English
  GuiControl MyCanvas, "canvas"
  Recall 99, L$(), tab ; res 99 =
Event CanvasPaint
  For_ ct=0 To L$(?)-2
sar Val(L$(ct, 0)), 2 ; /4
xchg eax, ecx
GuiTextBox 20, ct*30+12, ecx, 26, Cat$(" "+L$(ct, language+1)), fcol White, bcol Red, DT_LEFT
  GuiTextBox 800, 200, 200, auto, L$(ct, language+1), fcol Black, bcol LiteYellow, DT_WORDBREAK, font -20:FW_BOLD
Event Key
  Switch_ VKey
  Case_ VK_D: Clr language ; German
  Case_ VK_I: m2m language, 1 ; Italian
  Case_ VK_E: m2m language, 2 ; English
  Case_ VK_F: m2m language, 3 ; French


include \masm32\MasmBasic\         ; download
  StringToArray Launch$("cmd.exe /c dir *.asm"), f$()   ; use Launch$ to grab the output, translate into a string array
  For_ each esi in f$(): <Let f$(ForNextCounter)=Mid$(esi, 35)>  ; eliminate date, time, size, e.g. 27.08.17  23:34            16,527 SortAnIntegerArray.asm
  QSort f$()
  For_ each esi in f$(): PrintLine esi

An alternative:
include \masm32\MasmBasic\
  StringToArray Launch$("cmd.exe /c dir /O-D *.asm"), f$() ; use Launch$ to grab the output, translate into a string array
  Delete f$(0), 5 ; eliminate the five strings at the beginning of a dir command
  Delete f$(f$(?)-2), 2 ; eliminate the two trailing strings
  For_ each esi in f$(): PrintLine esi ; print all files

20.03.21  18:53               873 CovidAOK.asm
19.03.21  15:53            12,246 CheckNewPosts.asm
29.06.13  00:59             4,687 Win64_3e.asm
25.06.11  11:03             4,276 cids.asm


include \masm32\MasmBasic\         ; download
  GetRegArray "HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment", MyEnv$(), MyData$()
  QSortMode 1, 0, DataIndex() As DWORD  ; case-insensitive, don't skip leading spaces
  QSort MyEnv$()                        ; sort by name of key
  Open "O", #1, ""
  For_ each esi in MyEnv$(): <PrintLine #1, esi, Tb$, MyData$(DataIndex(ForNextCounter))>
  Close #1
  ShEx ""

Output (shortened):
ComSpec %SystemRoot%\system32\cmd.exe
DXSDK_DIR       C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\
VS140COMNTOOLS  C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
windir  %SystemRoot%

Attached a version that writes the variables to a tab-delimited file and opens it in your default *.tab viewer (which might be MS Excel, for example).


The dir command is lousy, but fortunately we have a handy MasmBasic command: GetFiles :thumbsup:

This little proggie should be put into a batch file e.g. as
\Masm32\bin\VS14\ml64.exe /c /Zp8 /Zi /Zd /Zf %1
echo ----------- assembly done --------------------
\Masm32\bin\VS14\link.exe /subsystem:console /entry:start /debug %~dpn1.obj /out:%~dpn164.exe
\Masm32\MasmBasic\Res\GetFiles %~dpn1* -time -age:2

Here is the (shortened) output for the source short.asm:
Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
----------- assembly done --------------------

Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

----- files created 14:50:18
389120  03.04.2021  14:50:18    Short64.pdb
14336   03.04.2021  14:50:18    Short64.exe
77928   03.04.2021  14:50:18    Short64.ilk
309334  03.04.2021  14:50:18    Short.obj

The arguments:
-time show the current time as ----- files created 14:50:18 (see above)
-age:2 show only files that are less than 2 seconds old (i.e. ignore older stuff)

Source & exe attached.


*** Use at your own risk - make a copy of the zip archive before testing this; warning: doesn't work with filenames containing spaces (I still have to find out why) ***

To encrypt:
- Drag a zip archive over the attached exe
- Type a 4-letter password and hit Return

To decrypt:
- Drag the *.encrypted file over the attached exe
- Type the 4-letter password and hit Return

include \masm32\MasmBasic\         ; download
  Let ebx=Input$("Gimme the seed: ", "abcd")
  Rand(seed:ebx)                        ; use e.g. "abcd" as seed (4 letters)
  Let esi=CL$()                             ; get file name from the commandline
  Let edi=FileRead$(esi)        ; put file content into a buffer
  .if Instr_(esi, ".zip")
        ; **** we got an archive - let's encrypt it: *******
       push edi                                ; save pointer to the buffer
       For_ ecx=0 To LastFileSize-1 Step 4
                xor [edi+ecx], Rand(-1)         ; xor buffer content with random dword
        pop edi                                 ; restore start of buffer
       Let esi=Left$(esi, Rinstr(esi, "."))+"encrypted"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
        ; **** we got an encrypted archive - let's read it back: *******
       Let edi=FileRead$(esi)
        push edi
       For_ ecx=0 To LastFileSize-1 Step 4
                xor [edi+ecx], Rand(-1)         ; reverse everything...
        pop edi
       Let esi=Left$(esi, Rinstr(esi, "."))+"zip"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
       ShEx esi                        ; open the archive with ShellExecute



Cheat, rename the file with underscores for the spaces then rename the results to whatever you need.  :icon_idea:    :biggrin:  :skrewy:


Just for fun

include \masm32\MasmBasic\         ; download
  Let esi="123456789012345678901234567890123456789012345678901234567890"
  push eax                              ; create a DWORD slot
  xor ecx, ecx
  or edx, -1
  fld FP10(10.0)                        ; for multiplication by 10
  .While 1
       movzx eax, byte ptr [esi+ecx]   ; "1"
       .Break .if eax<"."
       .if Zero?
               mov edx, ecx    ; store position of the dot
               and eax, 15     ; "1"->1
               mov [esp], eax
               fiadd dword ptr [esp]   ; add 1 to current ST(0)
               fmul ST, ST(1)  ; multiply by 10
       inc ecx                 ; advance position in string
  inc edx
  .if !Zero?
       sub ecx, edx
       void Exp10(ecx)         ; 10^position of dot
       fdiv                            ; result/(10^position of dot)
  fstp st
  Inkey Str$("Result: %Jf", ST(0)v)
  pop eax                               ; balance the stack


include \masm32\MasmBasic\         ; download
  fld FP10(0.00998001)
  PrintLine Str$("Result=%Jf", ST(0)v)


Just for fun, a full-fledged Scintilla editor in five lines (use at your own risk):

include \masm32\MasmBasic\Res\MbGui.asm ; OPT_Icon Editor
  GuiControl MySci, "scintilla", font 14:"Times New Roman", Cat$(FileRead$(CL$()))
Event Close
  If_ <Alert("Save file?", "bye", MB_YESNO)>==IDYES Then FileWrite CL$(), Win$(hMySci) ; save it, or don't...

P.S.: ScintillaPath equ <"\Masm32\wscite\SciLexer.dll">; drag a text file over the executable.


include \masm32\MasmBasic\         ; download
  Inkey Replace$(String$(1000, "x"), "x", cfm$("Hello Masm32\n")), "bye"

That was easy, no?  :tongue: