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

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

Richard,

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

jj2007

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"
  Endsw_
GuiEnd
OPT_Arg1 ?:\Masm32\MasmBasic\AscUser\OpenSaveFB.asc ; for testing with RichMasm

jj2007

Just drag the tabbish source over the attached exe.

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


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

jj2007

include \masm32\MasmBasic\MasmBasic.inc
  Init
  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
EndOfCode
Rsrc
#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"
Rsrc


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.

jj2007

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\MasmBasic.inc
  Init
  Cls
  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
  endif
  uMsgBox 0, edi, "Utf-8:", MB_OK
  wMsgBox 0, esi, "Utf-16:", MB_OK
EndOfCode


Output (20 = 32 dec are the spaces):
Utf-8:
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.....

Utf-16:
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.....

jj2007

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 = CovidAOK.tab
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
  Next
  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
  Endsw_
  GuiRefresh
EndOfCode



jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  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
EndOfCode


An alternative:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  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
EndOfCode


Output:
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

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  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, "Environment.tab"
  For_ each esi in MyEnv$(): <PrintLine #1, esi, Tb$, MyData$(DataIndex(ForNextCounter))>
  Close #1
  ShEx "Environment.tab"
EndOfCode


Output (shortened):
ComSpec %SystemRoot%\system32\cmd.exe
DXSDK_DIR       C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\
FP_NO_HOST_CHECK        NO
...
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).

jj2007

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 --------------------
echo.
\Masm32\bin\VS14\link.exe /subsystem:console /entry:start /debug %~dpn1.obj /out:%~dpn164.exe
echo.
\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.

jj2007

*** 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\MasmBasic.inc         ; download
  Init
  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
       Next
        pop edi                                 ; restore start of buffer
       Let esi=Left$(esi, Rinstr(esi, "."))+"encrypted"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
  .else
        ; **** 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...
       Next
        pop edi
       Let esi=Left$(esi, Rinstr(esi, "."))+"zip"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
       ShEx esi                        ; open the archive with ShellExecute
  .endif
EndOfCode

hutch--

 :biggrin:

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

jj2007

#176
Just for fun

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Let esi="123456789012345678901234567890123456789012345678901234567890"
  push eax                              ; create a DWORD slot
  xor ecx, ecx
  or edx, -1
  fld FP10(10.0)                        ; for multiplication by 10
  fldz
  .While 1
       movzx eax, byte ptr [esi+ecx]   ; "1"
       .Break .if eax<"."
       .if Zero?
               mov edx, ecx    ; store position of the dot
       .else
               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
       .endif
       inc ecx                 ; advance position in string
  .Endw
  inc edx
  .if !Zero?
       sub ecx, edx
       void Exp10(ecx)         ; 10^position of dot
       fdiv                            ; result/(10^position of dot)
  .endif
  fxch
  fstp st
  Inkey Str$("Result: %Jf", ST(0)v)
  pop eax                               ; balance the stack
EndOfCode

jj2007

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  fld1
  fld FP10(0.00998001)
  fdiv
  PrintLine Str$("Result=%Jf", ST(0)v)
EndOfCode

jj2007

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...
GuiEnd


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

jj2007

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


That was easy, no?  :tongue: