Author Topic: HJWASM 2.17 bugs  (Read 16245 times)

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #15 on: December 30, 2016, 08:24:27 AM »
I agree with you JJ, test is better then cmp, 1 byte less.
I'll look if I can make it work for hll.
About purists : it can be translated to extremist, remind me on Nazis  :badgrin:
Cod-Father

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #16 on: December 30, 2016, 08:39:13 AM »
Quote
    15:         inc edx
00af1019 42                                  inc         edx 
    16:         add ecx, 1
00af101a 83 C1 01                         add         ecx, 0x1
Cod-Father

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #17 on: December 31, 2016, 06:05:51 AM »
I have succeeded to change to JS and JNS if we have >= 0 or <=0, here is GE:
Code: [Select]
    14:     .while     (edx ==0 || edx ==1)&&(SDWORD ptr ecx >=0)
00b91017 EB 02                            jmp 0xb9101b 
    15:         inc edx
00b91019 42                               inc edx 
    16:         dec ecx
00b9101a 49                               dec ecx 
    17:     .endw
00b9101b 85 D2                            test edx, edx 
00b9101d 74 05                            jz 0xb91024 
00b9101f 83 FA 01                         cmp edx, 0x1 
00b91022 75 04                            jnz 0xb91028 
00b91024 85 C9                            test ecx, ecx 
00b91026 79 F1                            jns 0xb91019 
    18:     .if edx == 3
00b91028 83 FA 03                         cmp edx, 0x3 
00b9102b 75 0F                            jnz 0xb9103c 
and here is LE:
Code: [Select]
    14:     .while     (edx ==0 || edx ==1)&&(SDWORD ptr ecx <=0)
00cc1017 EB 02                            jmp 0xcc101b 
    15:         inc edx
00cc1019 42                               inc edx 
    16:         dec ecx
00cc101a 49                               dec ecx 
    17:     .endw
00cc101b 85 D2                            test edx, edx 
00cc101d 74 05                            jz 0xcc1024 
00cc101f 83 FA 01                         cmp edx, 0x1 
00cc1022 75 04                            jnz 0xcc1028 
00cc1024 85 C9                            test ecx, ecx 
00cc1026 78 F1                            js 0xcc1019 
    18:     .if edx == 3
00cc1028 83 FA 03                         cmp edx, 0x3 
00cc102b 75 0F                            jnz 0xcc103c
Cod-Father

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #18 on: December 31, 2016, 06:09:17 AM »
Hi nidud,
Give me one example where ')&&' doesn't work properly
Cod-Father

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #19 on: December 31, 2016, 07:38:22 AM »
I wrote a few yesterday but now they're all gone now for some reason.

Well, my argument was that the hack inserted in v2.11 was logically correct but produced the wrong (or invert) result. These cases works in the current version, hence the assumption that the logic is correct:
Code: [Select]
.if (eax || edx) && ecx
nop
.endif

.if !(eax || edx) && ecx
nop
.endif

I will assume that after the changes the invert case may fail.
Code: [Select]
.if !(eax || edx) && ecx
nop
.endif

.while !(eax || edx) && ecx
nop
.endw

The current encoding seems to be flipped somehow:
Code: [Select]
.while (eax || edx) && ecx
        jmp     ?_002           
?_001:  nop                     
?_002: test eax, eax ; encoding for !(eax || edx) && ecx
jnz ?_003
        test    edx, edx         
jz ?_003 ; - should be JNZ
        test    ecx, ecx         
        jnz     ?_001           

Code: [Select]
.while !(eax || edx) && ecx
?_004:  jmp     ?_006
?_005:  nop
?_006: test eax, eax ; encoding for (eax || edx) && ecx
        jnz     ?_007
        test    edx, edx       
jnz ?_008 ; - should be JZ
?_007:  test    ecx, ecx
        jnz     ?_005   

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #20 on: December 31, 2016, 08:35:33 AM »
I think you are not concentrated enough to realise that first example is doing correct job.
In second example '!' is taken only for the first register and not for the second. If you write  .while (!eax || !edx) && ecx
it does a proper job:
Code: [Select]
    18: .while (!eax || !edx) && ecx
0010102e EB 01                            jmp 0x101031 
    19: nop
00101030 90                               nop 
    20: .endw
00101031 85 C0                            test eax, eax 
    20: .endw
00101033 74 04                            jz 0x101039 
00101035 85 D2                            test edx, edx 
00101037 75 04                            jnz 0x10103d 
00101039 85 C9                            test ecx, ecx 
0010103b 75 F3                            jnz 0x101030 
    21:
    21:
