Hi Branislav & John. You are doing great good job for all asm community. I really like hjwasm, but I found several bugs (tested on hjwasm32.exe only).
Bug#1: Incorrect "while" parsing.
Simple source:
start:
xor edx,edx
mov ecx,1
.while (edx ==0 || edx ==1) && (SDWORD ptr ecx >=0)
inc edx
dec ecx
.endw
.if edx == 2
invoke MessageBox,0,0,0,MB_OK
.else
invoke MessageBox,0,0,0,MB_ICONERROR
.endif
invoke ExitProcess,0
end start
ML.exe (6.14.8444) code:
start:
xor edx, edx
mov ecx, 1
jmp While_check
do_while:
inc edx
dec ecx
While_check:
or edx, edx
jz While_check2
cmp edx, 1
jnz jmp_from_while
While_check2:
cmp ecx, 0
jge do_while
jmp_from_while:
HJWasm v2.17, Dec 5 2016 code:
start:
xor edx, edx
mov ecx, 1
jmp While_check
do_while:
inc edx
dec ecx
While_check:
cmp edx, 0
jz jmp_from_while
cmp edx, 1
jnz jmp_from_while
cmp ecx, 0
jge do_while
jmp_from_while:
Bug#2: For Win64 in many cases missing error: "Register value overwritten by INVOKE" for registers: rcx(ecx) & rdx(edx)
Simple case:
TestProc1 proc Par1:QWORD,Par2:QWORD,Par3:QWORD,Par4:QWORD,Par5:QWORD
ret
TestProc1 endp
start:
mov rcx,555h
mov rdx,666h
invoke TestProc1,111h,rcx,rdx,0,0
end start
40001005: mov rcx, 0x555
4000100C: mov rdx, 0x666
40001013: mov rcx, 0x111
4000101A: mov rdx, rcx
4000101D: mov r8, rdx
40001020: xor r9d, r9d
40001023: mov qword [rsp+0x20], 0x0
4000102C: call 0x40001000
Bug#3 Creating stack error (HJWasm v2.17, Dec 9 2016 bug) , HJWasm v2.13 - works fine.
Simple source:
func proc
LOCAL Buff[128]:byte
xor eax,eax
ret
func endp
55 PUSH EBP
8BEC MOV EBP,ESP
81C4 7FFFFFFF ADD ESP,-81 ;???????????
33C0 XOR EAX,EAX
8BE5 MOV ESP,EBP
5D POP EBP
C3 RET
Bug#4: Completely broken source mode debugging since HJWasm v2.13, Feb 13 2016.
In some of my projects converted from masm to hjwasm, /Zd parameter not generating line number debug information. In code section "number of lines number" = 1 and LINENUMBERS information present only for the first line.
HJWasm v2.13, Feb 13 2016 - source debugging works perfectly.
HJWasm v2.15r2, Oct 1 2016 - source debugging not working.
HJWasm v2.15, Sep 6 2016 - source debugging not working.
HJWasm v2.17, Dec 9 2016 - source debugging not working.
After all of this, HJWasm v2.13 is more stable(bug#3 and Bug#4 not present).
Quote from: powershadow on December 29, 2016, 03:53:22 AM
Hi Branislav & John. You are doing great good job for all asm community.
Indeed :t
p1_s: xor edx,edx
mov ecx,1
.while (edx ==0 || edx ==1) && (SDWORD ptr ecx >=0)
inc edx
dec ecx
.endw
p1_endp: nop
deb 4, "Res", edx, ecx
CodeSize p1
p2_s: xor edx,edx
mov ecx,1
jmp @test
@more: inc edx
dec ecx
@test: test edx, edx
je @ecx
cmp edx, 1
jne @out
@ecx: test ecx, ecx
jns @more
p2_endp: nop
@out: deb 4, "Res", edx, ecx
CodeSize p2
Correct output (ML 6.15):
Res
edx 2
ecx -1
25 bytes for p1
Res
edx 2
ecx -1
24 bytes for p2
Under the hood:
HJWasm32 2.17 & AsmC
00401083 ³. CC int3
00401084 ³. EB 02 jmp short 00401088
00401086 ³> 42 Úinc edx
00401087 ³. 49 ³dec ecx
00401088 ³> 83FA 00 +cmp edx, 0
0040108B ³. 74 0A ³je short 00401097
0040108D ³. 83FA 01 ³cmp edx, 1
00401090 ³. 75 05 ³jne short 00401097
00401092 ³. 83F9 00 ³cmp ecx, 0
00401095 ³. 7D EF Àjge short 00401086
00401097 ³> 90 nop
ML 6.15
00401083 ³. CC int3
00401084 ³. EB 02 jmp short 00401088
00401086 ³> 42 Úinc edx
00401087 ³. 49 ³dec ecx
00401088 ³> 0BD2 +or edx, edx
0040108A ³. 74 05 ³jz short 00401091
0040108C ³. 83FA 01 ³cmp edx, 1
0040108F ³. 75 05 ³jne short 00401096
00401091 ³> 83F9 00 ³cmp ecx, 0
00401094 ³. 7D F0 Àjge short 00401086
00401096 ³> 90 nop
Since AsmC has the same problem, it seems a WatCom issue...
Check the handling of brackets; this produces correct results:
.while edx ==0 || edx ==1 && SDWORD ptr ecx >=0
In any case, SDWORD ptr ecx >=0 could be translated to the shorter test + jns. ML code is already one byte shorter because of
or edx, edx instead of
cmp edx, 0; but to be honest, the coder can force the shorter version with
.while (!edx || edx ==1) && SDWORD ptr ecx >=0
deleted
That problem is fixed in next releise 2.18 and will be out as soon as Johnsa get the time to upload it, we had to add an additional label.
We have also changed 'cmp edx, 0' to 'test edx,edx' to reduce it to 2 bytes instead of 3, we have been tossing between OR and TEST but decided that TEST is more appropriate in that case:
start:
xor edx,edx
00C21000 33 D2 xor edx,edx
00C21002 EB 02 jmp $$$00001+6h (0C21006h)
@C0001:
00C21004 42 inc edx
00C21005 49 dec ecx
@C0004:
00C21006 85 D2 test edx,edx
00C21008 74 05 je $$$00001+0Fh (0C2100Fh)
00C2100A 83 FA 01 cmp edx,1
00C2100D 75 05 jne $$$00001+14h (0C21014h)
@C0002:
00C2100F 83 F9 00 cmp ecx,0
00C21012 7D F0 jge $$$00001+4h (0C21004h)
@C0003:
00C21014 83 FA 03 cmp edx,3
00C21017 75 0F jne $$$00001+28h (0C21028h)
To make code more optimised in this case:
.while (edx ==0 || edx ==1) && (SDWORD ptr ecx >=0)
it should be better to write:
.while (SDWORD ptr ecx >=0) && (edx ==0 || edx ==1)
Quote
start:
xor edx,edx
00D81000 33 D2 xor edx,edx
00D81002 EB 02 jmp $$$00001+6h (0D81006h)
@C0001:
00D81004 42 inc edx
00D81005 49 dec ecx
@C0004:
00D81006 83 F9 00 cmp ecx,0
00D81009 7C 09 jl $$$00001+14h (0D81014h)
@C0002:
00D8100B 85 D2 test edx,edx
00D8100D 74 F5 je $$$00001+4h (0D81004h)
00D8100F 83 FA 01 cmp edx,1
00D81012 74 F0 je $$$00001+4h (0D81004h)
@C0003:
00D81014 83 FA 03 cmp edx,3
00D81017 75 0F jne $$$00001+28h (0D81028h)
Fix is in hll.c
Quote
static ret_code GetAndExpression(struct hll_item *hll, int *i, struct asm_tok tokenarray[], int ilabel, bool is_true, char *buffer, struct hll_opnd *hllop)
/***********************************************************************************************************************************************************/
{
char *ptr = buffer;
uint_32 truelabel = 0;
uint_32 truelabel2 = 0; // added HJWasm 2.18
//char buff[16];
//char *nlabel;
//char *olabel;
DebugMsg1(("%u GetAndExpression(>%.32s< buf=>%s<) enter\n", evallvl, tokenarray[*i].tokpos, buffer));
if (ERROR == GetSimpleExpression(hll, i, tokenarray, ilabel, is_true, ptr, hllop))
return(ERROR);
while (COP_AND == GetCOp(&tokenarray[*i])) {
(*i)++;
DebugMsg1(("%u GetAndExpression: &&-operator found, is_true=%u, lastjmp=%s\n", evallvl, is_true, hllop->lastjmp ? hllop->lastjmp : "NULL"));
if (is_true) {
/* todo: please describe what's done here and why! */
if (hllop->lastjmp) {
char *p = hllop->lastjmp;
InvertJump(p); /* step 1 */
if (truelabel == 0){ /* step 2 */
if (tokenarray[*i-2].token == T_CL_BRACKET) // if '&&' is between closed bracket like ')&&'
truelabel2 = GetHllLabel(); // init truelabel2 for second test
truelabel = GetHllLabel();
}
if (*p ) { /* v2.11: there might be a 0 at lastjmp */
p += 4; /* skip 'jcc ' or 'jmp ' */
if (truelabel > 0) GetLabelStr(truelabel, p); // get string for second test
else GetLabelStr(truelabel2, p);
strcat(p, EOLSTR); // @C0002:
}
DebugMsg1(("%u GetAndExpression: jmp inverted >%s<\n", evallvl, hllop->lastjmp));
if (truelabel2 > 0)
ReplaceLabel(buffer, GetLabel(hll, ilabel), truelabel2);
else
ReplaceLabel(buffer, GetLabel(hll, ilabel), truelabel);
hllop->lastjmp = NULL;
}
}
if (tokenarray[*i-2].token == T_CL_BRACKET){
if (truelabel2 > 0) {
ptr += strlen(ptr);
GetLabelStr(truelabel2, ptr);
strcat(ptr, LABELQUAL EOLSTR);
DebugMsg1(("%u GetAndExpression: label added >%s<\n", evallvl, ptr));
hllop->lastjmp = NULL;
truelabel2 = 0;
}
}
ptr += strlen(ptr);
hllop->lasttruelabel = 0; /* v2.08 */
if (ERROR == GetSimpleExpression(hll, i, tokenarray, ilabel, is_true, ptr, hllop))
return(ERROR);
};
//here is label created
if (truelabel > 0) {
ptr += strlen(ptr);
GetLabelStr(truelabel, ptr);
strcat(ptr, LABELQUAL EOLSTR);
DebugMsg1(("%u GetAndExpression: label added >%s<\n", evallvl, ptr));
hllop->lastjmp = NULL;
}
else {
if (truelabel2 > 0) {
ptr += strlen(ptr);
GetLabelStr(truelabel2, ptr);
strcat(ptr, LABELQUAL EOLSTR);
DebugMsg1(("%u GetAndExpression: label added >%s<\n", evallvl, ptr));
hllop->lastjmp = NULL;
}
}
return(NOT_ERROR);
}
Bug#2:
It is not a bug, I have done it purposely so that we can use same register several times in the function call, like:
xor edx,edx
invoke SomeFunction, rcx, rdx, edx, edx, rdx
instead of:
invoke SomeFunction, rcx, NULL, 0, 0, NULL
If that bothers someone I can create an OPTION, something like: WORNREGOVERWRITTEN
It can be default WORNREGOVERWRITTEN 1
and not WORNREGOVERWRITTEN 0
Bug #3, I have to check yet and Bug #4 is half true, if you use original HJWasm from Teraspace, it will show source code and line nmbers because it is built with msvc2005ddk. Visual Studio is producing different debug info which HJWasm doesn't support.
So, to have fast and small exe with a proper debug info you need to build it with the msvc2005ddk
I'll investigate why is Bug #3 happening, it shouldn't be something complicated
I have added 1 additional local before and then it works fine:
Quote
func proc
LOCAL var :DWORD
LOCAL Buff[128]:byte
xor eax,eax
ret
func endp
0113103C 55 push ebp
0113103D 8B EC mov ebp,esp
0113103F 81 EC 84 00 00 00 sub esp,84h
01131045 33 C0 xor eax,eax
01131047 8B E5 mov esp,ebp
01131049 5D pop ebp
0113104A C3 ret
So, all of issues above will be fixed in 2.18 release.
To prove that HJWasm, when built with
msvc2005ddk produces correct debug info here is an example:
Quote
11: start:
12: call func
002b1010 E8 3C 00 00 00 call 0x2b1051
13: xor edx,edx
002b1015 33 D2 xor edx, edx
14: .while (SDWORD ptr ecx >=0) && (edx ==0 || edx ==1)
002b1017 EB 02 jmp 0x2b101b
15: inc edx
002b1019 42 inc edx
16: dec ecx
002b101a 49 dec ecx
17: .endw
002b101b 83 F9 00 cmp ecx, 0x0
002b101e 7C 09 jl 0x2b1029
002b1020 85 D2 test edx, edx
002b1022 74 F5 jz 0x2b1019
002b1024 83 FA 01 cmp edx, 0x1
002b1027 74 F0 jz 0x2b1019
18: .if edx == 3
002b1029 83 FA 03 cmp edx, 0x3
002b102c 75 0F jnz 0x2b103d
19: invoke MessageBoxA,0,0,0,3
002b102e 6A 03 push 0x3
002b1030 6A 00 push 0x0
002b1032 6A 00 push 0x0
002b1034 6A 00 push 0x0
002b1036 E8 39 10 00 00 call 0x2b2074
20: .else
002b103b EB 0D jmp 0x2b104a
21: invoke MessageBoxA,0,0,0,1
002b103d 6A 01 push 0x1
002b103f 6A 00 push 0x0
002b1041 6A 00 push 0x0
002b1043 6A 00 push 0x0
002b1045 E8 2A 10 00 00 call 0x2b2074
22: .endif
23: invoke ExitProcess,0
002b104a 6A 00 push 0x0
002b104c E8 1D 10 00 00 call 0x2b206e
24:
Quote from: jj2007 on December 29, 2016, 05:13:52 AMSDWORD ptr ecx >=0 could be translated to the shorter test + jns
What do you think about this optimisation?
p2_s: xor edx,edx
mov ecx,1
jmp @test
@more: inc edx
dec ecx
@test: test edx, edx
je @ecx
cmp edx, 1
jne @out
@ecx: test ecx, ecx
jns @more
p2_endp: nop
@ecx: test ecx, ecx
jns @more
It is certainly better than cmp ecx, 0, however, code can be more optimized and faster if we do that:
Quote
p2_s: xor edx,edx
mov ecx,1
jmp @test
@more: inc edx
dec ecx
@test: test ecx, ecx
js @out
test edx, edx
je @more
cmp edx, 1
je @more
@out: nop
Quote from: habran on December 30, 2016, 06:20:41 AMIt is certainly better than cmp ecx, 0, however, code can be more optimized and faster if we do that:
You mentioned that above:
Quote from: habran on December 29, 2016, 02:36:57 PM
To make code more optimised in this case:
.while (edx ==0 || edx ==1) && (SDWORD ptr ecx >=0)
it should be better to write:
.while (SDWORD ptr ecx >=0) && (edx ==0 || edx ==1)
But the question here was rather if
SDWORD ptr ecx >=0 and
edx==0 could generally be translated to
test+jns and
test+jne instead of the longer comparison with zero. Purists will say "that is not what I wrote", of course - but I can't see a situation where this optimisation would cause misbehaving code. And purists would never use .While ... .Endw anyway ;)
Btw ML 6.15 does this for edx==0 above - see or edx, edx in the disassembly.
The Intel manuals have since the PIV days said that INC and DEC are slower than ADD / SUB. If an algorithm is not optimised properly its not like it matters but if the rest of the algo is optimised properly then using ADD / SUB is faster.
Quote from: hutch-- on December 30, 2016, 08:13:32 AMThe Intel manuals have since the PIV days said that INC and DEC are slower than ADD / SUB.
Ah, I love it :t
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz (SSE4)
10 cycles for 1000 * dec
10 cycles for 1000 * sub
9 cycles for 1000 * dec
9 cycles for 1000 * sub
10 cycles for 1000 * dec
10 cycles for 1000 * sub
8 cycles for 1000 * dec
10 cycles for 1000 * sub
9 cycles for 1000 * dec
11 cycles for 1000 * sub
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:
Quote
15: inc edx
00af1019 42 inc edx
16: add ecx, 1
00af101a 83 C1 01 add ecx, 0x1
I have succeeded to change to JS and JNS if we have >= 0 or <=0, here is GE:
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:
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
Hi nidud,
Give me one example where ')&&' doesn't work properly
deleted
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:
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:
here is the first example:
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
deleted
deleted
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:
?_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:
?_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
deleted
deleted
The second one is incorrect! Your algorithm is correct but .while !(eax || edx) && ecx is not. It should produce this:
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
deleted
This .while !(eax || edx) && ecx should be the same as .while (!eax || !edx) && ecx, however:
.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:
.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:
I have checked also what C does and it comes out the same as masm and your fix, so I have implemented your idea and now hjwasm does the same. Here is the c source:
static ret_code GetAndExpression(struct hll_item *hll, int *i, struct asm_tok tokenarray[], int ilabel, bool is_true, char *buffer, struct hll_opnd *hllop)
/***********************************************************************************************************************************************************/
{
char *ptr = buffer;
uint_32 truelabel = 0;
char buff[16];
int nlabel;
int olabel;
DebugMsg1(("%u GetAndExpression(>%.32s< buf=>%s<) enter\n", evallvl, tokenarray[*i].tokpos, buffer));
if (ERROR == GetSimpleExpression(hll, i, tokenarray, ilabel, is_true, ptr, hllop))
return(ERROR);
while (COP_AND == GetCOp(&tokenarray[*i])) {
(*i)++;
DebugMsg1(("%u GetAndExpression: &&-operator found, is_true=%u, lastjmp=%s\n", evallvl, is_true, hllop->lastjmp ? hllop->lastjmp : "NULL"));
if (is_true) {
/* todo: please describe what's done here and why! */
if (hllop->lastjmp) {
char *p = hllop->lastjmp;
InvertJump(p); /* step 1 */
if (truelabel == 0) /* step 2 */
truelabel = GetHllLabel();
if (*p ) {/* v2.11: there might be a 0 at lastjmp */
p += 4; /* skip 'jcc ' or 'jmp ' */
GetLabelStr(truelabel, p);
strcat(p, EOLSTR);
}
/* HJWasm 2.18 fixed WHILE with && */
if (hllop->lasttruelabel)
ReplaceLabel(buffer,hllop->lasttruelabel, truelabel);
if (hll->cmd == HLL_WHILE){ // this is nidud's idea
nlabel = GetHllLabel();
olabel = GetLabel(hll, ilabel);
GetLabelStr(olabel, buff);
strcat(ptr, buff);
strcat(ptr, LABELQUAL EOLSTR);
DebugMsg1(("%u GetAndExpression: label added >%s<\n", evallvl, ptr));
ReplaceLabel(buffer, olabel, nlabel);
}
else{
DebugMsg1(("%u GetAndExpression: jmp inverted >%s<\n", evallvl, hllop->lastjmp));
ReplaceLabel(buffer, GetLabel(hll, ilabel), truelabel);
}
hllop->lastjmp = NULL;
}
}
ptr += strlen(ptr);
hllop->lasttruelabel = 0; /* v2.08 */
if (ERROR == GetSimpleExpression(hll, i, tokenarray, ilabel, is_true, ptr, hllop))
return(ERROR);
};
if (truelabel > 0) {
ptr += strlen(ptr);
GetLabelStr(truelabel, ptr);
strcat(ptr, LABELQUAL EOLSTR);
DebugMsg1(("%u GetAndExpression: label added >%s<\n", evallvl, ptr));
hllop->lastjmp = NULL;
}
return(NOT_ERROR);
}
deleted
Quote from: habran on December 29, 2016, 03:19:25 PM
Bug #3, I have to check yet and Bug #4 is half true, if you use original HJWasm from Teraspace, it will show source code and line nmbers because it is built with msvc2005ddk. Visual Studio is producing different debug info which HJWasm doesn't support.
So, to have fast and small exe with a proper debug info you need to build it with the msvc2005ddk
Hello everybody!
Where can I download
msvc 2005 ddk? On the Internet is very hard to find ..
Happy New Year! Thanks!
See if this will give you the correct version.
https://www.microsoft.com/en-au/download/details.aspx?id=11800
LiaoMi, I think that msvc2003R2.zip (https://drive.google.com/file/d/0B-19qezzOTkANDllNF9LRGNpS1E/edit) is what you need
and here is the .cmd file:
@SET Path=C:\code1\msvc2003R2\bin\amd64
@SET INCLUDE=C:\code1\msvc2003R2\include\crt;
@SET LIB=C:\code1\msvc2003R2\lib\amd64
cl -c -Zl -GS- -O2 -Ox -I..\HJWasm-master\H ..\HJWasm-master\*.c -D_CRT_SECURE_NO_DEPRECATE -DDEBUG_OUT -DWIN64 -DAVXSUPP
cl main.obj apiemu.obj assemble.obj assume.obj atofloat.obj backptch.obj bin.obj branch.obj cmdline.obj codegen.obj coff.obj condasm.obj context.obj cpumodel.obj data.obj dbgcv.obj directiv.obj elf.obj end.obj equate.obj errmsg.obj expans.obj expreval.obj extern.obj fastpass.obj fixup.obj fpfixup.obj hll.obj input.obj invoke.obj label.obj linnum.obj listing.obj loop.obj lqueue.obj macro.obj mangle.obj memalloc.obj msgtext.obj omf.obj omffixup.obj omfint.obj option.obj parser.obj posndir.obj preproc.obj proc.obj queue.obj reswords.obj safeseh.obj segment.obj simsegm.obj string.obj symbols.obj tbyte.obj tokenize.obj types.obj libc.lib bufferoverflowu.lib -o hjwa64v200R2clib.exe
@DEL *.obj
pause
I think that TWell can give you all info you need about building with DDK, you can PM him 8)
For x86 old MS Visual C++ Toolkit 2003 should work, but it is hard to find :(
Also x86 compiler and libc.lib are in 1830_usa_ddk.iso (http://download.microsoft.com/download/9/0/f/90f019ac-8243-48d3-91cf-81fc4093ecfd/1830_usa_ddk.iso)
EDIT: Server 2003 SP1 Platform SDK ISO (https://www.microsoft.com/en-us/download/details.aspx?id=15656)
Thanks TWell, excellent stuff :t
Quote from: TWell on January 02, 2017, 08:03:27 AM
For x86 old MS Visual C++ Toolkit 2003 should work, but it is hard to find :(
You can check this link :
http://www.unfiles.info/vctoolkitsetup.exe/m-download-23770.html
Hello
I testing hJwasm as new Assembler why give hJwasm to cryptic output
Total compile time 734 ms
×ܹ²±àÒëʱ¼ä 734 ºÁÃë <<<<<<<<
And give any macro or function to auto translate registers?
example
if _WIN64 EQU 1 ; registers are auto translated eax to rax etc...
Code example my way is really dirty to use a one project code to build a x86 app or X64
Or has any a better solution or macro?
IFDEF _WIN64
_eax TEXTEQU <rax>
_ebx TEXTEQU <rbx>
_ecx TEXTEQU <rcx>
_edx TEXTEQU <rdx>
_esi TEXTEQU <rsi>
_edi TEXTEQU <rdi>
_ebp TEXTEQU <rbp>
_esp TEXTEQU <rsp>
ELSE
_eax TEXTEQU <eax>
_ebx TEXTEQU <ebx>
_ecx TEXTEQU <ecx>
_edx TEXTEQU <edx>
_esi TEXTEQU <esi>
_edi TEXTEQU <edi>
_ebp TEXTEQU <ebp>
_esp TEXTEQU <esp>
ENDIF
mov _eax,1
Greets,
Hi ragdog,
It sims to me that you are using some other language then English for your text editor :biggrin:
It is pretty complex job to write source that can be used for both 32 and 64 bit.
You can ask rrr314159 about the best way how to do that because he has done some conversion few years ago.
Hi Vortex,
I have downloaded and installed Toolkit 2003 from your link, however, it is only 32 bit.
Here is Russian link for platformSDK2003SP1 (http://ftp.ufanet.ru/pub/microsoft/sdk/)
QuoteIt sims to me that you are using some other language then English for your text editor
I use Radasm2 as Texteditor and use default language ( English)
Greets,
I don't know how to setup Radasm2 for HJWasm, I am using Visual Studio Community 2013 to build my programs.
You can PM Johnsa, to give you some tips how to setup Radasm2 for HJWasm.
Thank you
Quote from: habran on January 07, 2017, 11:50:15 PM
I don't know how to setup Radasm2 for HJWasm, I am using Visual Studio Community 2013 to build my programs.
You can PM Johnsa, to give you some tips how to setup Radasm2 for HJWasm.
RadAsm2->File->New Project-> ...
then
Menu:Project->Project Options->go to Assemble ; replace ML.exe With HJWasm64.exe or HJWasm.exe
@mabdelouahab
This is not my problems to change the compiler settings.
I have only ask fo this cryptic string but all is ok und solved Thank you all.
Just for fun - I am playing around with downloading. This is a simple GUI executable that allows to see the GitHub sources in an edit window. Here is the full source:
include \masm32\MasmBasic\Res\MbGui.asm
GuiControl MyRich, "richedit", x200, w800
GuiControl MyListbox, "listbox", w200
SetGlobals cursel, f$, ct, http$="https://raw.githubusercontent.com/Terraspace/HJWasm/master/"
SetGlobals
Dim t$()
Dim url$()
Let t$(0)="Select a file"
StringToArray 99, gh$() ; the table of contents is embedded as resource #99
For_ ecx=0 To eax-1
.if Instr_(gh$(ecx), '<td class="content">')
mov esi, gh$(ecx+1)
inc ct
Let url$(ct)=http$+Extract$(esi, '/master/', '"')
Let t$(ct)=Extract$(esi, 'title="', '"')
.endif
Next
SetListbox t$() ; fill the listbox
Event Command
.if NotifyCode==LBN_SELCHANGE && LbSel>0 ; if user selects a file from the list...
Let f$=FileRead$(url$(LbSel)) ; ... get its content and display it
SetWin$ hMyRich=f$
SetWin$ hWnd="GitHub - "+url$(LbSel)
.endif
GuiEnd
Hey all,
After my extended vacation ;) I am finally back and after some more testing 2.18 is up on the site and github.
Cheers
John
Hi John,
Tested with my big sources, everything fine :t
Bug#4 still present. /Zd parameter not generating line number debug information for unknown reason.
Are the others sorted?
Also, is the /Zd problem you are having when assembling a 32bit application?
Also which hjwasm version do you use hjwasm32 or hjwasm64 ? (Have you tried both to see if there is a difference?)
I just check bug1 - fixed. bug4 - not fixed. bug2 & bug3 - not checked.
I use hjwasm32 to assembling 32bit application.
I admit, that it depends on source. If i comment some parts then obj file generated with "line numbers". But i can't identify exact dependence.
That's quite odd, I'll investigate it.
Let me know if 2 and 3 are right when you get a chance.
Cheers
John
Hi johnsa.
I spent some time to investigate Bug#4 and found something strange to me:
linenum.c:
static void AddLinnumData( struct line_num_info *data )
...
data->next = NULL;
if ( q->head == NULL)
q->head = q->tail = data;
else {
if (ModuleInfo.Ofssize == USE32) {
if ((q->tail && ((uint_32)q->tail < 0x00FFFFFF))) { // what this check do ??? why 0x00FFFFFF? (i don't understand).
((struct line_num_info *)q->tail)->next = data;
q->tail = data;
}
}
I removed this and other similarly checks. Actually i restored linnum.c like in version 2.13 and bug4 is gone!
Looking into it :)
Hi johnsa, some new bugs :biggrin:
Bug#5: Structures corruption while writing symbolic debug info (/Fs)
void WriteSymbols()
{
...
ld = fopen(pName, "w");
So each linefeed is replaced with a carriage-return – linefeed pair, after that all structures corrupted.
Fix:
void WriteSymbols()
{
...
ld = fopen(pName, "wb");
Also need to check all othesrs functions with fopen (name,"w").
Bug#6 Skipped first procedure while writing symbolic debug info (/Fs)
First procedure has sym->offset==0, so it skipped by this code:
void WriteSymbols()
{
...
if ((sym->state == SYM_INTERNAL && sym->offset==0) || sym->state == SYM_MACRO || sym->state == SYM_TMACRO || sym->state == SYM_GRP) continue;
Bug#4,Bug#5,Bug#6- also present in HJWASM 2.18.
1,2,3,5 and 6 are fixed now and will be in 2.19 (along with some other encoding of mmx and avx512 fixes found by other users).
A question about 4, is this happening when you use the binary (released) packages or when you compile hjwasm from source ?
Quote from: johnsa on January 27, 2017, 10:03:52 AM
A question about 4, is this happening when you use the binary (released) packages or when you compile hjwasm from source ?
Both.
I already found mistake.
if ((q->tail && ((uint_32)q->tail < 0x00FFFFFF))) Why you think that allocated memory address must be less then 0x00FFFFFF ??? This is wrong.
Habran added that to solve an issue when adding switch with line number generation.
I'll leave him to explain it :)
If he can ensure that switch works without that code in then we can make that change, as it does seem strange to me.
A propos .Switch:
\Masm32\ObjAsm32\Code\Macros\System.inc
.switch macro Variable:req, CasReg:=<eax>
mov CasReg, Variable
??CasStk CatStr <CasReg>, <#>, ??CasFlg, <#>, ??CasStk
??CasVar equ CasReg
??CasFlg equ <0> ;;0 = emit an .if, 1 an .elseif
endm
That one chokes, of course... not the fault of HJWasm but friends of ObjAsm32 might not like this behaviour.
I have added that code because I was having "address to large" error for some unknown reason while running .SWITCH-.CASE
I have changed it to the previous code and tested with .SWITCH-.CASE and surprisingly enough it works fine.
We will upload a new version with these changes and see if it will run properly.
Hey all, 2.19 is up which should include all the fixes.
Cheers
John
2.19 works fine with my fat sources, thanks a lot to both of you :t
It is our curse to make you happy :biggrin:
Hahah.. but remember in so doing we also make ourselves happy! :eusa_dance:
My "thank you" is generic - MasmBasic works fine with ML 6.15 and higher, so my baby does not depend on your work. But I believe in competition, and I find that Micros**t needs competitors. You are doing a great service to the whole community :t
Johnsa, you are correct 8)
JJ, Nun says:"Better safe then sorry" and put a condom on a cucamber :biggrin:
Simple code:
0000002C mov [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
0000002F mov [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
00000034 mov [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
0000003A mov [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.0040105C: C60011 mov b,[eax],011
.0040105F: 66C7001111 mov w,[eax],01111
.00401064: C70011111100 mov d,[eax],000111111
.0040106A: C70011111111 mov d,[eax],011111111
Simple code:
00000040 cmp [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
00000043 cmp [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
00000048 cmp [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
0000004E cmp [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.00401070: 833811 cmp d,[eax],011 ;????????????????
.00401073: 6681381111 cmp w,[eax],01111
.00401078: 813811111100 cmp d,[eax],000111111
.0040107E: 813811111111 cmp d,[eax],011111111
Simple code:
00000054 sub [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
00000057 sub [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
0000005C sub [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
00000062 sub [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.00401084: 832811 sub d,[eax],011 ;????????????????
.00401087: 6681281111 sub w,[eax],01111
.0040108C: 812811111100 sub d,[eax],000111111
.00401092: 812811111111 sub d,[eax],011111111
cmp,sub,add and so on... In x64 the same error present to. Tested on HJWasm v2.18.
I can't find documentation to this, but:
.drectve SEGMENT BYTE INFO
db '/subsystem:console',0
.drectve ENDS
hjwasm creates attributes IMAGE_SCN_CNT_INITIALIZED_DATA and IMAGE_SCN_LNK_INFO same way as ml even it is wrong
those should be IMAGE_SCN_LNK_INFO and IMAGE_SCN_LNK_REMOVE , 200h and 800h
PS: poasm.exe do it correctly.
EDIT:
Something about it here (https://msdn.microsoft.com/en-us/library/ms809762.aspx)
QuoteThe .drective section only appears in OBJ files. It contains text representations of commands for the linker.
as there is no way to put correct attributes with SEGMENT INFO, i think it is assembler's job to do that.
Quote from: powershadow on March 03, 2017, 07:16:53 PM
Simple code:
0000002C mov [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
0000002F mov [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
00000034 mov [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
0000003A mov [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.0040105C: C60011 mov b,[eax],011
.0040105F: 66C7001111 mov w,[eax],01111
.00401064: C70011111100 mov d,[eax],000111111
.0040106A: C70011111111 mov d,[eax],011111111
Simple code:
00000040 cmp [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
00000043 cmp [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
00000048 cmp [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
0000004E cmp [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.00401070: 833811 cmp d,[eax],011 ;????????????????
.00401073: 6681381111 cmp w,[eax],01111
.00401078: 813811111100 cmp d,[eax],000111111
.0040107E: 813811111111 cmp d,[eax],011111111
Simple code:
00000054 sub [eax],11h ;Warning A4073: Size not specified, assuming: BYTE
00000057 sub [eax],1111h ;Warning A4073: Size not specified, assuming: WORD
0000005C sub [eax],111111h ;Warning A4073: Size not specified, assuming: DWORD
00000062 sub [eax],11111111h ;Warning A4073: Size not specified, assuming: DWORD
Result:
.00401084: 832811 sub d,[eax],011 ;????????????????
.00401087: 6681281111 sub w,[eax],01111
.0040108C: 812811111100 sub d,[eax],000111111
.00401092: 812811111111 sub d,[eax],011111111
cmp,sub,add and so on... In x64 the same error present to. Tested on HJWasm v2.18.
Version 2.20 is up on the site/GIT. The cmp/add/sub byte override is fixed, along with some other small bugs relating to vmovq encoding and option win64:6 mode.