MASM / JWASM - Combining Conditional Assembly statements with logical operator

Started by bugthis, October 27, 2022, 01:15:23 PM

Previous topic - Next topic

bugthis

I have the following macro code:

    IF (Reg EQ AL) OR (Reg EQ AH)
      ...
    ELSE
      ...
    ENDIF

and this assembles in MASM <= version 5.1, but not in MASM >= 6 or JWASM.

Read here for more information and proof that it assembles in MASM 5:
http://masm32.com/board/index.php?topic=4791.msg115112#msg115112

Now i need a replacement for the above code in a MASM v6 conform syntax.

A working command directive replacement for EQ

If (argument1 EQ argument2)

is

IFIDNI textItem , textItem


but it only works on one singular item.
In this case, i could test for AL register

IFIDNI <Reg>,<AL>
   ....
ELSE
...
ENDIF


But how do i combine IFIDNI with the logical OR of the old previous code to test also on AH register?

I tried the following combinations (each line, one combination, when doing so, the others were commented)

; IF (Reg EQ AL) OR (Reg EQ AH)    ; this was the old syntax working only in MASM <= 5.1 
IF (IFIDNI <Reg>, <BL>) OR (IFIDNI <Reg>, <BH>)  ; JWASM throws Error A2064: Expression expected: IFIDNI <BH>, <BL>) OR (IFIDNI <BH>, <BH>)
IF [IFIDNI <Reg>, <BL>] OR [IFIDNI <Reg>, <BH>]  ; JWASM throws Error A2064: Expression expected: IFIDNI <BH>, <BL>] OR [IFIDNI <BH>, <BH>)
IFIDNI (<Reg>,<BL>) OR (<Reg>,<BH>) ; JWASM throws Error A2144: Text item required
IFIDNI <Reg>, <BL> OR <Reg>,<BH> ; JWASM throws Error A2209: Syntax error OR
IFIDNI <Reg>, <BL> OR IFIDNI <Reg>, <BL>  ; JWASM throws Error A2209: Syntax error OR


But none of them worked.
Can you tell my, how do i combine several conditional assembly IFIDNI statements with a logical operator like OR?

The only solution i found so far is repeating the code block part after an ELSEIFIDNI, but this is not a very elegant
and clean solution and it is error prone.

IFIDNI <Reg>, <BL>
  ... ; Code A
ELSEIFIDNI <Reg>, <BH>
   ... ; Code A, same Code A as before
ELSE
  ... ; Code B
ENDIF


_japheth

Quote from: bugthis on October 27, 2022, 01:15:23 PM
But how do i combine IFIDNI with the logical OR of the old previous code to test also on AH register?

That's the problem: OR doesn't operate "logical", it's working bitwise and hence accepts numeric arguments only.
Register names are socalled keywords and don't have a numeric value assigned to them since Masm v6.

Quote
The only solution i found so far is repeating the code block part after an ELSEIFIDNI, but this is not a very elegant
and clean solution and it is error prone.

IFIDNI <Reg>, <BL>
  ... ; Code A
ELSEIFIDNI <Reg>, <BH>
   ... ; Code A, same Code A as before
ELSE
  ... ; Code B
ENDIF


I agree. You can instead use the FOR loop operator:

m1 macro arg
   for x,<al,bl,cl>
     ifidni <arg>,<x>
       echo found arg
     endif
   endm
endm
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

jj2007

testme macro arg
Local yes
  yes=0
  ifidni <arg>, <al>
    yes=1
  endif
  ifidni <arg>, <cl>
    yes=1
  endif
  if yes
    dosomething
  endif
endm

bugthis

Quote from: _japheth on October 27, 2022, 03:28:13 PM
Quote from: bugthis on October 27, 2022, 01:15:23 PM
But how do i combine IFIDNI with the logical OR of the old previous code to test also on AH register?

That's the problem: OR doesn't operate "logical", it's working bitwise and hence accepts numeric arguments only.
Register names are socalled keywords and don't have a numeric value assigned to them since Masm v6.
Thank you for the information.

Quote
I agree. You can instead use the FOR loop operator:

m1 macro arg
   for x,<al,bl,cl>
     ifidni <arg>,<x>
       echo found arg
     endif
   endm
endm

But with "for" i can't implement the "else".

That brings me to another question. I know it's not very good to use a GOTO, but is there a GOTO for MASM's preprocessor?

bugthis

Quote from: jj2007 on October 27, 2022, 09:14:04 PM
testme macro arg
Local yes
  yes=0
  ifidni <arg>, <al>
    yes=1
  endif
  ifidni <arg>, <cl>
    yes=1
  endif
  if yes
    dosomething
  endif
endm


Thank you. That seems to be the best solution so far.

_japheth

Quote
But with "for" i can't implement the "else".

Yes, you'd need a helper variable.

Quote
That brings me to another question. I know it's not very good to use a GOTO, but is there a GOTO for MASM's preprocessor?

GOTO exists inside macros, and you can also use EXITM ( exits macros and macro loops [FOR, REPEAT, WHILE ), however it exits just the current level, so if used inside a FOR loop, you'll find yourself behind the ENDM belonging to the FOR.

GOTO labels must be preceded by a colon.


Btw., using LOCAL inside macros is usually a good idea, to avoid unwanted side effects. However, whenever the macro is invoked a new variable is created then, having the probably unwanted side effect to eat up precious memory - something worth to consider if jwasmR is used.
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

bugthis

Quote from: _japheth on October 29, 2022, 05:45:34 PM
Quote
That brings me to another question. I know it's not very good to use a GOTO, but is there a GOTO for MASM's preprocessor?

GOTO exists inside macros, and you can also use EXITM ( exits macros and macro loops [FOR, REPEAT, WHILE ), however it exits just the current level, so if used inside a FOR loop, you'll find yourself behind the ENDM belonging to the FOR.

GOTO labels must be preceded by a colon.
I thought of something like this:

Instead of:

INPUT_X MACRO Reg
IFIDNI <Reg>, <BL>
  ... ; Code A
ELSEIFIDNI <Reg>, <BH>
   ... ; Code A, same Code A as before
ELSE
  ... ; Code B
ENDIF
ENDM

i could use something like this:

INPUT_X MACRO Reg
IFIDNI <Reg>, <BL>
  ... GOTO GA
ELSEIFIDNI <Reg>, <BH>
   ... GOTO GA
ELSE
  ... ; Code B
ENDIF
EXITM
:GA ; Code A
ENDM

This way I only have Code A once in the code without the need for a helper variable. This eliminates the error proneness of having the same code of A in the code multiple times. I only need 2 GOTO commands.

The question is, is it better than the one with the helper variable from jj2007?

Quote
Btw., using LOCAL inside macros is usually a good idea, to avoid unwanted side effects. However, whenever the macro is invoked a new variable is created then, having the probably unwanted side effect to eat up precious memory - something worth to consider if jwasmR is used.
If i put LOCAL in front of the above :GA definition, then JWASMR doesn't see the GM routine before calling GOTO GM.