Cod-Father

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #21 on: December 31, 2016, 08:39:35 AM »
here is the first example:
Code: [Select]
    12: .while (eax || edx) && ecx
00101010 EB 01                            jmp 0x101013 
    13: nop
00101012 90                               nop 
    14: .endw
00101013 85 C0                            test eax, eax 
00101015 75 04                            jnz 0x10101b 
00101017 85 D2                            test edx, edx 
00101019 74 04                            jz 0x10101f 
0010101b 85 C9                            test ecx, ecx 
0010101d 75 F3                            jnz 0x101012 
0010101f EB 01
Cod-Father

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #22 on: December 31, 2016, 09:02:32 AM »
The previous missing post:
I did some testing with this .WHILE thing and it appear to be the inverse problem that resulted in the current hack. The test was added in v2.11 and I  extended the test to preserve the (missing) label. This removed the error message but not the actual problem. The fix you provided appear to work for the current test but fails if you invert the statement.
Code: [Select]
.while (eax || edx) && ecx
.while !(eax || edx) && ecx

The same seems to apply to .IF/.ELSEIF/.UNTIL and so on. The jump-around label is lost and should at best be replaced with the exit label.

ML code:
Code: [Select]
.while !(eax || edx) && ecx
 00000000  EB 01    *     jmp    @C0001
 00000002    *@C0002:
 00000002  90 nop
.endw
 00000003    *@C0001:
 00000003  0B C0    *     or eax, eax
 00000005  75 08    *     jne    @C0003
 00000007  0B D2    *     or edx, edx
 00000009  75 04    *     jne    @C0003
 0000000B  0B C9    *     or ecx, ecx
 0000000D  75 F3    *     jne    @C0002
 0000000F    *@C0003:

I think you are not concentrated enough to realise that first example is doing correct job.
In second example '!' is taken only for the first register and not for the second. If you write  .while (!eax || !edx) && ecx

it does a proper job:
Code: [Select]
    18: .while (!eax || !edx) && ecx
0010102e EB 01                            jmp 0x101031 
    19: nop
00101030 90                               nop 
    20: .endw
00101031 85 C0                            test eax, eax 
    20: .endw
00101033 74 04                            jz 0x101039 
00101035 85 D2                            test edx, edx 
00101037 75 04                            jnz 0x10103d 
00101039 85 C9                            test ecx, ecx 
0010103b 75 F3                            jnz 0x101030 
    21:
    21:

The correct encoding should be something like this:
Code: [Select]
.while !eax && !edx && ecx
And this also produce the correct result:
Code: [Select]
0000001C                        .while !eax && !edx && ecx
0000001C  EB01              *   jmp @C0009
0000001E                    *   @C0007:
0000001E  90                    nop
0000001F                        .endw
0000001F                    *   @C0009:
0000001F  85C0              *   test eax , eax
00000021  7508              *   jnz @C0008
00000023  85D2              *   test edx , edx
00000025  7504              *   jnz @C0008
00000027  85C9              *   test ecx, ecx
00000029  75F3              *   jnz @C0007
0000002B                    *   @C0008:

Before the changes was made this was also the case with .IF
Code: [Select]
00000000                        .if !(eax || edx) && ecx
00000000  85C0              *   test eax , eax
00000002  7509              *   jnz @C0001
00000004  85D2              *   test edx, edx
00000006  7505              *   jnz @C0001
00000008  85C9              *   test ecx, ecx
0000000A  7401              *   jz  @C0001
0000000C  90                    nop
0000000D                        .endif
0000000D                    *   @C0001:

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #23 on: December 31, 2016, 09:11:27 AM »
So, to be clear, both of these where wrongly encoded before the changes was made:
Code: [Select]
.while (eax || edx) && ecx
.while !(eax || edx) && ecx

The first seems to work after the changes. The question was if the latter also work. If not then .if !(eax || edx) && ecx may also fail.

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #24 on: December 31, 2016, 03:22:05 PM »
It looks like .while !(eax || edx) && ecx is icorect encoding because ml.exe creates the wrong code as well

Here is what ml.exe does:
Code: [Select]
?_004:  jmp     ?_006                                   ; 0040101F _ EB, 01

