### Author Topic: MasmBasic  (Read 267089 times)

#### nidud

• Member
• Posts: 1851
##### Re: MasmBasic
« Reply #480 on: August 05, 2019, 07:18:08 AM »
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.

if ((dstyle) and SS_ICON) eq SS_ICON

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #481 on: August 05, 2019, 08:15:29 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:
Code: [Select]
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:
Code: [Select]
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

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #482 on: August 05, 2019, 09:04:53 PM »
This is code from an old plugin posted here two years ago:

Code: [Select]
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:
Code: [Select]
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.
« Last Edit: August 09, 2019, 10:55:31 PM by jj2007 »

#### sinsi

• Guest
##### Re: MasmBasic
« Reply #483 on: August 05, 2019, 11:41:31 PM »
Table 1.3 Operator Precedence
Precedence Operators
1 ( ), [ ]
2 LENGTH , SIZE , WIDTH , MASK, LENGTHOF, SIZEOF
3 . (structure-field-name operator)
4 : (segment-override operator), PTR
5 LROFFSET , OFFSET , SEG , THIS , TYPE
6 HIGH , HIGHWORD , LOW , LOWWORD
7 + ,– (unary)
8 *, /, MOD , SHL , SHR
9 +, – (binary)
10 EQ , NE , LT , LE , GT , GE
11 NOT
12 AND
13 OR , XOR
14 OPATTR , SHORT , .TYPE

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #484 on: August 05, 2019, 11:58:30 PM »
Thanks, Sinsi - this is already fixed with Nidud's suggestion to use brackets: if ((dstyle) and SS_ICON) eq SS_ICON

To my big surprise, I discovered that, after applying that fix, the line that choked was no longer the SS_LEFT or WS_BORDER line but rather the line that followed - see snippet above. After some trial and error, I discovered that cases 1 and 3, although almost identical, act differently:

case 1: DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%
case 3: DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%   ; this one is also OK!!

The first one chokes, the second one is OK. And of course, both are OK for UAsm and AsmC.

#### TimoVJL

• Member
• Posts: 494
##### Re: MasmBasic
« Reply #485 on: August 06, 2019, 12:42:26 AM »
8.14.5 Macro Parameter Expansion and Macro Operators
Quote
One possible solution, that works well for macros like the above, is to put parentheses
around macro parameters that occur within expressions inside the macro
.
http://www.phatcode.net/res/223/files/html/Chapter_8/CH08-7.html

EDIT: to avoid further misunderstanding, only documentation for that ?
Quote
The problem above occurs because MASM simply replaces a formal parameter by the actual parameter’s text, not the actual parameter’s value. This pass by name parameter passing mechanism should be familiar to long-time C and C++ programmers who use the #define statement. If you think that macro (pass by name) parameters work just like Pascal and C’s pass by value parameters, you are setting yourself up for eventual disaster.

One possible solution, that works well for macros like the above, is to put parentheses around macro parameters that occur within expressions inside the macro. Consider the following code:
« Last Edit: August 06, 2019, 03:45:14 AM by TimoVJL »
May the source be with you

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #486 on: August 06, 2019, 02:25:21 AM »
Yes, Timo, but it's not relevant here. Or, rather: it does work if you put parentheses around (x or z) but if you don't put these parentheses, all paras are passed correctly to this macro but the macro in the next line chokes.

And to make things perfect, you can make it assemble if ... tara! ... you add a comment to the next line:
Code: [Select]
case 1: DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%
case 3: DlgControl dcStatic,  "maxMB=", SS_LEFT, 73.0%, -7, 31%   ; this comment makes the line assemble!!

If there is no comment, you get error A2026: constant expected - and that is complete BS. It's a MASM bug, that's all. Of the same kind as the inability to deal with the "#" character if it's not at a certain position inside the include file. I can't find the reference right now, but that was another ML bug that drove me crazy. My suspicion is that during macro processing, some buffers don't get delimited properly, but that is impossible to chase.

MASM has some serious problems, and I would ditch it completely in favour of UAsm or AsmC if there wasn't a bit of nostalgia around to stick with the original M\$ product.

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #487 on: August 09, 2019, 11:00:57 PM »
Timo,

