News:

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

Main Menu

MasmBasic

Started by jj2007, May 23, 2012, 10:16:07 PM

Previous topic - Next topic

jj2007

MasmBasic was updated, version 8 May features some improvements under the hood, inter alia building a library has become a lot faster because it will no longer do a full rebuild (unless you use Shift F6).

As a side effect, RichMasm now supports the conversion of a library folder into a single source (the MasmBasic library is indeed one fat 2.2 MB file containing 33 modules). To test this feature, extract the attached files to a folder of your choice, then either drag a folder over the exe, or open a DOS prompt and type e.g. BuildTheLibSource.exe \Masm32\m32lib

Soon after, RichMasm will show you more or less this:
include TestFile.asm
OxPT_LibName \fullpath\MyLib
OPT_DelTmp 0
OPT_DelObj 0
OPT_Tgt rml ; RichMasmLibrary
OPT_Linker link ; polink does not recognise certain options
OPT_Arg1 "Hello coder, how are you?" ; for testing

LibMod AA: a2dw
; #########################################################################

    ; --------------------------------------
    ; This procedure was written by Iczelion
    ; --------------------------------------

      .386
      .model flat, stdcall  ; 32 bit memory model
... etc ...


Hit F6 and watch the library being built. By default, it will be named BuildLib.lib - move it wherever you need it, the little TestFile.asm includes it "as is", i.e. as BuildLib.lib

What is the advantage of one big source file, instead of 237 tiny modules? It surely is a matter of taste, but, for example, you can search the source for mov e*, 0 to do a bit of maintenance (Intel says xor reg32, reg32 is the right thing to do). Plus comfortable navigation, highlighting of critical parts, etc - it's not meant for bare metal purists :P

TimoVJL

splitting / combine source is a good idea.
easy too see what parts are changes, time stamp.

a common keyword for it might be usable ?

Find in files helps finding things, but often too many files to open in an editor.

MasmBasic.lib:
almost 250 symbols in 33 modules, still some work to do ?