?_005:  nop                                             ; 00401021 _ 90
?_006:  or      eax, eax                                ; 00401022 _ 0B. C0
        jnz     ?_007                                   ; 00401024 _ 75, 08
        or      edx, edx                                ; 00401026 _ 0B. D2
        jnz     ?_007                                   ; 00401028 _ 75, 04
        or      ecx, ecx                                ; 0040102A _ 0B. C9
        jnz     ?_005                                   ; 0040102C _ 75, F3
?_007: 
It should be .while (!eax || !edx) && ecx
This produces a proper code:
Code: [Select]
?_007:  jmp     ?_009                                   ; 0040102E _ EB, 01

?_008:  nop                                             ; 00401030 _ 90
?_009:  or      eax, eax                                ; 00401031 _ 0B. C0
        jz      ?_010                                   ; 00401033 _ 74, 04
        or      edx, edx                                ; 00401035 _ 0B. D2
        jnz     ?_011                                   ; 00401037 _ 75, 04
?_010:  or      ecx, ecx                                ; 00401039 _ 0B. C9
        jnz     ?_008                                   ; 0040103B _ 75, F3
?_011:  or      eax, eax                                ; 0040103D _ 0B. C0

If you check code few posts above you'll see that hjwasm produces the same output

Cod-Father

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #25 on: December 31, 2016, 04:09:31 PM »

https://github.com/nidud/asmc/blob/master/source/asmc/regress/src/bin/RTCOND9.ASM

Code: [Select]
.if !(1 || 1) ;false
inc eax
.endif

.if !(0 || 1) ;false
inc eax
.endif

.if !(1 || 0) ;false
inc eax
.endif

.if !(0 || 0) ;true
inc eax
.endif

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #26 on: December 31, 2016, 06:06:52 PM »
This seems to work
Code: [Select]
; operator &&, which has the second lowest precedence, is handled here

GetAndExpression PROC USES esi edi ebx,
hll: PTR hll_item,
i: PTR SINT,
tokenarray: PTR asm_tok,
ilabel: UINT,
is_true: UINT,
buffer: LPSTR,
hllop: PTR hll_opnd

local truelabel: SINT,
nlabel: SINT,
olabel: SINT,
buff[16]: SBYTE

mov edi,hllop
mov esi,buffer
mov truelabel,0

.while 1

GetSimpleExpression( hll, i, tokenarray, ilabel, is_true, esi, edi )
cmp eax,ERROR
je toend
mov ebx,i
mov eax,[ebx]
shl eax,4
add eax,tokenarray
.break .if GetCOp( eax ) != COP_AND
inc DWORD PTR [ebx]
mov ebx,[edi].hll_opnd.lastjmp
.if ebx && is_true

InvertJump( ebx )

.if truelabel == 0

mov truelabel,GetHllLabel()
.endif
;
; v2.11: there might be a 0 at lastjmp
;
.if BYTE PTR [ebx]

strcat( GetLabelStr( truelabel, addr [ebx+4] ), addr EOLSTR )
.endif
;
; v2.22 .while (eax || edx) && ecx -- failed
; .while !(eax || edx) && ecx -- failed
;
mov ebx,esi
                        .if [edi].hll_opnd.lasttruelabel

ReplaceLabel( ebx, [edi].hll_opnd.lasttruelabel, truelabel )
.endif

mov eax,hll
.if [eax].hll_item.cmd == HLL_WHILE

mov nlabel,GetHllLabel()
mov olabel,GetLabel( hll, ilabel )
strlen( ebx )
add ebx,eax
sprintf( ebx, "%s%s%s", GetLabelStr( olabel, addr buff ), addr LABELQUAL, addr EOLSTR )
ReplaceLabel( buffer, olabel, nlabel )
.else

ReplaceLabel( buffer, GetLabel( hll, ilabel ), truelabel )
.endif
mov [edi].hll_opnd.lastjmp,0
.endif

strlen( esi )
add esi,eax
mov [edi].hll_opnd.lasttruelabel,0
.endw

.if truelabel

strlen( esi )
add esi,eax
strcat( strcat( GetLabelStr( truelabel, esi ), addr LABELQUAL ), addr EOLSTR )
mov [edi].hll_opnd.lastjmp,0
.endif
mov eax,NOT_ERROR
toend:
ret
GetAndExpression ENDP

Output:
Code: [Select]
0000001A                        .while (eax || edx) && ecx
0000001A  EB01              *   jmp @C0008
0000001C                    *   @C0005:
0000001C  90                    nop
0000001D                        .endw
0000001D                    *   @C0008:
0000001D  85C0              *   test eax , eax
0000001F  7504              *   jnz @C0007
00000021  85D2              *   test edx, edx
00000023  7404              *   jz  @C0006
00000025                    *   @C0007:
00000025  85C9              *   test ecx, ecx
00000027  75F3              *   jnz @C0005
00000029                    *   @C0006:

00000029                        .while !(eax || edx) && ecx
00000029  EB01              *   jmp @C000E
0000002B                    *   @C0009:
0000002B  90                    nop
0000002C                        .endw
0000002C                    *   @C000E:
0000002C  85C0              *   test eax , eax
0000002E  7508              *   jnz @C000C
00000030                    *   @C000B:
00000030  85D2              *   test edx, edx
00000032  7504              *   jnz @C000C
00000034                    *   @C000D:
00000034  85C9              *   test ecx, ecx
00000036  75F3              *   jnz @C0009
00000038                    *   @C000C:

Test case:
https://github.com/nidud/asmc/blob/master/source/asmc/regress/src/bin/RTCOND10.ASM

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #27 on: January 01, 2017, 08:58:28 AM »
The second one is incorrect! Your algorithm is correct but .while !(eax || edx) && ecx is not. It should produce this:
Code: [Select]
009d102e EB 01                            jmp 0x9d1031 
009d1030 90                               nop 
009d1031 85 C0                            test eax, eax 
009d1033 74 04                            jz 0x9d1039 
009d1035 85 D2                            test edx, edx 
009d1037 75 04                            jnz 0x9d103d 
009d1039 85 C9                            test ecx, ecx 
009d103b 75 F3                            jnz 0x9d1030 
009d103d
Cod-Father

nidud

  • Member
  • *****
  • Posts: 1934
    • https://github.com/nidud/asmc
Re: HJWASM 2.17 bugs
« Reply #28 on: January 01, 2017, 09:53:29 AM »
this:
Code: [Select]
.while !(eax || edx) && ecx
is the same as this:
Code: [Select]
.while (!eax && !edx) && ecx
same as this:
Code: [Select]
.while !eax && !edx && ecx
and this:
Code: [Select]
if ( !(a || b) && c )

so this assumption is wrong:
Code: [Select]
.while (!eax || !edx) && ecx

example:

Code: [Select]
    if ( opnd1->kind == EXPR_EMPTY &&  !( tokenarray[*i].token == T_OP_BRACKET || tokenarray[*i].token == T_OP_SQ_BRACKET || tokenarray[*i].token == '+' || tokenarray[*i].token == '-' || tokenarray[*i].token == T_UNARY_OPERATOR ) )
same as:
Code: [Select]
    if ( a && !( b || c || d || e || f ) )

the only way this becomes true:
Code: [Select]
    if ( 1 && !( 0 || 0 || 0 || 0 || 0 ) )

so !( every value inside these brackets is a break statement )

same as:
Code: [Select]
    if ( a && !b && !c && !d && !e && !f )

habran

  • Member
  • *****
  • Posts: 1225
    • uasm
Re: HJWASM 2.17 bugs
« Reply #29 on: January 01, 2017, 02:03:53 PM »
This .while !(eax || edx) && ecx   should be the same as .while (!eax || !edx) && ecx, however:

Code: [Select]
.while !(eax || edx) && ecx
nop
.endw
ml.exe produces:
?_004:  jmp     ?_006                                   ; 0040101F _ EB, 01

?_005:  nop                                             ; 00401021 _ 90
?_006:  or      eax, eax                                ; 00401022 _ 0B. C0
        jnz     ?_007                                   ; 00401024 _ 75, 08
        or      edx, edx                                ; 00401026 _ 0B. D2
        jnz     ?_007                                   ; 00401028 _ 75, 04
        or      ecx, ecx                                ; 0040102A _ 0B. C9
        jnz     ?_005                                   ; 0040102C _ 75, F3
?_007: 

Code: [Select]
.while (!eax || !edx) && ecx
nop
.endw
ml.exe produces:
?_007:  jmp     ?_009                                   ; 0040102E _ EB, 01

?_008:  nop                                             ; 00401030 _ 90
?_009:  or      eax, eax                                ; 00401031 _ 0B. C0
        jz      ?_010                                   ; 00401033 _ 74, 04
        or      edx, edx                                ; 00401035 _ 0B. D2
        jnz     ?_011                                   ; 00401037 _ 75, 04
?_010:  or      ecx, ecx                                ; 00401039 _ 0B. C9
        jnz     ?_008                                   ; 0040103B _ 75, F3
?_011: 

Cod-Father