I use all these macros on a daily basis, they work just fine. The problem is really some kind of buffer overflow in MASM that makes it choke with the % and # characters. I opened a separate MASM bug post with the complete example.

The new MasmBasic version has fixes for the brackets bug, allows using e.g. 12.3% in the first DlgControl (that was the DlgDefY issue), and adds a specific warning to the output window if RichMasm sees "error A2026:constant expected".

Thanks a lot, Timo, Nidud and Sinsi, for your help.

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #488 on: October 26, 2019, 12:09:19 PM »
MasmBasic version 26 October 2019 is online.

Changes:
- the RichMasm editor lists now macros and procs correctly, as in the image below
- For_ ... Next with floats follows a different logic now:
* previously, the step was added to the float counter (fct in the example below). For small steps and REAL4 counters, significant deviations could accumulate
* the new version calculates fct as endvalue - step*(total - current iterations), which is much more exact.

Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc
SetGlobals fct:REAL4
Init
For_ fct=1.5 To 2.0 Step 0.01 ; counter is a float, and therefore needs to be
Print Str\$("%Jf\n", fct) ; previously defined in .data? or with SetGlobals
Next
Inkey "ok?"
EndOfCode

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #489 on: December 08, 2019, 01:17:13 AM »
Version 7 December 2019 is online. Minor improvements, e.g. it's now possible to add a legend to an ArrayPlot (project attached):

The code required to add the legend:

ArrayPlot RgbCol(192, 255, 255)         ; init & set background
If_ useLegend Then Legend ld\$(), mr, hLegendFont                ; corners: ul, ur, ll, lr, mr
...
ArrayPlot exit, 0005000032#T title\$, fcol Black         ; finish with a title, xxxxyyyyfsize

ld\$() can be any Utf8 string array; mr indicates the position middle/right

To build the project,
- install the latest MasmBasic version
- extract the archive below to a folder on your Masm32 drive
- open LifeExpOECD.asc in RichMasm (\Masm32\MasmBasic\RichMasm.exe)
- hit F6

#### JK

• Regular Member
• Posts: 7
##### Re: MasmBasic
« Reply #490 on: February 05, 2020, 04:05:19 AM »
Hi jj2007,

JK

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #491 on: February 05, 2020, 04:52:03 AM »

#### JK

• Regular Member
• Posts: 7
##### Re: MasmBasic
« Reply #492 on: February 05, 2020, 09:23:23 AM »
The idea is very cool, the implementation (RichMasm) is ... not easy to get used to. I would like to discuss a few things (MasmBasic and FreeBASIC related) in private - would you please drop me a mail at "jklwn44 at mail dot de".

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Re: MasmBasic
« Reply #493 on: February 05, 2020, 10:13:00 AM »
Email sent, although I prefer discussing here in this thread, or, if necessary, via PMs.

Re RichMasm, there are some posts here. I know it looks different, but I couldn't do any serious work with one of the standard editors. For example, the RichMasm source has currently 21,000 lines, try working with such a source without the listbox, the bookmarks and the history (Alt cursor left/right)

Note you can build FreeBasic sources with RichMasm, but a little add-on is needed. Let me know if you want to test it.

My biggest nuisance with RichMasm is that the MRU is limited to 25 files. The library itself is easy to handle, just one big file with 30 or so modules, but I have over 5,000 sources hanging around, and I am always playing with a dozen new ideas.

#### jj2007

• Moderator
• Member
• Posts: 10091
• Assembler is fun ;-)
##### Trigonometric functions: sine, cosine, tangent
« Reply #494 on: February 22, 2020, 03:58:11 PM »
Update 22 Feb 2020:
- minor improvements of the RichMasm editor
- changes to the deb macro:

- displaying a string by address is now possible via e.g. deb 4, "test", \$addr MyAnsi\$, \$\$addr MyWide\$
- the handling of strings in structures was improved
- debugging the FPU was improved - now the state of the registers is displayed:

Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc
Init
FpuFill ; fill FPU with 1001.0 ... 1008.0
ffree st(7) ; create some problems
fldz
fldpi
ffree st(5)
ffree st(7)
fldl2e
deb 4, "FPU filled, NaN in ST1, zero in ST2, ST6 empty", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)
fstp st
ffree st(7)
ffree st(6)
ffree st(5)
ffree st(4)
ffree st(3)
deb 1, "As previous, one fstp st plus 5*ffree", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)
EndOfCode

You may wonder why there are five ffree instructions: it is a special service for the Windows 10 users

Console output (deb 1 produces a MsgBox):
Code: [Select]
FPU filled, NaN in ST1, zero in ST2, ST6 empty
ST(0)           1.442695040888963407
ST(1)           - NaN -
ST(2)           zero
ST(3)           1001.000000000000000
ST(4)           1002.000000000000000
ST(5)           1003.000000000000000
ST(6)           empty 1004.000000000
ST(7)           1005.000000000000000

- various trigonometric functions added (source attached):

Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc
SetGlobals fct:REAL8
Init
Cls
Print cfm\$("degrees\tSinus\tCosinus\t  Tangens    Cotangens")
For_ fct=0.1 To 360.0 Step 15.0
Print Str\$("\n%__i", fct), Str\$("\t%3f", Sinus(fct)v), Str\$("\t%3f", Cosinus(fct)v), Str\$("\t  %3f", Tangens(fct)v)
Print At(37) Str\$("%3f", Cotangens(fct)v)
Next
Print
Print Str\$("\nrTangens(PI/3)=30°    \t%3f", rTangens(0.5236)v)
Print Str\$("\nrCotangens(PI/6)=15° \t%3f", rCotangens(0.2618)v)
Print Str\$("\nArctangens(0.268) \t%3f", Arctangens(0.268)v)
Print Str\$("\nArctangens(0.577) \t%3f", Arctangens(0.577)v)
Print Str\$("\nArctangens(1)    \t%3f", Arctangens(1)v)
Print Str\$("\nArctangens(1.732) \t%3f", Arctangens(1.732)v)
Print Str\$("\nArctangens(60/30) \t%3f", Arctangens(60, 30)v) ; ideally opposite/adjacent sides of a rectangular triangle
Print Str\$("\nArctangens(4/3) \t%3f", Arctangens(4, 3)v) ; Pythagoras: 25=16+9
EndOfCode

Output:
Code: [Select]
degrees Sinus   Cosinus   Tangens    Cotangens
0     0.00175 1.000     0.00175    573.
15     0.259   0.966     0.268      3.73
30     0.500   0.866     0.577      1.73
45     0.707   0.707     1.00       1.00
60     0.866   0.500     1.73       0.577
75     0.966   0.259     3.73       0.268
90     1.00    0.0       -3.69e+19  -2.71e-20
105     0.966   -0.259    -3.73      -0.268
120     0.866   -0.500    -1.73      -0.577
135     0.707   -0.707    -1.000     -1.00
150     0.500   -0.866    -0.577     -1.73
165     0.259   -0.966    -0.268     -3.73
180     0.0     -1.00     5.42e-20   1.84e+19
195     -0.259  -0.966    0.268      3.73
210     -0.500  -0.866    0.577      1.73
225     -0.707  -0.707    1.00       1.00
240     -0.866  -0.500    1.73       0.577
255     -0.966  -0.259    3.73       0.268
270     -1.00   0.0       -5.27e+18  -1.90e-19
285     -0.966  0.259     -3.73      -0.268
300     -0.866  0.500     -1.73      -0.577
315     -0.707  0.707     -1.00      -1.000
330     -0.500  0.866     -0.577     -1.73
345     -0.259  0.966     -0.268     -3.73
360     0.0     1.00      1.08e-19   9.22e+18

rTangens(PI/3)=30°      0.577
rCotangens(PI/6)=15°    3.73
Arctangens(0.268)       15.0
Arctangens(0.577)       30.0
Arctangens(1)           45.0
Arctangens(1.732)       60.0
Arctangens(60/30)       63.4
Arctangens(4/3)         53.1