PS: ml and pocc have a same problem, no COMDAT support :(
May the source be with you

jj2007

Quote from: TimoVJL on May 09, 2019, 12:35:23 AM
splitting / combine source is a good idea.
easy too see what parts are changes, time stamp.
I use a checksum for the part between LibMods. When working inside the source, RichMasm remembers the last 8 edit positions (and saves them with the file!). By pressing Alt Left / Alt Right, you can jump between them. Hitting Alt Right several times brings you always back to the last edit. Thus, even if you stopped working on a source months ago, the editor will remember what you were last working on. Extremely handy in my experience. I hate editors that open a file, and you always stare at the top of the file.

QuoteMasmBasic.lib:
almost 250 symbols in 33 modules, still some work to do ?

Not all modules can be neatly separated, unfortunately. This is mainly because of the fast circular buffer and the array engines; many modules use them.

2B||!2B

Hi jj,

How can i get the returned value of Split$ (number of found substrings)?

MOV EBX,Split$("Masm32 is great", " ", My$())-1 ;Does not work
Let EBX = Split$("Masm32 is great", " ", My$())-1 ;Does not work


jj2007

Hi,

The example in the manual has a FOR counter:
For_ ct=0 To Split$("Masm32 is great", " ", My$())-1
PrintLine "[", My$(ct), "]"
Next


Since Split$() returns the number of strings in eax, you could write this also as
void Split$("Masm32 is great", " ", My$())
For_ ct=0 To eax-1
PrintLine "[", My$(ct), "]"
Next


The example returns 3 strings, so this is for x=0 ... 3-1, given that arrays are zero-based. The problem in your example is the -1. You are writing MOV EBX, eax-1, and indeed, that does not work. Take away the -1, and all is fine.

Re your second example: Let is for strings only.

Thanks for the feedback - I will modify the manual to make that point clearer :Thmbsup:

2B||!2B

Thank you, that works now compiled without error.

I have one more question

Is it possible to get the Array size?

Dim MyBuffer(10) As BYTE

How can i get the size of this buffer?
I have looked the manual and couldn't find what i am looking for.

jj2007

If you mean the number of elements: mov ecx, somearray(?)

2B||!2B

Thanks. It works perfect. Very useful library :D

jj2007

Thanks. Note that you can, but you don't have to, specify the array size. This is legal code:
  xor ecx, ecx
  Dim MyBuffer() As BYTE  ; no size!
  .Repeat
mov MyBuffer(ecx), cl
inc ecx
  .Until ecx>100
  Inkey "hit any key"


Arrays are dynamic, they auto-expand when the index (ecx in this case) hits the allocated number. You can't do a mov MyBuffer(1000), 123 though - the loop must increment the counter from the bottom.

jj2007

Update 4 August 2019 (download):

- added a warning to RichMasm for a hilarious MASM bug where a constant passed as e.g. SS_LEFT or WS_BORDER was not recognised as a constant by ML.exe:
DlgControl dcStatic,  "some text", SS_LEFT or WS_BORDER, 1, -7, 60.0

RichMasm will now add a "(1): Brackets around paras?" at the end of the output window. This may seem ridiculous but understanding the non-logic and misleading error messages of ML took me several hours, so I decided to warn myself next time.

- new macro ArrayFind(strings$(), "match", [mode], [startindex]):

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Recall "\Masm32\include\Windows.inc", L$()
  Print Str$("%i lines found in Windows.inc\n", eax)
  .if ArrayFind(L$(), "Hutch")
        PrintLine Trim$(L$(eax))        ; Original file 1998        hutch
  .endif
  xor ecx, ecx
  .While 1
        .Break .if ArrayFind(L$(), "MACRO", 1, ecx)<0   ; mode 1: case insensitive; see Instr_(...)
       xchg eax, ecx
        PrintLine Str$("line %i\t", ecx), L$(ecx)
        inc ecx
  .Endw
  MsgBox 0, "ok?", "Hi", MB_OK
EndOfCode


Project attached.

aw27

We know the trolling pleasure you have in ranting Microsoft (and not only Microsoft).  :badgrin:
However, the MASM BASIC macro (DlgControl MACRO ctrlType, szText, dstyle, etc) you provided as an example is buggy.

Look here:
if (dstyle and SS_ICON) eq SS_ICON

It is completely different to pass SS_LEFT or WS_BORDER and to pass (SS_LEFT or WS_BORDER). Macros are not functions, just in case you don't know.

BTW, I am not studying MASM BASIC at this time, I was looking at the latest posts and noticed this perl.  :skrewy:


jj2007

Yeah, completely different:
include \masm32\include\masm32rt.inc  ; plain Masm32, no MasmBasic required

rant MACRO par1, par2, par3
Local tmp$
  tmp$ CATSTR <Paras passed: p1=>, <par1>, <, p2=>, <par2>, <, p3=>, <par3>
  % echo tmp$
  print "Test "
  print hex$(par1), 9
  print hex$(par2), 9
  print hex$(par3), 9
  if (par2 and WS_BORDER) eq WS_BORDER
print "WS_BORDER passed "
  endif
  print chr$(13, 10)
ENDM
.code
start:
   rant 1, SS_LEFT, 3
   rant 2, WS_BORDER, 3
   rant 3, SS_LEFT or WS_BORDER, 3
   rant 4, WS_BORDER or SS_LEFT, 3
   rant 5, (SS_LEFT or WS_BORDER), 3
   rant 6, (WS_BORDER or SS_LEFT), 3
   inkey
  exit

end start


And you shouldn't feel ashamed for studying MasmBasic macros. There is a lot to learn for you :cool:

nidud

#477
deleted

jj2007

Quote from: nidud on August 05, 2019, 07:18:08 AM
    if ((dstyle) and SS_ICON) eq SS_ICON

Thanks, Nidud, I see. Irrelevant for this specific macro (it works indeed), but there may be cases where it matters. Here is one, building on the previously posted example:
include \masm32\include\masm32rt.inc

rant MACRO par1, par2, par3
Local tmp$
  tmp$ CATSTR <Paras passed: p1=>, <par1>, <, p2=>, <par2>, <, p3=>, <par3>
  % echo tmp$
  print "Test "
  print hex$(par1), 9
  print hex$(par2), 9
  print hex$(par3), 9
  if ((par2) and WS_BORDER) eq WS_BORDER ; Nidud's solution: (SS_RIGHT or WS_BORDER) and WS_BORDER
print "WS_BORDER passed "
  endif
  if (par2 and WS_BORDER) eq WS_BORDER ; fails: SS_RIGHT or WS_BORDER and WS_BORDER
print " +"
  endif
  print chr$(13, 10)
ENDM
.code
start:
   rant 1, SS_RIGHT, 3
   rant 2, WS_BORDER, 3
   rant 3, SS_RIGHT or WS_BORDER, 3
   rant 4, WS_BORDER or SS_RIGHT, 3
   rant 5, (SS_RIGHT or WS_BORDER), 3
   rant 6, (WS_BORDER or SS_RIGHT), 3
   inkey
  exit

end start


Test 3 fails:
Test 00000001   00000002        00000003
Test 00000002   00800000        00000003        WS_BORDER passed  +
Test 00000003   00800002        00000003        WS_BORDER passed
Test 00000004   00800002        00000003        WS_BORDER passed  +
Test 00000005   00800002        00000003        WS_BORDER passed  +
Test 00000006   00800002        00000003        WS_BORDER passed  +

jj2007

#479
This is code from an old plugin posted here two years ago:

  DlgControl dcEdit, wRec$(ini$(4)), WS_BORDER, 89.0, -6, 11.0, , ID_MODE2 ; x, y only, the macro will assign width, height and ID; OPT_Assembler mlv615
  if 0
DlgControl dcStatic,  "Files containing both strings:", SS_LEFT or WS_BORDER, 1, -7, 60.0  ; THIS ONE CHOKES
DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%
  elseif 0
DlgControl dcStatic,  "Files containing both strings:", (SS_LEFT or WS_BORDER), 1, -7, 60.0  ; this one is OK - Nidud's trick with the brackets works!!
DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%
  else
DlgControl dcStatic,  "Files containing both strings:", SS_LEFT or WS_BORDER, 1, -7, 60.0  ; guess what?
DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31% ; this one is also OK!!
  endif


The interesting part is that, under the hood, Nidud's suggestion has been implemented:
if ((dstyle) and SS_ICON) eq SS_ICON
and ch, 10111111b ; clear bit 14
endif


So it should not matter whether we use (SS_LEFT or WS_BORDER) or SS_LEFT or WS_BORDER

But it does, as case 2 shows! Now the hilarious part is that it works in case 3.

Needless to say that UAsm and AsmC have no problem at all - this is a MASM only bug! Project attached.