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

#### nidud

• Member
• Posts: 1795
##### 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: 9786
• 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.incrant MACRO par1, par2, par3Local 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.codestart:   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  exitend start`
Test 3 fails:
Code: [Select]
`Test 00000001   00000002        00000003Test 00000002   00800000        00000003        WS_BORDER passed  +Test 00000003   00800002        00000003        WS_BORDER passedTest 00000004   00800002        00000003        WS_BORDER passed  +Test 00000005   00800002        00000003        WS_BORDER passed  +Test 00000006   00800002        00000003        WS_BORDER passed  +`

#### jj2007

• Moderator
• Member
• Posts: 9786
• 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

• Member
• Posts: 1187
##### 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
I can walk on water but stagger on beer bourbon.

#### jj2007

• Moderator
• Member
• Posts: 9786
• 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: 476
##### 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: 9786
• 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: 9786
• 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: 9786
• 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
`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`