Hello folks,
UASM 2.40 release is out, with fixes:
.SWITCH to allow negative and positive cases and usage of multi cases:
.case 1, 2, 3, 4... or
.case 1
.case 2
.case 3
.case 4
.FOR will report an error if you don't use 2 columns, this is the minimum requirement ( : : )
Improved integers usage for building with different environments
fixed some problem with literals in 32 bit
fixed some listing issues
check it here:
Uasm (Site) http://www.terraspace.co.uk/uasm.html
Uasm (GitHub) https://github.com/Terraspace/UASM
Works fine with my big sources but it chokes with this one (an old source that built fine years ago... mystery ::)):
include \masm32\MasmBasic\Res\MbGui.asm
.data?
MyFonts dd 4 dup(?)
.code
mov edi, offset MyFonts
MakeFont stosd, Height:14, "Times New Roman"
MakeFont stosd, Height:16
MakeFont stosd, Height:20
MakeFont stosd, Height:24
Event Paint
For_ ct=0 To 3
mov ecx, ct
GuiTextBox ct*32+7, ct*64+7, 100, 50, Str$("This is textbox #%i ", ct+1), font MyFonts[4*ecx]
Next
GuiEnd
The issue is admittedly exotic (and there is a workaround, see attached project):
include \masm32\include\masm32rt.inc
any macro arg
Local oa
oa = opattr arg
if oa eq 48
print "&arg is a register", 13, 10
else
print "&arg is not a register", 13, 10
endif
endm
.code
start:
any eax
any nop
inkey "Hello World"
exit
end start
This works in UAsm and ML. This doesn't: if (opattr arg) eq 48
In short:
oa = opattr arg works with everything,
if (opattr arg) eq ... doesn't work with an "exotic" arg like nop or stosd
This is an inconsistent behaviour, btw also of Microsoft MASM. So if you decide to remain compatible, I will support your decision :lol:
IMHO if (opattr arg) should use 0 to indicate "other" if the arg doesn't fit into the immediate, mem, register etc categories, but it should never throw an error.
:dazzled:
13120: if (opattr arg) eq 48
13121: nop
13122: else
13123: nop
00B09838 90 nop
13124: nop
00B09839 90 nop
13125: endif
Quote
oa = opattr arg works with everything,
Does not work in ML and works in UASM for some unknown reason. :shock:
Quote
if (opattr arg) eq ... doesn't work with an "exotic" arg like nop or stosd
Well, we can make it work in both ML and UASM, I just don't know if this is what you want: :icon_rolleyes:
include \masm32\include\masm32rt.inc
OPTION NOKEYWORD: <nop>
any macro arg
Local oa
;;oa = opattr arg
;;if oa eq 48
if (opattr arg) eq 48
print "&arg is a register", 13, 10
else
print "&arg is not a register", 13, 10
endif
endm
.code
start:
any eax
any nop
inkey "Hello World"
exit
end start
deleted
Quote from: aw27 on September 21, 2017, 08:17:45 PM
Quote
oa = opattr arg works with everything,
Does not work in ML and works in UASM for some unknown reason. :shock:
You are right, it works with JWasm, UAsm, AsmC but chokes with the ML versions I tested. Sorry for the wrong info.
QuoteQuoteif (opattr arg) eq ... doesn't work with an "exotic" arg like nop or stosd
Well, we can make it work in both ML and UASM, I just don't know if this is what you want: :icon_rolleyes:
include \masm32\include\masm32rt.inc
OPTION NOKEYWORD: <nop>
Undefining keywords is not a solution. Ideally, and that is what the Watcom family does, the programmer should decide if e.g.
stosd is a valid argument or not. But for the sake of compatibility with ML, the workaround
ifidni <arg>, <stosd> is acceptable and perhaps preferable.
The MASM manual expressly says "You cannot use reserved words as parameter
names (...for macros) unless you disable the keyword with OPTION NOKEYWORD". It is not exactly the same thing as using reserved words as parameters but the MASM manual is full of slightly imprecise statements.
If JWasm, UAsm, AsmC let you do that it can be one of 2 things: a bonus or a subtle bug.
I suspect it is a bug because, as you have noticed, will not be processed within the macro as expected.
Quote
the workaround ifidni <arg>, <stosd> is acceptable and perhaps preferable
Through some magic it is possible to turn a bug into a bonus then. :exclaim:
Quote from: aw27 on September 22, 2017, 03:22:53 AMI suspect it is a bug because, as you have noticed, will not be processed within the macro as expected.
The "long"
oa = opattr arg form gets correctly processed by UAsm:
include \masm32\include\masm32rt.inc
any macro arg
Local oa
oa = opattr arg
if oa eq 48
print chr$("&arg is a register", 13, 10)
else
print chr$("&arg is not a register", 13, 10)
endif
endm
.code
start:
; int 3
any eax
any nop
exit
end start
habran,
the compiler is your willing servant: turn on all warnings (I guess you are using MSVS) and watch out for C4554(!). Checking all occurrences of C4701 and C4703 might be also useful. Easy to fix: C4101 and C4189.
BTW: Just reading some minutes in hll.c (code related to your dot-for-loop) brings up two raw copy-loops where one cause buffer overflows and the other some subtle bug that produce nonexisting identifiers while removing white spaces...
EDIT: an other nice find: C4334 (x64-Build) in expreval.c
regards
Hi qWORD, thanks for reporting :t
Can you please give me some details about error in .for - .endfor code? Maybe source code?
Regarding warnings, I agree with you that it is already overdue to clean it up, however, there is always something more urgent to work on :biggrin:
I'll look at that ASAP
RE C4554 (precedence of operators!):
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/codegen.c#L655
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/codegen.c#L656
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/symbols.c#L822
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/symbols.c#L825
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/symbols.c#L828
C4334 (32bit shift, but 64bit probably expected):
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/expreval.c#L303
Buffer overflow for identifiers with size >= 256 (also: if-statement in loop is deadcode):
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/hll.c#L1186
Identifiers starting with any valid ID-char. other than a-z cause concatenation of tokens (e.g BYTE ptr _MyVar):
https://github.com/Terraspace/UASM/blob/76ee4d61c6a1c4c061b083ba2c8253bb5b1c11ea/hll.c#L1606
regards
Hi,
using the Visual Studio PVS-Studio plugin - https://www.viva64.com/en/pvs-studio/ (https://www.viva64.com/en/pvs-studio/)
QuotePVS-Studio is a tool for bug detection in the source code of programs, written in C, C++ and C#. It works in Windows and Linux environment.
PVS-Studio performs static code analysis and generates a report that helps a programmer find and fix bugs. PVS-Studio performs a wide range of code checks, it is also useful to search for misprints and Copy-Paste errors. Examples of such errors: V501, V517, V522, V523, V3001.
The main value of static analysis is in its regular use, so that errors are identified and fixed at the earliest stages. There is no point in wasting 50 hours looking for a bug that could be found with static analysis. So, let's point out that again - the main idea of static analysis is not to find one hidden bug on the day before the release, but to fix dozens of bugs day by day.
The analyzer can be run at night on the server and warn about suspicious code fragments. Ideally, these errors can be detected and fixed before getting into the repository. PVS-Studio can automatically be launched immediately after the compiler for the files that have been just modified. It works in Windows and Linux.
you can find a lot of bugs, probably not all are important, here is an interesting example
V647 The value of 'int' type is assigned to the pointer of 'char' type. Consider inspecting the assignment: 'tmp = _alloca(size)'. bin.c 1813
#if PE_SUPPORT && RAWSIZE_ROUND
if ( modinfo->sub_format == SFORMAT_PE ) {
size = ftell( CurrFile[OBJ] );
if ( size & ( cp.rawpagesize - 1 ) ) {
char *tmp;
size = cp.rawpagesize - ( size & ( cp.rawpagesize - 1 ) );
tmp = myalloca( size );
memset( tmp, 0, size );
fwrite( tmp, 1, size, CurrFile[OBJ] );
}
}
#endif
or
V512 A call of the 'memset' function will lead to overflow of the buffer 'sym'. symbols.c 250
struct asym *SymAlloc( const char *name )
/***************************************/
{
int len = strlen( name );
struct asym *sym;
sym = LclAlloc( sizeof( struct dsym ) );
memset( sym, 0, sizeof( struct dsym ) );
or
V501 There are identical sub-expressions 'CodeInfo->token == T_VCVTPS2PD' to the left and to the right of the '||' operator. codegen.c 988
if (CodeInfo->token == T_VMOVHPS || CodeInfo->token == T_VMOVLPS || CodeInfo->token == T_VCVTPS2PD ||
CodeInfo->token == T_VCVTPH2PS || CodeInfo->token == T_VCVTPS2PD ||
CodeInfo->token == T_VPMOVQB || CodeInfo->token == T_VPMOVSQB ||
CodeInfo->token == T_VPMOVUSQB || CodeInfo->token == T_VGATHERQPS ||
CodeInfo->token == T_VPGATHERQD || CodeInfo->token == T_VGATHERDPS){
lbyte &= ~EVEX_P1WMASK;
}
:redface:
V547 Expression 'CodeInfo->indexreg != 0xFF' is always false. codegen.c 2004
if (CodeInfo->vexconst){
tmp &= ~NOT_BIT_345;
tmp &= ~BIT_012;
tmp |= MOD_10;
tmp |= RM_SIB;
if (CodeInfo->indexreg != 0xFF){
c = CodeInfo->indexreg;
c = (c &= 0x07) << 3;
CodeInfo->sib |= c;
c = CodeInfo->basereg;
c &= 0x7;
CodeInfo->sib |= c;
CodeInfo->sib &= 0xf0;
}
These are the results for the 64 bit release, total number of suspicions - 300, high-risk - 50 messages :idea:
Thanks both of you for your support, I am sure that there is always space for improvement and optimisation
which we have been doing 24 hours a day.
I personally don't trust so much to those vizard tools because they are not able to write UASM,
however, it doesn't hurt to look twice at some warnings.
I am planning to look again through the .FOR-.ENDFOR source and optimise and rewrite some parts, I am sure there can be done some improvements and probably add some more functionality, however, that will be for the next release, as well as clearing up some warnings.
I am also grateful to you Nidud for pushing me hard to clear all bags in SWITCH - ENDSWITCH block, that was very complex job to do but rewarding when all works flawlessly.
There is still need to recheck and fix some bugs in listing.c because we are not happy how it deals with inserted code with AddLineQueue() and AddLineQueueX()
I hope John will upload soon the last fix of hll.c
Hi,
Windows x86 and x64 packages have been updated with fixes in HLL for switch/for, a bunch of the warnings have been cleaned up as per qWords excellent list :)
Cheers
John
Works fine for all my major sources :t
Thanks mate :t
deleted
deleted
Good find Nidud,
however, the problem was not there where you thought and that alternative doesn't build large data and is actually much faster than IF - ELSE
I have used this code:
.switch eax
.case 1
.case 2
.case 100000
.case 100001
mov edx, 100000
.case 6
mov edx, 6
.case 7
mov edx, 7
.case 8
mov edx, 8
.case 9
mov edx, 9
.case 12
mov edx, 12
mov edx, 15
.case 16
mov edx, 16
.case 17
mov edx, 17
.case 18
mov edx, 18
.case 19
mov edx, 19
.case 24
mov edx, 24
.case 27
mov edx, 27
.case 21
mov edx, 21
.default
xor edx, edx
.endswitch
and it creates only this data:
* ALIGN 8
* @C0004 dq @C0009, @C000A, @C000D, @C000E, @C000F, @C0010, @C0011, @C0012, @C0013, @C0014, @C0015, @C0018, @C0016, @C0017, @C000B
* dq @C000C
* @C0006 dd 1,2,6,7,8,9,12,16,17,18,19,21,24,27,100000,100001
and it works fine after the small fix in HllStartDir();
I have followed stupid PVS to remove :
if ((t->tokval <= T_EAX))
; //skip it, no need to write MOV EAX,EAX
so I returned it back here:
#if AMD64_SUPPORT
else if (ModuleInfo.Ofssize == USE64) //USE64
{
if ((t->tokval <= T_EAX))
; //skip it, no need to write MOV EAX,EAX
else if (t->tokval <= T_BX) // AL, CL, DL, BL, AH, CH, DH, BH, AX, CX, DX, BX
AddLineQueueX(" movzx eax, %s", tokenarray[i].tokpos);
else if (t->tokval <= T_EDI && t->tokval != T_EAX) //ECX,EDX,EBX,ESP,EBP,ESI,EDI
AddLineQueueX(" mov eax, %s", tokenarray[i].tokpos);
else {
if (t->tokval != T_RAX) //skip it, no need to write MOV RAX,RAX
AddLineQueueX(" mov rax, %s", tokenarray[i].tokpos);
hll->csize = 8;
}
} //end USE64
#endif
now I just put that back and it works as it suppose to
I'll just recheck everything and then reupload again
there were actually 2 bugs :icon_eek:
the second one was popping out RCX 2 times, here:
#if AMD64_SUPPORT
else if (ModuleInfo.Ofssize == USE64) {
AddLineQueueX("pop rdi");
AddLineQueueX("pop rsi");
AddLineQueueX("pop rbx");
AddLineQueueX("pop rcx"); this was the bug
GetLabelStr(hll->labels[LDATA1], buff);
AddLineQueueX("lea rcx,%s", buff);
AddLineQueueX("mov rax, qword ptr[rcx+rax*8]");
AddLineQueueX("pop rcx");
AddLineQueueX("xchg rax,[rsp]");
AddLineQueueX("retn");
}
#endif
so, thank you again to make me aware of it :t
now your source works flowlesly
and this is data that is created for the cases:
* ALIGN 8
* @C0004 dq @C0009, @C000A, @C000B, @C000C, @C000D, @C000E, @C000F, @C0010, @C0011, @C0012, @C0013, @C0014, @C0015, @C0016, @C0017
* dq @C0018, @C0019, @C001A, @C001B, @C001C, @C001D, @C001E, @C001F, @C0020, @C0021, @C0022, @C0023, @C0024, @C0025, @C0026
* dq @C0027, @C0028, @C0029, @C002A, @C002B, @C002C, @C002D, @C002E, @C002F, @C0030, @C0031, @C0032, @C0033, @C0034, @C0035
* dq @C0036, @C0037, @C0038, @C0039, @C003A, @C003B, @C003C, @C003D, @C003E, @C003F, @C0040, @C0041, @C0042, @C0043, @C0044
* dq @C0045, @C0046, @C0047, @C0048, @C0049, @C004A, @C004B, @C004C, @C004D, @C004E, @C004F, @C0050, @C0051, @C0052, @C0053
* dq @C0054, @C0055, @C0056, @C0057, @C0058, @C0059, @C005A, @C005B, @C005C, @C005D, @C005E, @C005F, @C0060, @C0061, @C0062
* dq @C0063, @C0064, @C0065, @C0066, @C0067, @C0068, @C0069, @C006A, @C006B, @C006C, @C006D, @C006E, @C006F, @C0070, @C0071
* dq @C0072, @C0073, @C0074, @C0075, @C0076, @C0077, @C0078, @C0079, @C007A, @C007B, @C007C, @C007D, @C007E, @C007F, @C0080
* dq @C0081, @C0082, @C0083, @C0084, @C0085, @C0086, @C0087, @C0088, @C0089, @C008A, @C008B, @C008C, @C008D, @C008E, @C008F
* dq @C0090, @C0091, @C0092, @C0093, @C0094, @C0095, @C0096, @C0097, @C0098, @C0099, @C009A, @C009B, @C009C, @C009D, @C009E
* dq @C009F, @C00A0, @C00A1, @C00A2, @C00A3, @C00A4, @C00A5, @C00A6, @C00A7, @C00A8, @C00A9, @C00AA, @C00AB, @C00AC, @C00AD
* dq @C00AE, @C00AF, @C00B0, @C00B1, @C00B2, @C00B3, @C00B4, @C00B5, @C00B6, @C00B7, @C00B8, @C00B9, @C00BA, @C00BB, @C00BC
* dq @C00BD, @C00BE, @C00BF, @C00C0, @C00C1, @C00C2, @C00C3, @C00C4, @C00C5, @C00C6, @C00C7, @C00C8, @C00C9, @C00CA, @C00CB
* dq @C00CC, @C00CD, @C00CE, @C00CF, @C00D0
* @C0006 dd 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
* dd 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59
* dd 60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89
* dd 90,91,92,93,94,95,96,97,98,99,100000,100001,100002,100003,100004,100005,100006,100007,100008,100009,100010,100011,100012,100013,100014,100015,100016,100017,100018,100019
* dd 100020,100021,100022,100023,100024,100025,100026,100027,100028,100029,100030,100031,100032,100033,100034,100035,100036,100037,100038,100039,100040,100041,100042,100043,100044,100045,100046,100047,100048,100049
* dd 100050,100051,100052,100053,100054,100055,100056,100057,100058,100059,100060,100061,100062,100063,100064,100065,100066,100067,100068,100069,100070,100071,100072,100073,100074,100075,100076,100077,100078,100079
* dd 100080,100081,100082,100083,100084,100085,100086,100087,100088,100089,100090,100091,100092,100093,100094,100095,100096,100097,100098,100099
include \masm32\include\masm32rt.inc ; plain Masm32 for the fans of pure assembler
.code
start: MsgBox 0, "Hello World", "Hi UAsm team:"
exit
end start
Tmp_File.asm(7) : Error A2244: Invalid symbol type in expression: exit
Weird? This works fine (and you will realise why it doesn't like exit):start: MsgBox 0, "Hello World", "Hello..."
MB_YESNOCANCEL or MB_ICONQUESTION
exit