Author Topic: An interesting issue  (Read 798 times)

johnsa

  • Member
  • ****
  • Posts: 791
    • Uasm
An interesting issue
« on: August 06, 2019, 12:30:41 AM »

The below code produces un-expected result.

Code: [Select]

 .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

  • Member
  • ***
  • Posts: 469
    • LetTheLightIn
Re: An interesting issue
« Reply #1 on: August 06, 2019, 01:15:25 AM »
Might cause problems if for example you have two separate tracks of include files based on a conditional assembly.

Code: [Select]
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?
fearless

CM690II Case, HX1000 PSU, Asus Z97, Intel i7-4790K, Seidon 120v Cooler, 16GB DDR3, MSI GTX 980TI

My Github  Twitter

johnsa

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #2 on: August 06, 2019, 01:31:39 AM »
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

  • Member
  • *****
  • Posts: 1803
    • https://github.com/nidud/asmc
Re: An interesting issue
« Reply #3 on: August 06, 2019, 01:39:05 AM »
;.386
;.model flat
.code
l0: cmp ecx,l2-l0
l1: org $+100h
l2:
%   echo @CatStr(%(l1-l0))
    mov eax,l1-l0
    end


ML/ML64 calculate this to 14 and asmc/uasm 3, but they all (x86) move 6 to eax.

...

If you remove ORG ML still assume this to be 14 so this will not assemble:

l0: cmp ecx,l2-l0
l1:
l2:
if (l1-l0) eq 3
    mov eax,l1-l0
endif

johnsa

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #4 on: August 06, 2019, 02:39:58 AM »
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

  • Member
  • *****
  • Posts: 9811
  • Assembler is fun ;-)
    • MasmBasic
Re: An interesting issue
« Reply #5 on: August 06, 2019, 03:59:22 AM »
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

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #6 on: August 06, 2019, 04:11:19 AM »
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 :)

AW

  • Member
  • *****
  • Posts: 2447
  • Let's Make ASM Great Again!
Re: An interesting issue
« Reply #7 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

 

HSE

  • Member
  • *****
  • Posts: 1148
  • <AMD>< 7-32>
Re: An interesting issue
« Reply #8 on: August 06, 2019, 05:16:32 AM »
This work with "org 10" but not with "org 100" ¿?:
Code: [Select]
.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

johnsa

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #9 on: August 06, 2019, 05:20:13 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 ..

AW

  • Member
  • *****
  • Posts: 2447
  • Let's Make ASM Great Again!
Re: An interesting issue
« Reply #10 on: August 06, 2019, 05:29: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

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #11 on: August 06, 2019, 06:16:20 AM »
This work with "org 10" but not with "org 100" ¿?:
Code: [Select]
.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

  • Member
  • *****
  • Posts: 1148
  • <AMD>< 7-32>
Re: An interesting issue
« Reply #12 on: August 06, 2019, 06:26:12 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?

johnsa

  • Member
  • ****
  • Posts: 791
    • Uasm
Re: An interesting issue
« Reply #13 on: August 06, 2019, 06:50:00 AM »
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

  • Member
  • *****
  • Posts: 1803
    • https://github.com/nidud/asmc
Re: An interesting issue
« Reply #14 on: August 06, 2019, 06:59:22 AM »
Masm will create a long imm even if the distance is less than 128 so the default size is then 6 but it still get the distance wrong. If you extend the value to 6 the calculation is still off by one byte for some reason.

l0: cmp ecx,dword ptr (l2-l0)
l1: org $+100h
l2:
%   echo @CatStr(%(l1-l0))

5

This however works:
l0: cmp ecx,dword ptr 106h
l1: org $+100h
l2:
%   echo @CatStr(%(l1-l0))

6

Using a long value as default and reduce it in the second pass may then solve the problem at hand, but then again this will fail if the end result is reduced.