Author Topic: MasmBasic  (Read 251212 times)

nidud

  • Member
  • *****
  • Posts: 1735
    • https://github.com/nidud/asmc
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: 9686
  • Assembler is fun ;-)
    • MasmBasic
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: 9686
  • Assembler is fun ;-)
    • MasmBasic
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: 1182
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: 9686
  • Assembler is fun ;-)
    • MasmBasic
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: 429
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: 9686
  • Assembler is fun ;-)
    • MasmBasic
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: 9686
  • Assembler is fun ;-)
    • MasmBasic
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.