News:

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

Main Menu

An interesting issue

Started by johnsa, August 06, 2019, 12:30:41 AM

Previous topic - Next topic

johnsa


The below code produces un-expected result.



.686p
.model flat
.code

Len0:           
            cmp    ecx,Len2-Len0
Len1:           
            org    $+100h
Len2:           

Lenx        equ    (Len1-Len0)

if Lenx EQ 6
xor eax,eax
else
xor ebx,ebx
endif

            end



The issue seems to relate to the fact that the pre-processor handles if/else/endif etc in a pass before the final value of the equate can be determined. So the final EQU value is 6, which is correct however the conditional assembly happens based on the value being 3 from the first pass.

The same result seems to be produced by MASM and I would guess ASMC too.

Fixing this problem I suspect would be non-trivial as I'm not 100% sure what the implications would be of delaying the handling of the conditional assembly.

Interested to get other peoples thoughts on this.

fearless

Might cause problems if for example you have two separate tracks of include files based on a conditional assembly.

IF something eq somevalue
include file1.inc
ELSE
include file2.inc
ENDIF

I can understand how it might appear that all the stuff that comes before the check for the conditional is all done and dusted, all evaluated - including the forward references.

Looks like it would be a tough nut to crack though - provisionally handle conditionals on a first pass and then handle them again after some other pass to check for those forward references?

johnsa

Agreed.

The tricky part is the the conditional assembly modifies the source stream which is then handled in subsequent passes. So by current design you lose the ability to keep re-evaluation the conditional code.
The only thing I can think now is that we need to force at least another pass before dealing with conditional pre-processing. That would probably slow the assembler down in some cases.

Another idea would be to simply output warnings for ANY/ALL equates whose value changes between passes.. that way it's up to the coder then to decide if that has caused an issue.

nidud

#3
deleted

johnsa

We are "more" correct than MASM, but still not 100% correct. I guess the decision is do we change the way conditional processing is handled to give 100% accurate result, or do we at least warn about something going potentially awry..

jj2007

Warning, John. There is always somebody (like me) who wants to remain compatible with buggy Masm, and such people will complain that your assembler breaks existing code. Even if that sounds illogical. Anyway, it's an exotic problem.

johnsa

That is why I'm leaning more towards some sort of warning.. something along the lines of:

Warning: [Equate X used by Preprocessor changed size in PASS n]

That way it would only show IFF you used the equate in a pre-processor expression evaluation and if it changed value due to an additional pass, and then it's just a warning. What you do about it from there is your problem :)

aw27

This behavior is mentioned in the Masm 6.1 Readme.txt

Span-Dependent Expressions used in Macros
     --------------------------------------------------
     MASM 6.1x evaluates macro expressions only on the first pass of
     assembly, but code and data are reevaluated on subsequent passes.
     Because of this, macro expressions which depend on the span between
     two addresses may not evaluate correctly. For instance, the
     following code will not evaluate correctly:

     Label1:
          JMP Label2
     Label2:

     REPEAT Label2 - Label1  ; Evaluates incorrectly
          INC AX
     ENDM


HSE

This work with "org 10" but not with "org 100" ¿?: .686p
.model flat
.code

Len0:           
    cmp    ecx, Len2-Len0
Len1:           
    org    $+10h
Len2:           
mov eax , Len1-Len0
lenx1 = Len1-Len0
if lenx1 EQ 3
    xor eax,eax
    len3 = 1
else
    xor ebx,ebx
    len3 = 4
endif
mov eax, len3
end Len0
Equations in Assembly: SmplMath

johnsa

Quote from: AW on August 06, 2019, 04:45:38 AM
This behavior is mentioned in the Masm 6.1 Readme.txt

Span-Dependent Expressions used in Macros
     --------------------------------------------------
     MASM 6.1x evaluates macro expressions only on the first pass of
     assembly, but code and data are reevaluated on subsequent passes.
     Because of this, macro expressions which depend on the span between
     two addresses may not evaluate correctly. For instance, the
     following code will not evaluate correctly:

     Label1:
          JMP Label2
     Label2:

     REPEAT Label2 - Label1  ; Evaluates incorrectly
          INC AX
     ENDM

Yep this is definitely expected behaviour, it's just not very smart ..

aw27

Quote from: johnsa on August 06, 2019, 05:20:13 AM
Yep this is definitely expected behaviour, it's just not very smart ..
It is mentioned in the "Known Assembler Bugs" section. Probably, after 26 years nobody reminded them about that. There are others I believe are still there, but would need to confirm.

johnsa

Quote from: HSE on August 06, 2019, 05:16:32 AM
This work with "org 10" but not with "org 100" ¿?: .686p
.model flat
.code

Len0:           
    cmp    ecx, Len2-Len0
Len1:           
    org    $+10h
Len2:           
mov eax , Len1-Len0
lenx1 = Len1-Len0
if lenx1 EQ 3
    xor eax,eax
    len3 = 1
else
    xor ebx,ebx
    len3 = 4
endif
mov eax, len3
end Len0


ORG 10 will probably work because the opcode remains in it's 3-byte form instead of needing a DWORD imm value (>byte imm value)

HSE

Quote from: johnsa on August 06, 2019, 06:16:20 AM
ORG 10 will probably work because the opcode remains in it's 3-byte form instead of needing a DWORD imm value (>byte imm value)
Yes. But, why is posible to calculate before expansion lenx1=Len1-Len0 when is 3 and not when is 6?
Equations in Assembly: SmplMath

johnsa

The default assumption on the 1st pass is the optimal one. The instruction is de-optimised in subsequent pass only if required. So if the value is truly 3 (which is the optimal) then everything works out. It only goes wonky when at a following pass it has to extend the instruction and hence the distance between addresses.

nidud

#14
deleted