The MASM Forum

64 bit assembler => ASMC Development => Topic started by: nidud on November 13, 2012, 02:33:57 AM

Title: High Level Language in MASM
Post by: nidud on November 13, 2012, 02:33:57 AM
There is an attempt to include HLL in MASM, but it is currently not fully implemented. The first problem with the current implementation is that it doesn’t work, and the second problem is that it's not High Level Language.

Analysing the problem

All expansions are pre-processed by the assembler, and this is line-based. The code
Code: [Select]
label: mov edx,func(strlen,string)expands to
Code: [Select]
invoke strlen,string
label: mov edx,eax

This creates problems for the HLL section so this must be addressed first.

Syntax (.while, .if and .elseif):

Code: [Select]
while (<expression>) { <statement> }
<statement> is executed repeatedly as long as the value of <expression> remains non-zero. This will currently fail if <expression> is expanded.

Code: [Select]
<expanded expression>
jmp expression
statement:
<statement>
expression:
<expression>
jnz statement

Code: [Select]
if (<expression1>) { <statement1> }
else if (<expression2>) { <statement2> }

This will currently fail if <expression2> is expanded.

Code: [Select]
<expanded expression1>
expression1:
<expression1>
jz expression2
<statement1>
[color=red]<expanded expression2>[/color]
jmp endif
expression2:
<expression2>
jz endif
<statement2>
endif:

Fixing the problem

All labels must be corrected to the actual offset of the code.
From
Code: [Select]
label: .if func(strlen,string)To
Code: [Select]
label:
.if func(strlen,string)

Expansion of <expression> must be delayed and expanded correctly.

Code: [Select]
jmp expression
statement:
<statement>
expression:
<expanded expression>
<expression>
jnz statement

A late expansion of a macro is difficult but possible. It dos however need a full rescan of the source for each pass, so the level of impact to the existing code becomes a huge undertaking. It will also have an impact on the speed of the compilation, so expansion should be done in the first pass to avoid messing up the existing logic.

The problem is not to move the expansion to the right place, but to find a way to split the fixup of labels in the exit code.

Pass one:
Code: [Select]
;.while func(foo) - delay expansion
* jmp expression
* statement:
<statement>
The exit code will be called when .endw if found, an this expands as follows:
Code: [Select]
* expression:
* test eax,eax
* jnz statement

It’s not possible to move the expansion without braking up the code, so whatever approach used this must be done:
Code: [Select]
* expression:
<expanded expression>
* test eax,eax
* jnz statement
So the label must be inserted in pass one, and removed in the next passes. The same approach also applie to the .elseif expansion.

Code: [Select]
<expanded expression1>
<expression1>
jz expression2
<statement1>
jmp endif
expression2:
<expanded expression2>
<expression2>
jz endif
<statement2>
endif:

A test case is made to see if this work as expected. It passes the regression test provided with jwasm v2.08, but no effort has been made to fix the listing, which is destroyed in this process.

In addition to these updates there is also a few non-MASM changes made to this release:
The and/or eax,eax test is replaced by test eax,eax.
The .untilcxz now use dec ecx, jnz label and not loop.

TODO:
To implement a full high level syntax in <expression> also means that assignment of value (as done by habran in the .for loop) and invoke is included:
Code: [Select]
.if ((ecx = strlen(string)) > edi)
Title: Re: High Level Language in MASM
Post by: jj2007 on November 13, 2012, 02:58:16 AM
The .untilcxz now use dec ecx, jnz label and not loop.

Caution with the flags - this might break some existing code.

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
   Init
   mov ecx, 5
   mov eax, -3
   .Repeat
      inc eax
   .Untilcxz   ; old version
   .if Zero?
      Print Str$("ZERO:   \teax=%i", eax)
   .else
      Print Str$("Non-Zero:\teax=%i", eax)
   .endif
   Print Str$(", ecx=%i\n", ecx)

   mov ecx, 5
   mov eax, -3
   .Repeat
      inc eax
      dec ecx   ; new version
   .Until Zero?
   .if Zero?
      Print Str$("ZERO:   \teax=%i", eax)
   .else
      Print Str$("Non-Zero:\teax=%i", eax)
   .endif
   Print Str$(", ecx=%i", ecx)
   Inkey
   Exit
end start
Title: Re: High Level Language in MASM
Post by: qWord on November 13, 2012, 03:05:39 AM
Why are you talking about MASM? You have made an syntax extension to JWASM thus it allows code that isn't compatible with MASM.

EDIT: you may add an option to disable the extension, because existing code that relies on that special expansion behavior won't work anymore.
Title: Re: High Level Language in MASM
Post by: nidud on November 13, 2012, 03:59:47 AM
Why are you talking about MASM?
The HLL syntax was introduced by MASM, not JWASM.
The problems addressed here is MASM syntax.

You have made an syntax extension to JWASM thus it allows code that isn't compatible with MASM.
True, as mention in text.

JJ, I see the first one, but:
Quote from:  jj2007
.Until Zero?
I'll do some testing.

What is the output from the original test now?
Title: Re: High Level Language in MASM
Post by: nidud on November 13, 2012, 04:21:51 AM
Code: [Select]
.386
.model flat

.code

mov ecx, 5
mov eax, -3
.repeat
inc eax
dec ecx ; new version
.until ZERO?

end
expands to:
Code: [Select]
MOV ECX,00000005h
MOV EAX,FFFFFFFDh
CS000A: INC EAX
DEC ECX
JNZ SHORT CS000A
Code: [Select]
.386
.model flat

.code

mov eax, -3
.repeat
inc eax
.until ZERO?

end
expands to:
Code: [Select]
MOV EAX,FFFFFFFDh
CS0005: INC EAX
JNZ SHORT CS0005
Title: Re: High Level Language in MASM
Post by: jj2007 on November 13, 2012, 05:20:15 AM
Here are the results for ML, JWasm standard and JWasm Nidud:

(RichMasm: Press F6 to assemble & link
opt_xxx in uppercase, last one is valid)

OPT_Assembler   ml
Non-Zero:       eax=2, ecx=0
ZERO:           eax=2, ecx=0

OPT_Assembler   JWasm
Non-Zero:       eax=2, ecx=0
ZERO:           eax=2, ecx=0

OPT_Assembler   JWasmNidud
ZERO:           eax=2, ecx=0
ZERO:           eax=2, ecx=0


Admittedly .Untilcxz is an exotic instruction nowadays. The only reason why somebody would use it is to keep the flags intact. And that is exactly what your version will break.
Title: Re: High Level Language in MASM
Post by: nidud on November 13, 2012, 06:10:08 AM
Quote
Admittedly .Untilcxz is an exotic instruction nowadays. The only reason why somebody would use it is to keep the flags intact. And that is exactly what your version will break.
This is a minor issue in my view, and I change this behaviour to make it less exotic.
The next step will be to allow value, like .repeat (ecx = 5, eax = -3).
The syntax should be based on logic, and .untilcxz expands to: Until (E)CX is ZERO.
I always assumed this returned ZERO:
Code: [Select]
    .repeat
call item_SetIndex?
.break .if !ZERO?
sub edi,SIZE S_TOBJ
    .untilcxz
    .if ZERO?

Now the code works as it should do. Make sense?

Searching the masm32 directory for .untilcxz gives no result.
In the MASM directory there is many, but none who assume flags on return.

Special case (forcing a flag return):
Code: [Select]
.REPEAT
...
.UNTILCXZ (al != ' ')    ; Scan for last nonblank character
.IF     !zero?  ; If nonblank char found,

Code: [Select]
JWasm v2.08b, Nov 12 2012
00000000 .repeat
00000000     *   @C0002:
00000000 .untilcxz (al != ' ')
00000000     *   @C0001:
00000000  3C20      *   cmp al , ' '
00000002  E1FC      *   loopz  @C0002
00000004     *   @C0003:

Code: [Select]
JWasm v2.09pre, Sep 22 2012
00000000 .repeat
00000000     *   @C0002:
00000000 .untilcxz (al != ' ')
00000000     *   @C0001:
00000000  3C20      *   cmp al , ' '
00000002  E1FC      *   loopz  @C0002
00000004     *   @C0003:

Code: [Select]
Microsoft (R) Macro Assembler
.repeat
 00000000    *@C0001:
.untilcxz (al != ' ')
 00000000  3C 20    *     cmp    al, ' '
 00000002  E1 FC    *     loope  @C0001

The test I was curious about is this:

Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc   ; download
  Init
  Let esi="This is a stupid test"
  .if Instr_(esi, "stuupid")
     PrintLine "stuupid found"
  .elseif Instr_(esi, "test")
     PrintLine "test found"
  .endif
  Inkey "Found something??", CrLf$
  .if Instr_(esi, "stuupid")
     PrintLine "stuupid found"
  .else
     .if Instr_(esi, "test")
  PrintLine "test found"
     .endif
  .endif
  Inkey "better??"
  Exit
end start
Title: Re: High Level Language in MASM
Post by: jj2007 on November 13, 2012, 06:37:14 AM
This is a minor issue in my view, and I change this behaviour to make it less exotic.
Those few coders who have ever used .Untilcxz will be eternally grateful that you broke their exotic code. All others don't need this "improvement".

Quote
The test I was curious about...

That test works fine now, compliments :t
Title: Re: High Level Language in MASM
Post by: nidud on November 13, 2012, 08:08:08 AM
Quote
Those few coders who have ever used .Untilcxz will be eternally grateful that you broke their exotic code.

These modifications will be Public Domain, free for all use or not.
All modifications will be defined in the global.h header file, which at the moment look like this:
Code: [Select]
#define __FULLSRCPATH /* Use full or relative path (as given) fix */
#define __FIXLABELS /* label: func(foo) fix */
#define __EXPANDHLL /* expand .elsif and .while func(foo) fix */
/*
 * none-masm compatible updates (include fix for -Zg)
 */
#define __UNTILCXZ /* replace <loop> with <dec ecx, jnz> */
#define __TESTREGREG /* replace <and/or reg,reg> with <test reg,reg> */

Quote
All others don't need this "improvement".
The aim here is to explore the possibility to implement HLL in assembly, so the loops included are definitely needed for this to become a reality. If this is bad news for a minority "exotic coders", so be it. I think the reason for this (that nobody use it) is the way it’s currently implemented. So I changed it for this reason.

But the main reason I implemented this is (of course) that I use it myself, and if some find it useful, new features and #defines would have been added, but so far this seems not to be the case.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 13, 2012, 09:26:39 AM
The aim here is to explore the possibility to implement HLL in assembly, so the loops included are definitely needed for this to become a reality. If this is bad news for a minority "exotic coders", so be it.

Nidud,

There is no need to "improve" exotic code like...
   .Repeat
      inc eax
   .Untilcxz eax==edx

... since you can simple use the less exotic
   .Repeat
      inc eax
      dec ecx
      .Break .if Zero?
   .Until eax==edx

... or, better...

   .Repeat
      inc eax
      dec ecx
   .Until Zero? || eax==edx


No problem for new code. But it is fatal to change the behaviour of an assembler or compiler when your audience are sitting on a pile of old code. I have thousands of assembler sources, and I am pretty sure that none contains .Untilcxz, but some older members here may have such code. When you introduce such "improvements", the verdict is "not compatible, bug-prone, don't touch".

Believe me, those who watch this thread do watch it with sympathy. I cannot speak for qWord, but I am just trying to tell you that your efforts into .Untilcxz are not well invested :icon14:
Title: Re: High Level Language in MASM
Post by: hutch-- on November 13, 2012, 10:34:32 AM
Yep,

Any of the instructions that utilise ancient junk like j***cxz and higher level variants were abandoned long ago (486 era) because they are so slow. Coding the loop counter can be done with any register, not just ECX and it can be done much faster than with an antique instruction.
Title: Re: High Level Language in MASM
Post by: nidud on November 13, 2012, 10:57:04 AM
Quote
There is no need to "improve" exotic code like...
   .Repeat
      inc eax
   .Untilcxz eax!=edx
Agreed, and no improvement has been made there, compiles equal to MASM.

Quote
No problem for new code. But it is fatal to change the behaviour of an assembler or compiler when your audience are sitting on a pile of old code.
It’s not fatal, and the change does not break with any documentation given by MS. They don’t say anything about flags.

http://msdn.microsoft.com/en-us/library/ty7cf4bk(v=vs.71).aspx

Quote
I have thousands of assembler sources, and I am pretty sure that none contains .Untilcxz,
And the reason for this is?
My reason will be speed: loop is slow.
The reason for using it will be readability.

Quote
but some older members here may have such code.
If so, I really want to know.

Quote
When you introduce such "improvements", the verdict is "not compatible, bug-prone, don't touch".

There are many things in JWASM that is different from MASM, hence the reason for the switch –Zg, which in this case works.

Title: Re: High Level Language in MASM
Post by: habran on November 13, 2012, 12:43:19 PM
Hey nidud,
don't get discouraged in your innovations :idea: :eusa_clap:
even though I have opinion that you are barking up to wrong tree here
none here wants to make a step forward and have to face a new, 'evil' things :eusa_naughty:
it is mush safer to hold on old, safe-proof stuff, who cares about wrinkles
it spells "conservatism" 
but, hey, that is why we cling to assembler :biggrin:
 
best regards
Title: Re: High Level Language in MASM
Post by: japheth on November 13, 2012, 10:15:50 PM

nidud, I like your enthusiasm.

As for me, however, I'm one of those guys who don't believe in progress.  Calling me "conservative" would be an euphemism, I'm deep 19th century.

Therefore I'm very reluctant to accept "extensions" for jwasm. Perhaps you should consider to start a fork, with it's own name ( nwasm? ).

Title: Re: High Level Language in MASM
Post by: habran on November 14, 2012, 12:13:48 AM
Hey japheth,
Code: [Select]
As for me, however, I'm one of those guys who don't believe in progress.
how dare you to say that!!!  :icon_eek:
You created JWasm, the best thing in long time of assembly programming!!! :bgrin:

would you call that REGRESS??? ::)

would you call that regress to WASM???

However, I appreciate your decisions about the things you will accept or refuse to include in your JWasm
The source is available and everyone who wants something else can start a new fork

best regards 

Title: Re: High Level Language in MASM
Post by: nidud on November 14, 2012, 04:04:18 AM
Thanks for the encouragement habran, but I have to admit that I am a bit old-fashioned myself. I think it is a bad idea that more/newer is always better, and then (for this reason) assume the future will be good.

As for me, however, I'm one of those guys who don't believe in progress.
I have spent a lot of my time travelling, viewing the result of this alleged progress, so I must (sadly as it is) agree with you there.

The reason for this idea comes from experience with assembly in general, and could be summed up like this: I have used assembler language for a long time, but normally only as a supplement to applications written in C/C++. At one point I converted a whole application to assembly, and the difference it made was quite astonishing. The size was cut in half and the speed of the program dramatically increased. Needless to say I was happy with the result, but at this time I had to leave. After a few weeks on returning I had some ideas on improving the program, and also some new features that I wanted to add. I then discover the problem with assembly: it only took a few weeks to forget how the thing works. If someone will ask me today if this is a good idea, I will use this experiment to explain the benefits, but then also add the following: you better get it right the first time because you wont be able to apply changes to it later.

The main problem in this context is readability, and I think that is the reason why so few applications are written in assembly. So the main idea here is to make it possible to write readable code, and thereby maintainable code. These problems only occur on large projects, and the suggested changes will therefore only applies to people who have this in mind.

This is also why the interpreters was made: to converts macro language (in this case C) to assembly code. The interpreter used by MS is called CL, and (JJ) this is how it works:
Code: [Select]
/* repeat.c */
int repeat(void)
{
    int eax = -3;
    int ecx = 5;

    do { eax++; } while (--ecx);
    return eax;
}
cl -c –Farepeat.asm repeat.c
Code: [Select]
TITLE repeat.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _repeat
_TEXT SEGMENT
_eax$ = -4
_ecx$ = -8
_repeat PROC NEAR
; File repeat.c
; Line 3
push ebp
mov ebp, esp
sub esp, 8
; Line 4
mov DWORD PTR _eax$[ebp], -3 ; fffffffdH
; Line 5
mov DWORD PTR _ecx$[ebp], 5
$L34:
; Line 7
mov eax, DWORD PTR _eax$[ebp]
add eax, 1
mov DWORD PTR _eax$[ebp], eax
mov ecx, DWORD PTR _ecx$[ebp]
sub ecx, 1
mov DWORD PTR _ecx$[ebp], ecx
cmp DWORD PTR _ecx$[ebp], 0
jne SHORT $L34
; Line 8
mov eax, DWORD PTR _eax$[ebp]
; Line 9
mov esp, ebp
pop ebp
ret 0
_repeat ENDP
_TEXT ENDS
END

This illustrates how good (as in readable) the C language is, and how good the assembly language become if you code the loop yourself.

The HLL section made by MS emulates the C language, so readability means that all extensions made must be common. Comment should describe what the function does, not how it actually do it. The body of the function must then be written in a way that it explains itself. This means that you can’t introduce a lot of new things in order to achieve this, so you need to use the old (conservative if you will) methods included. Some other conservative people allegedly steal these functions. If you focus more on the actual intention of the HLL section, and what hutch is saying, the purpose of it is usage, not antiquity.

The question to answer will then be why you don’t use the HLL directives, and what needs to change in order for you to consider using it. My argument will be to enable me to read my own dribble, if I want to make changes to it later. The optimal result will be to enable others to read (and understand it) as well, so they could apply changes to it.

Therefore I'm very reluctant to accept "extensions" for jwasm. Perhaps you should consider to start a fork, with it's own name ( nwasm? ).
This is just an idea at the moment, and the enthusiasm currently only serves selfish interest. This could not happen without the source code provided by you. If there is an interest in implementing these changes, there will be many extensions made, so in this case I will consider making a fork. CASM will not make changes that makes problems for existing code, so it will still be JWASM with some added features.
Title: Re: High Level Language in MASM
Post by: hutch-- on November 14, 2012, 09:31:20 AM
> The main problem in this context is readability

The assumption that C language format will improve readability of MASM code would be a hard idea to sell, MASM and by derivation JWASM already has a macro language that is far more powerful than the C preprocessor and it already has the notation for higher level loop structures, conditional branching and variation on single line function calls. It is part of the appeal of using a macro assembler that you can perform a task in a number of different ways from purely manual mnemonics to reasonably high level notation.
Title: Re: High Level Language in MASM
Post by: nidud on November 14, 2012, 10:39:30 AM
The assumption that C language format will improve readability of MASM code would be a hard idea to sell
You don’t have to; it’s already a fact (that C language improves readability that is).

MASM and by derivation JWASM already has a macro language that is far more powerful than the C preprocessor and it already has the notation for higher level loop structures, conditional branching and variation on single line function calls. It is part of the appeal of using a macro assembler that you can perform a task in a number of different ways from purely manual mnemonics to reasonably high level notation.
True, it will outperform C on all levels, except from one: portability.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 14, 2012, 10:45:34 AM
You don’t have to; it’s already a fact (that C language improves readability that is).

Over one Billion people are firmly convinced that Chinese is the World's most readable language 8)
Title: Re: High Level Language in MASM
Post by: hutch-- on November 14, 2012, 11:01:14 AM
 :biggrin:

> You don’t have to; it’s already a fact (that C language improves readability that is).

The problem is the world is full of people who write other languages that don't agree. I grew up with K & R C notation and formatting so I read it OK but it is an archaic notation that irks many people including those who write Pascal, Basic, Fortran, VB dialects etc etc. Nested braces {}, trailing line terminators ";", the need for "break" etc, its ancient notation that was long ago left behind. Thank God for the clarity and precision of MASM.  :P
Title: Re: High Level Language in MASM
Post by: nidud on November 14, 2012, 11:08:21 AM
Over one Billion people are firmly convinced that Chinese is the World's most readable language 8)
Think you will find that more than five billion will disagree on that one :lol:
Title: Re: High Level Language in MASM
Post by: nidud on November 14, 2012, 11:17:32 AM
The problem is the world is full of people who write other languages that don't agree. I grew up with K & R C notation and formatting so I read it OK but it is an archaic notation that irks many people including those who write Pascal, Basic, Fortran, VB dialects etc etc. Nested braces {}, trailing line terminators ";", the need for "break" etc, its ancient notation that was long ago left behind. Thank God for the clarity and precision of MASM.  :P
No need to import all that crap :biggrin:
This will do for starters:
Code: [Select]
.if ((ecx = strlen(string)) > edi)
Title: Re: High Level Language in MASM
Post by: dedndave on November 14, 2012, 11:57:48 AM
i don't know why you MUST write in hll ???
afterall, if you want your code to look like C, write it in C - lol
if i want to use LOOPNZ, i can do it by using.....  LOOPNZ   :biggrin:

as for Hutch's comment about those instructions being slower...
we may need to re-test those instructions with newer cores
they may be slower on a P4, but not his new-fangled i7
Title: Re: High Level Language in MASM
Post by: japheth on November 14, 2012, 02:33:31 PM
how dare you to say that!!!  :icon_eek:

The term "to believe in" isn't always used in the context of "to believe in the existence of"; this is a technical usage. A more philosophical usage of this term is "to believe in the concept or idea of" - and this latter view was meant here.
Title: Re: High Level Language in MASM
Post by: habran on November 14, 2012, 03:44:20 PM
japheth,

I found this in TheFreeDictionary
progress:
1. Movement, as toward a goal; advance.
2. Development or growth: students who show progress.
3. Steady improvement, as of a society or civilization: a believer in human progress. See Synonyms at development.

what I want to say is: The Perfection is most probably inaccessible to us humans
however, that doesn't mean that we should give up on trying to become one  ;)

regards :biggrin:
Title: Re: High Level Language in MASM
Post by: habran on November 14, 2012, 03:49:44 PM
nidud

consider this:

"rbx=qwinvoke(strlen,ADDR src)"  is not neccecery in this function
 I'v just put it there to show how it works

Code: [Select]
qwinvoke MACRO Fun:REQ, A:VARARG
  IFB <A>
    invoke Fun
  ELSE
    invoke Fun, A
  ENDIF
  EXITM <rax>
ENDM


xmemcpy PROC FRAME USES rbx dest:QWORD,src :QWORD, count:UINT_PTR

  .if (rcx != rdx) 
  .for (rbx=qwinvoke(strlen,ADDR src)¦r8¦al=[rdx],[rcx]=al,rcx++,rdx++,r8--)
        .break .if (r8 > rbx)
  .endfor
  .endif
  mov rax,dest
  ret
xmemcpy ENDP

xmemcpy:
00000000004935B0  mov         qword ptr [rsp+8],rcx
00000000004935B5  mov         qword ptr [rsp+10h],rdx
00000000004935BA  mov         qword ptr [rsp+18h],r8
00000000004935BF  push        rbp 
00000000004935C0  mov         rbp,rsp
00000000004935C3  sub         rsp,20h
00000000004935C7  cmp         rcx,rdx
00000000004935CA  je          xmemcpy+46h (4935F6h)
00000000004935CC  lea         rcx,[rbp+18h]
00000000004935D0  call        strlen (4246E0h)
00000000004935D5  mov         rbx,rax
00000000004935D8  jmp         xmemcpy+3Ah (4935EAh)
00000000004935DA  mov         al,byte ptr [rdx]
00000000004935DC  mov         byte ptr [rcx],al
00000000004935DE  add         rcx,1
00000000004935E2  add         rdx,1
00000000004935E6  sub         r8,1
00000000004935EA  and         r8,r8
00000000004935ED  je          xmemcpy+46h (4935F6h)
00000000004935EF  cmp         r8,rbx
00000000004935F2  ja          xmemcpy+46h (4935F6h)
00000000004935F4  jmp         xmemcpy+2Ah (4935DAh)
00000000004935F6  mov         rax,qword ptr [rbp+10h]
00000000004935FA  add         rsp,20h
00000000004935FE  pop         rbp 
00000000004935FF  ret             


regards
Title: Re: High Level Language in MASM
Post by: nidud on November 15, 2012, 01:35:38 AM
i don't know why you MUST write in hll ???
I don’t; nobody does.
afterall, if you want your code to look like C, write it in C - lol
I do, because I MUST: JWasm is written in C.
...
all the programs in the \masm32\bin directory are written in C.
all the library source code in the \masm32\lib directory is written in C.

if i want to use LOOPNZ, i can do it by using.....  LOOPNZ   :biggrin:

as for Hutch's comment about those instructions being slower...
we may need to re-test those instructions with newer cores
they may be slower on a P4, but not his new-fangled i7
Ok.

habran

consider this:

Code: [Select]
.data
s1 db 'abcdefgh',0
s2 db 'abcd',0
.code
start:
.for (ebx = offset s1, edx = func(strlen,ebx) ¦ edx >= sizeof(s2) ¦ edx--)
    mov byte ptr [ebx+edx-1],0
.endfor
invoke printf,cstr(<"s1: %s",10,"s2: %s",10>),ebx,addr s2
output:
s1: abcdefgh
s2: abcd
...
mov ebx,offset s1
.for (edx = func(strlen,ebx) ¦ edx >= sizeof(s2) ¦ edx--)
output:
s1: abcd
s2: abcd

This is what a delayed expansion of macros does, and this is what is done with .elseif <expression> and .while <expression>.

In this case the code will expand to:
* invoke strlen,ebx
.for (ebx = offset s1, edx = eax…

For this to work, the .for <expression> must also delay the expansion of <expression>, and you have to do the actual expansion inside your code.

Code: [Select]
.for (ebx = offset s1, edx = func(strlen,ebx) ¦ edx >= func(strlen,addr s2) ¦ edx--)or, since you parse the .for[...] locally, the macro could be removed
Code: [Select]
.for (ebx = offset s1, edx = strlen(ebx) ¦ edx >= strlen(addr s2) ¦ edx--)
Title: Re: High Level Language in MASM
Post by: hutch-- on November 15, 2012, 02:00:03 AM
 :biggrin:

Quote
all the programs in the \masm32\bin directory are written in C.
all the library source code in the \masm32\lib directory is written in C.

Tell us something new, Microsoft binaries are written in C or C++ but the stubs that are too small for C in the bin directory are written in MASM, LIB.EXE, DUMPBIN.EXE and EDITBIN.EXE. The complete LIB directory import libraries were created at install with ML.EXE.

We have all heard C zealots before waxing lyrical about its supposed superiority but long ago assembler produced binaries that are beyond the best C compilers, this is mainly why assembler programmers still exist. No high level language owns assembler, C interfaces with it fine, many dialects of basic write sound assembler and from memory even Pascal can produce assembler output but assembler is a language in its own right that has little need for the constraints of C or C++. It does EXE, DLL and OBJ file just fine without a C compiler.
Title: Re: High Level Language in MASM
Post by: CommonTater on November 15, 2012, 02:15:21 AM
We have all heard C zealots before waxing lyrical about its supposed superiority but long ago assembler produced binaries that are beyond the best C compilers, this is mainly why assembler programmers still exist. No high level language owns assembler, C interfaces with it fine, many dialects of basic write sound assembler and from memory even Pascal can produce assembler output but assembler is a language in its own right that has little need for the constraints of C or C++. It does EXE, DLL and OBJ file just fine without a C compiler.

At the risk of stepping in it...

I prefer C because I know C.  When I was working mostly in Pascal, I preferred Pascal because I knew Pascal.  I think it's just human nature to want to think we've hooked ourselves up with "all the right stuff" whether we have or not. 

I don't see ASM, C, C++, C# and a hundred other languages I will never use as competing with one another.  I see them as complimentary... each having a place according to their own strengths.
Title: Re: High Level Language in MASM
Post by: dedndave on November 15, 2012, 02:22:51 AM
yes - they do have their place
i tried other languages in days of old
but always came back to assembler because of some limitation from the compiler   :P

if i were writing apps on a professional basis, i would probably use C with some asm-created OBJ's
Title: Re: High Level Language in MASM
Post by: CommonTater on November 15, 2012, 02:29:53 AM
yes - they do have their place
i tried other languages in days of old
but always came back to assembler because of some limitation from the compiler   :P

if i were writing apps on a professional basis, i would probably use C with some asm-created OBJ's

Yep... mostly I write in C... and occasionally dip into a couple of lines of ASM when needed.

That's not to say I have anything against ASM.  It is to say that, so far, I've been lucky enough to not get into projects that require ASM's fine grained code (and the learning curve that implies)... Now that I'm here, I'm hoping to pick some of it up by osmosis and do a little ASM coding for the experience.  I try very hard to never close my mind to new possibilities.

Title: Re: High Level Language in MASM
Post by: nidud on November 15, 2012, 04:37:27 AM
No high level language owns assembler
:biggrin:
MASM is own by Microsoft, and it’s written in a high level language called C

JWasm is own by us, but this is also written in C, and there is a reason for this. If we then could agree on the fact that there are some benefits in writing applications in C compare to assembly, then we could move on to the issue at hand.

We have the source code to a MASM compatible assembler, and the capacity to apply changes to it. There is no intention of importing any constraints of C or any other high level language into this equation. What is suggested is to enhance the already built in hll directives by MASM. The aim is then to steal some of these benefits from C, and implement them to increase readability without breaking any already existing code.

The result could then be a smoother transition from C and an increase of the overall usage of assembly.
Title: Re: High Level Language in MASM
Post by: hutch-- on November 15, 2012, 09:19:31 AM
The problem is that the facts also support writing apps in Pascal, Fortran and a number of dialects of basic. Nor does the language a tool is written in effect what its output is. Early C compilers were written in assembler, various compilers have been written in Pascal and i have seen compilers written in basic. I have no beef with C apart from its notation being a bit long in the tooth, many modern C compiler produce very good code as long as you are not doing anything that is truly critical and this is why Microsoft still update MASM on a needs basis.

As far as introducing C control flow directives into MASM, Microsoft did it in 1990 with MASM version 6.00 and it has had the capacity ever since. With current existing pre-processor macros, MASM does "switch" blocks with no problems and variations that a C compiler does not do, string versions of switch in case or casei variations. The more recent version of MASM32 also added the data type specifiers to function calls so the you have either pointers or dereference notation.

Then you have a project like JJ's MasmBasic which leverages the MASM pre-processor to produce a basic dialect while retaining all of MASM's capacity.

I more than happily encourage folks to keep extending MASM but you will have to forgive me in that I have heard too many zealots for other languages and it all sound much the same after a while.
Title: Re: High Level Language in MASM
Post by: nidud on November 15, 2012, 11:51:18 AM
I have never expressed any zealous attitude towards other languages. I only made a point of the fact that the hll section in MASM is based on C. I wrote an application in assembly and it become difficult maintain. I then started to use the hll directives (which I normally don’s use) to compensate for this, and discovered some shortcomings. I debated this with Japheth and he meant that this was a design flaw in MASM and not a bug JWasm. He is of course right in this regard. However, I looked at the source code and provided a fix for the label: macro() issue. This was fixed in v2.06, and now the .elseif macro(), and .while macro() issue is fixed using v2.08. JJ provided a test case for the bug, and this now seems to work, so I’m happy with the result. That’s about the size of it, no more, no less.

Since the feedback here seems to revolve around other unrelated issues, and the purpose of the fix only serves selfish interest, I will not pursue this any further.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 15, 2012, 05:24:32 PM
nidud,

You did a very good job on that late expansion problem :t

I only made a point of the fact that the hll section in MASM is based on C.

My previous favourite BASIC dialect, GfaBasic, born around 1988, features
REPEAT .. UNTIL
WHILE ... WEND
DO WHILE ... LOOP
DO ... LOOP UNTIL
IF ELSE ELSEIF ENDIF
SWITCH CASE DEFAULT ENDSW

But it did not require the excessive use of {strange brackets everywhere}, and both its interpreter and its blazing fast compiler knew that the end of a line is marked by CrLf, not by ;

So obviously MASM is based on GfaBasic.
Title: Re: High Level Language in MASM
Post by: japheth on November 15, 2012, 06:54:57 PM
Since the feedback here seems to revolve around other unrelated issues, and the purpose of the fix only serves selfish interest, I will not pursue this any further.

You probably did not express yourself clearly in the first post - and in the thread caption. The topic becomes clear if you read everything carefully ... but quite a few people in this board are in "write-only" mode and a true discussion with them is virtually impossible.

Also, be a bit careful with statements about C. I well remember Agner Fog a few years ago who started a discussion about JWasm and assembly language "standards". He happened to make a innocent remark, kinda "C is probably sometimes better than assembly", and was then scared away by one of the super-intelligent super-moderators. This event made me realize that this forum is the WRONG place for ... "certain things".

Title: Re: High Level Language in MASM
Post by: MichaelW on November 15, 2012, 06:58:46 PM
So obviously MASM is based on GfaBasic.

I think Microsoft started on MASM around 1980, so they must have had an early pre-alpha version that they pirated :biggrin:
Title: Re: High Level Language in MASM
Post by: jj2007 on November 15, 2012, 08:45:25 PM
So obviously MASM is based on GfaBasic.

I think Microsoft started on MASM around 1980, so they must have had an early pre-alpha version that they pirated :biggrin:

I was joking, of course. Around 1980 I coded in Fortran IV, and that looked similar, too. GfaBasic is a well-balanced mix of Fortran, Pascal and Basic syntax elements, but anyway, practically all languages have these constructs. Strange that C coders believe they invented it ::)
Title: Re: High Level Language in MASM
Post by: hutch-- on November 15, 2012, 10:19:18 PM
Funny enough I used GFA basic back in the middle 90s as it out performed Microsoft C version 7.0. C version 6.0 was a much better version but had limited Windows support at the time. I wrote GFA basic until WinNT version 4 when I went to 32 bit with both MASM and PowerBASIC. I remember the guy I used to buy some basic stuff from in the DOS days giving me a copy of PowerBASIC to test out and it took me about 2 days to digest enough of it to start 32 bit Windows programming. I have been buying it ever since.

It is unfiortunate that GFA never made the transition to 32 bit properly as they wrote some good stuff in the late 16 bit Windows period. Their code example tended to be scruffy looking piles of crap but much of it works well. I already had the discipline of writing original SDK C for Windows so it was not a hard transition to full API code in both MASM and PowerBASIC. I can still write pure Microsoft C in 32 bit but I was long ago seduced by the sheer elegance of MASM. I still keep a number of C compilers going from VC98 up to current but most of the C code I have builds best in VC2003, the later versions became piggy and slower.

I actually liked the interface on early VB Versions but the fun stopped when you had to write some decent code behind the easy interface. It was an absolute toothless terror behind the scene and I gave up on it by about 1994.
Title: Re: High Level Language in MASM
Post by: hutch-- on November 22, 2012, 08:07:51 PM
 :biggrin:

Quote
Also, be a bit careful with statements about C. I well remember Agner Fog a few years ago who started a discussion about JWasm and assembly language "standards". He happened to make a innocent remark, kinda "C is probably sometimes better than assembly", and was then scared away by one of the super-intelligent super-moderators. This event made me realize that this forum is the WRONG place for ... "certain things".

Something that some need to be aware of is how rare an assembler venue is yet after about 15 years of practice we still occasionally see and hear a selection of programmers waxing lyrical about the superiority of of the C language over others including assembler programming. There is a vast number of our members who can read and write competent C code with many years of experience but they write assembler code where they need it without needing to try and shift the status of one language over another.

Knowing the difference is where the action is, if you need high quality compiler code that is portable, C is a very good language and a massive amount of operating system code has been written in C but equally if you need high precision targeted code without the clunkyness of a high level language, assembler has no peers. There is of course considerable overlap between the two in Windows coding because the Windows API is available to both.

Its the old assumptions that were long ago discredited that can still grate when you hear another zealot waxing lyrical about the superiority of C as a language. I don't personally care if someone wants to create a macro system where you can write COBOL in MASM, as long as we are free from the dogma.  :P
Title: Re: High Level Language in MASM
Post by: CommonTater on November 22, 2012, 09:59:26 PM
There is a vast number of our members who can read and write competent C code with many years of experience but they write assembler code where they need it without needing to try and shift the status of one language over another.

Last week I was helping a friend fix the drywall in his kid's bedroom (long story), and mostly I used a putty knife and sandpaper.

Before that I was busy working on a home theatre system and mostly I used a soldering iron and some transistors.

I'm often given to helping out in the  your link does not work IDIOT  and that's usually soaps and towels.

Programming is no different... you simply use the right tools for the job. 

There is no one universal programming language that is magically better than any other... each has it's strengths and weaknesses.  Delphi had a good run because you could knock out (bloated, slow and kludgey) code faster than you could say "spit".  C++ is pretty cool when you have data that can be easily compartmentalized in objects.  C is the man when it comes to general procedural programming (like Easy Build).  ASM is the obvious choice when you need to get down and dirty with the chip itself. 

OR... maybe your list is a little different. 

It doesn't matter, it's still all about using the right tool for the job.
Title: Re: High Level Language in MASM
Post by: dedndave on November 22, 2012, 10:19:38 PM
i don't really see one as "better" than another - no reason for it, really
i write in assembler because it is my preference
i have more experience with assembler and, thus, a shorter learning curve to get going
with me - the fewer changes i have to make, the happier i am - lol

if i had to write code on a day-to-day basis, i would probably want to use C with some routines in assembler
it's a matter of productivity and maintainability
this hypothetical company i work for can hire C programmers a lot easier than it can hire assembly programmers
Title: Re: High Level Language in MASM
Post by: nidud on November 23, 2012, 08:44:50 AM
The experience:
I started using the hll directives and found out they where crap.
I analysed the situation and made some arguments.
I probed into the usage of it and found this to be very low.
The overall feedback was that this is a minor issue.

The assumptions:
I assume that the reason for not using it is bad experience.
I assume that the lack of interest is that nobody uses it.
I assume that removing the reason for not using it will increase usage.

Conclusion:
I fail to emphasise enough that this was an experiment, an idea to apply changes for increased usage in the future. By doing so I was mixing logic with assumptions. The problem with this experiment is that nobody knows the outcome of it, and the only way to find out is to implement the changes and wait for the results.

The feedback:
changes might break some existing code -- if (not may) so: problem
The hll section is bad, slow, ancient, junk -- agree: the window of opportunity.
The norm is to write the program in HLL and include some asm -- fact
The libraries and programs included in MASM32 is written in C -- fact
The C declarations are needed in assembly code using these libraries -- fact

Some results (MASM32):
Code: [Select]
        .WHILE TRUE
                invoke GetMessage, ADDR msg, 0,0,0
.BREAK .IF (!eax)
invoke TranslateAccelerator, hwnd, hAccel, ADDR msg
                .IF !eax
    invoke TranslateMessage, ADDR msg
                    invoke DispatchMessage, ADDR msg
.ENDIF
        .ENDW

    .while GetMessage(ADDR msg, 0,0,0)
.if !TranslateAccelerator(hwnd, hAccel, ADDR msg)
    invoke TranslateMessage, ADDR msg
    invoke DispatchMessage, ADDR msg
.endif
    .endw
if i had to write code on a day-to-day basis, i would probably want to use C with some routines in assembler
it's a matter of productivity and maintainability
this hypothetical company i work for can hire C programmers a lot easier than it can hire assembly programmers
True: C to asm:
Code: [Select]
#include <io.h>
#include <dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <string. h>
..
int IOGetFileType(char *fname)
{
    char *p;
    p = strrchr(fname, '.');
    if (p == NULL)
        return NO_SOURCE;
    if (!stricmp(p, ".c"))
        return SOURCE_C;
    if (!stricmp(rsi, ".asm"))
        return SOURCE_ASM;
    if (!stricmp(rsi, ".idd"))
        return SOURCE_IDD;
    if (!stricmp(rsi, ".obj"))
        return SOURCE_OBJ;
    return –1;
}

include io.inc
include dir.inc
include stdio.inc
include stdlib.inc
include string.inc
..
IOGetFileType proc uses rsi fname:ptr byte
    invoke strrchr,fname, '.'
    mov rsi,eax
    .if !rax
        mov rax,NO_SOURCE
    .elseif !stricmp(rsi, ".c")
        mov rax,SOURCE_C
    .elseif !stricmp(rsi, ".asm")
        mov rax,SOURCE_ASM
    .elseif !stricmp(rsi, ".idd")
        mov rax,SOURCE_IDD
    .elseif !stricmp(rsi, ".obj")
        mov rax,SOURCE_OBJ
    .else
        mov rax,-1
    .endif
    ret
IOGetFileType endp
Title: Re: High Level Language in MASM
Post by: MichaelW on November 23, 2012, 09:15:46 AM
The problem as I see it is that no matter how much you massage the high-level syntax, or how creative your macros are, you still do not have anything close to a HLL syntax. To get the full benefit of coding in a HLL you need a HLL compiler. I think the time would be much better spent developing a compiler that would allow you to more or less freely mix HLL code with MASM/JWASM code and macros.
Title: Re: High Level Language in MASM
Post by: qWord on November 23, 2012, 09:33:09 AM
Sphinx C-- (http://c--sphinx.narod.ru/indexe.htm)
Title: Re: High Level Language in MASM
Post by: hutch-- on November 23, 2012, 10:09:12 AM
I am inclined to think that compilers and assemblers are different animals, you can get some overlap between them but the base architecture between them is fundamentally different. You can in fact get the best of both worlds by using both a C compiler and an assembler and isolate the code in object modules which you then link into a finished binary. This allows you to fully leverage what both do best, an optimising compiler is free to tweak anything without having to accommodate manual code and an assembler module can handle anything you write in it without the restrictions and irritations of a compiler.

I agree with Michael here in that while MASM is able to emulate many higher level techniques, it will never be a high level tool, likewise a C compiler can do many things that an assembler can do with its inline assembler but its specifications of preprocessing are toothless terrors alongside MASM. The idea is that while they overlap, neither will ever be the other. The assumption that you can only use one tool in binary production is flawed in that mixed language programming has been with us for a very long time and it allows you to get the advantages of multiple tools.
Title: Re: High Level Language in MASM
Post by: nidud on November 23, 2012, 10:39:24 AM
The problem as I see it is that no matter how much you massage the high-level syntax, or how creative your macros are, you still do not have anything close to a HLL syntax. To get the full benefit of coding in a HLL you need a HLL compiler. I think the time would be much better spent developing a compiler that would allow you to more or less freely mix HLL code with MASM/JWASM code and macros.
My idea was to remove the usage of macros, not to create new ones.

The reason why I stopped here was that I use my own C libraries (written in assembly), and I assumed the MASM32 package was the same, but it seems to be based on macros interfacing with C.

So, the argument that the use of macros should be limited, or not used at all will be hard to do here. :biggrin:

Sphinx C-- (http://c--sphinx.narod.ru/indexe.htm)
The plan was to improve (and synchronise) the already existing architecture at hand. Reducing the learning curve (and cost) by using the same abbreviations (strlen, memcpy, ..) and help system (msdn) as already established in C to increase readability and usage of assembly.

http://en.wikipedia.org/wiki/The_Mythical_Man-Month

I am inclined to think that compilers and assemblers are different animals, you can get some overlap between them but the base architecture between them is fundamentally different. You can in fact get the best of both worlds by using both a C compiler and an assembler and isolate the code in object modules which you then link into a finished binary. This allows you to fully leverage what both do best, an optimising compiler is free to tweak anything without having to accommodate manual code and an assembler module can handle anything you write in it without the restrictions and irritations of a compiler.

I agree with Michael here in that while MASM is able to emulate many higher level techniques, it will never be a high level tool, likewise a C compiler can do many things that an assembler can do with its inline assembler but its specifications of preprocessing are toothless terrors alongside MASM. The idea is that while they overlap, neither will ever be the other. The assumption that you can only use one tool in binary production is flawed in that mixed language programming has been with us for a very long time and it allows you to get the advantages of multiple tools.
Well put, but the possibility of narrowing the gap between them could be useful in some cases. And if it could be done without compromising existing code, I think one should explore this possibility.
Title: Re: High Level Language in MASM
Post by: dedndave on November 23, 2012, 11:41:41 AM
macros certainly have their place
they are great for saving keystrokes, especially during the debug phase
on the flip side, if you are trying to learn windows programming and masm, they can hide things you want to learn
if you know the OS and you know the assembler - they are great   :biggrin:
Title: Re: High Level Language in MASM
Post by: jj2007 on November 23, 2012, 02:19:21 PM
I use my own C libraries (written in assembly), and I assumed the MASM32 package was the same, but it seems to be based on macros interfacing with C.

Only a small part of the Masm32 package links to the C run-time library. MasmBasic has actually only one reference to crt_qsort, all the rest is pure assembler.

[rant]My impression is that you see lots of non-existent problems. Many people use HLL constructs in assembler, and do not start weeping when occasionally they forget that .elseif MyMacro(eax) won't work. That's about half as bad as C's habit to fall thru switches (shudder :dazzled:).

Every time I touch C code or, worse, C compilers, I get the creeps.

First, it never works from the start, because everybody uses a different compiler, different libraries, different switches. You spend a lot of time hanging on the web just to convince a hello world snippet to compile properly.

Second, it's soo sloooooow. Building a C snippet is a factor ten slower than the same in MasmBasic using JWasm. Visual C Express? What does "Express" mean? That you can go for an Espresso while the damn bloatware is loading??

Third, the horrible syntax with all those {brackets that cause Repetitive Stress Injury} and the strange obligation to tell the compiler that the end of a line is not 0D0Ah but rather a semicolon. And instead of printing, C prefers to cout. Hilarious.

Of course, everybody grows up with a different language. Over one Billion people believe that Chinese is an easy language. My languages are FORTRAN, Basic and assembler, and I firmly believe that assembler is a fantastic language, provided you know how to use macros wisely. A mix of MasmBasic, "pure" assembler and WinAPI calls is hard to beat in terms of productivity...
[/rant]
Title: Re: High Level Language in MASM
Post by: CommonTater on November 23, 2012, 04:15:29 PM
Every time I touch C code or, worse, C compilers, I get the creeps.

ROFL... here we go...

(counter-rant)
Having (at this point) written something well in excess of a million lines of C code, I have to say my experience has been somewhat different...

C falls through switches by design... so you can do this:
Code: [Select]
switch (x)
  {
     case 1:
     case 7:
     case 2:
       puts( "1 7 or 2");
       break;
     case 4 :
       puts ("Definately 4);
       break;
     default:
        puts(" something else");
  }

The C language is relatively standardized by ISO C-99 and ISO C-11 ... properly written programs from any compiler using either of those standards will compile on any other compiler using the same standard.

Yes, C compilers are a bit slowish... but you only compile something once... from there the actual speed differences between well written C code and well written ASM code are trivial in most cases.  Especially true with an optimizing C compiler. 

That horrible syntax with all those brackets is not without purpose... The brackets mark "scopes" which serve to separate blocks of code... The open brace actually creates a stack frame ... the code runs on that... then the closing brace destroys it.  C rules of scope are very handy at times, especially when you have a long subroutine with several sets of independent variables...

In the case of VC++ "Express" means "Free".

The C language has it's place in the world, just like any other.   The real problem here, IMO, is that people just love trashing what they don't fully understand.
(/counter-rant)
 
 
Title: Re: High Level Language in MASM
Post by: nidud on November 23, 2012, 04:23:20 PM
My impression is that you see lots of non-existent problems. Many people use HLL constructs in assembler, and do not start weeping when occasionally they forget that .elseif MyMacro(eax) won't work.
The janitor is standing on the roof with a shingle in his hand; desperately trying to fix the leak in the roof while the house is floating down the river. The architect is not to blame for this; his job is to design things. Neither is this the fault of the janitor; his job is to fix things. The problem was the location of the house; it was built on sand.

I have never seen any problems with regards to these issues, only opportunities; a chance; an opening; a break; a prospect. The problems you mention are a positive; not a negative. Without these problems the prospect of an opening to these possibilities will not exist.

So, relax JJ, the rain is poring down but there are no leakage  :biggrin:
Title: Re: High Level Language in MASM
Post by: MichaelW on November 23, 2012, 05:11:45 PM
C falls through switches by design... so you can do this:
Code: [Select]
switch (x)
  {
     case 1:
     case 7:
     case 2:
       puts( "1 7 or 2");
       break;
     case 4 :
       puts ("Definately 4);
       break;
     default:
        puts(" something else");
  }

By design, yes, but IMO the original authors did not spend enough time on the design. They could have provided more functionality with less code. For example Greg Falen’s switch/case macros:
Code: [Select]
;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
    .code
;==============================================================================
start:
;==============================================================================
    FOR eax,<0,1,2,3,4,5,6,7,8,9>
        SWITCH eax
            CASE 1,2,3
                printf("1,2,3\n")
            CASE 4
                printf("4\n")
            CASE 5..9
                printf("5..9\n")
            DEFAULT
                printf("default\n")
        ENDSW
    ENDM
    inkey
    exit
;==============================================================================
end start

Or a mainstream BASIC:
Code: [Select]
for i as integer = 0 to 10
    select case i
        case 1,2,3
            print "1,2,3"
        case 4
            print "4"
        case 5 to 9
            print "5 to 9"
        case is > 9
            exit select
        case else
            print "else"
    end select
next
sleep
Title: Re: High Level Language in MASM
Post by: CommonTater on November 23, 2012, 05:19:23 PM
By design, yes, but IMO the original authors did not spend enough time on the design.

Don't get me wrong... I have my grumbles about C too...

In the case of C's switch statement, yes, we agree they could have done a LOT better. The compiler output is essentialy the same as for an if - else if chain, so there's really no penalty for it other than clumsy syntax.  For high level languages I think Pascal did this one best, with ranges, lists and enums in switches.

Now if someone could come up with a C compiler with **real strings**...  that would be a step in the right direction.



Title: Re: High Level Language in MASM
Post by: anta40 on November 23, 2012, 05:28:58 PM
For high level languages I think Pascal did this one best, with ranges, lists and enums in switches.

Code: [Select]
#include <stdio.h>

int main(void){

    int num = 99;

    switch(num){
        case 1 ... 40:
            printf("< 50");
            break;
        case 49 ... 100:
            printf("> 50");
            break;
        default:
            printf("error");
            break;
    }

    return 0;
}

gcc will happily compile that code, and it will work as expected (like in Basic or Pascal)
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Case-Ranges.html

of course, it's not a valid ISO C code  :(

Now if someone could come up with a C compiler with **real strings**...  that would be a step in the right direction.

Too late, maybe  :P
Title: Re: High Level Language in MASM
Post by: jj2007 on November 23, 2012, 07:05:43 PM
Every time I touch C code or, worse, C compilers, I get the creeps.

ROFL... here we go...
...
C falls through switches by design... so you can do this:
Redmond speaking?
 
Quote
That horrible syntax with all those brackets is not without purpose... The brackets mark "scopes" which serve to separate blocks of code... The open brace actually creates a stack frame ... the code runs on that... then the closing brace destroys it.  C rules of scope are very handy at times, especially when you have a long subroutine with several sets of independent variables...

You mean something like this?
Quote
   if (myflag)   //C needs (lots) (of) (brackets) (everywhere)
      {
         cout << "flag was set" << endl;
         cout << "hooray" << endl;
      }
   else
      {
         cout << "flag was clear" << endl;
      }

IMHO the "design" could be improved:
Quote
   .if myflag   ; Masm is user-hands-friendly
      PrintLine "flag was set"
      Print "hooray"
   .else
      PrintLine "flag was clear"
   .endif
;)

P.S.:
> The open brace actually creates a stack frame
In Masm we use proc ... endp, which helps to distinguish code blocks that are called from those that are separated by branching (.if ... .elseif ... .endif). These so-called "procs" are very handy if you have long blocks of code ;-)
Title: Re: High Level Language in MASM
Post by: jj2007 on November 23, 2012, 07:16:44 PM
    switch(num){
        case 1 ... 40:
            printf("< 50");
            break;
        case mystart ... myend:
            printf("> 50");
            break;
        default:
            printf("error");
            break;
    }

    return 0;
}

The green part would be easy to implement in Masm. What about the red part? Would GCC understand it?
Title: Re: High Level Language in MASM
Post by: anta40 on November 23, 2012, 07:44:46 PM
You mean like this?
Code: [Select]
#include <stdio.h>

int main(void){

    int num = 99;
    int mystart = 49;
    int myend = 100;

    switch(num){
        case 1 ... 40:
            printf("< 50");
            break;
        case mystart ... myend:
            printf("> 50");
            break;
        default:
            printf("error");
            break;
    }

    return 0;
}

Doesn't work, unfortunately (tested with GCC 4.7.2)
Quote
switchtest.c: In function 'main':
switchtest.c:13:9: error: case label does not reduce to an integer constant

Title: Re: High Level Language in MASM
Post by: hutch-- on November 23, 2012, 08:16:30 PM
 :biggrin:

DAMN, I knew it would happen !!!! HOLY WAR !   :P
Title: Re: High Level Language in MASM
Post by: jj2007 on November 23, 2012, 08:49:55 PM
You mean like this?
...
Doesn't work, unfortunately (tested with GCC 4.7.2)

What a pity. Try this:
Code: [Select]
include \masm32\include\masm32rt.inc
.code
start:
  mov eax, 8
  mov edx, 7
  mov ecx, 9
  switch eax
  case 1
  print "my var is one", 13, 10
  case edx .. ecx
  print "my var is between 7 and 9", 13, 10
  case 10 .. 15
  print "my var is between 10 and 15", 13, 10
  case 16
  print "my var is sixteen", 13, 10
  default
  print str$(eax), " is nowhere in the ranges above", 13, 10
  endsw
  inkey "OK?"
  exit
end start

;-)
Title: Re: High Level Language in MASM
Post by: CommonTater on November 23, 2012, 11:01:47 PM
You mean something like this?
Quote
   if (myflag)   //C needs (lots) (of) (brackets) (everywhere)
      {
         cout << "flag was set" << endl;
         cout << "hooray" << endl;
      }
   else
      {
         cout << "flag was clear" << endl;
      }

Nope... that's C++ 
This is C...
Code: [Select]
if (Myflag)
  puts("flag was set\n hooray");
else
  puts("flag was clear");

FYI  they are two separate languages.
Title: Re: High Level Language in MASM
Post by: CommonTater on November 23, 2012, 11:03:18 PM
:biggrin:

DAMN, I knew it would happen !!!! HOLY WAR !   :P

Not to worry, Hutch...  I learned a long time ago to never argue with a zealot...
But I still get a kick out of prodding them once in a while.

Title: Re: High Level Language in MASM
Post by: hutch-- on November 23, 2012, 11:36:04 PM
 :biggrin:

Yeah, particularly if you use a sharp stick.  :P
Title: Re: High Level Language in MASM
Post by: jj2007 on November 24, 2012, 01:05:30 AM
This is C...
Code: [Select]
if (Myflag)
  puts("flag was set\n hooray");
else
  puts("flag was clear");

FYI  they are two separate languages.

Soooorry  :redface:
So C++ couts, and C puts text on the screen. Interesting.
And you could have two lines without {brackets} in C, like this? I mean, the C compiler understands that the two lines between if and else belong to the same scope?

Code: [Select]
if (Myflag)
  puts("flag was set");
  puts("hooray");
else
  puts("flag was clear");
Title: Re: High Level Language in MASM
Post by: CommonTater on November 24, 2012, 02:12:09 AM
So C++ couts, and C puts text on the screen. Interesting.
And you could have two lines without {brackets} in C, like this? I mean, the C compiler understands that the two lines between if and else belong to the same scope?

Code: [Select]
if (Myflag)
  puts("flag was set");
  puts("hooray");
else
  puts("flag was clear");

No it doesn't... you would need brackets on the first part but not on the second.  However it's much easier to do it the way I showed in my origial example... since you have two puts statements you can simply merge the strings and have one call.

You do this...
Code: [Select]
if (Myflag)
  {
     puts("flag was set");
     puts("hooray");
  }
else
  puts("flag was clear");

The thing is you are revealing that you don't actually know enough about these languages to offer a valid critique.  Why don't you take in a couple of tutorials...  like THIS (http://www.iu.hio.no/~mark/CTutorial/CTutorial.html) ...Play with the code, try the examples and then see what you think, once armed with real information?
 
Most of the outspoken opposition I hear to various programming languages comes from a natural human tendency to react to difference in a negative way.  I'm here by invitation to do two things... First, to offer up Easy Build (in the IDE forum) for beta testing and Second to learn a little ASM.  I look at some of the code snippets here and find myself naturally going "Oh WTF is THIS???" but through experience learning new languages and procedures, I know this is just a reaction to difference... its a semantically different way of expressing the same instructions to the CPU and not a flaw at all. 
 
There are many many cases of "distinction without difference" in this world... C uses puts(), C++ uses cout, Pascal uses write(), BASIC uses print, and so on... in the end they're all calls to the API's WriteConsole() function, which is really the only way to get something onto a console screen... The semantics employed in doing that are unimportant.  This truly is disctinction without difference and to criticise any one as being worse than the others is a fools errand.  In the end all you're really saying is "I don't understand this and it scares me".
 
Title: Re: High Level Language in MASM
Post by: jj2007 on November 24, 2012, 03:57:48 AM
C uses puts(), C++ uses cout, Pascal uses write(), BASIC uses print, and so on... in the end they're all calls to the API's WriteConsole() function, which is really the only way to get something onto a console screen... The semantics employed in doing that are unimportant.  This truly is disctinction without difference and to criticise any one as being worse than the others is a fools errand.  In the end all you're really saying is "I don't understand this and it scares me".

Hi Tater,

No offense meant - but I do understand C, and I am not scared, just amused. I know that you can merge the two lines, but I also know that in order to squeeze in one more instruction, you must revert to {ugly brackets} that you so kindly made disappear by joining the two puts statements.

And semantics do matter. Print and Write are user-friendly, cout and puts aren't. They reflect the attitude of C coders who say, more or less openly, "you hobby coders with your BASIC spaghetti code and GOTOs all over the place, do not speak up when professionals are around" (I haven't used any GOTO in the last 25 years). Many C coders have similar "respect" for assembly coders, they see them as freaks who have missed the train etc...

My heart pressure regularly increases when I am confronted with "professional" products coded in C, like AcroRead or Flash or Mozilla, and they crash right in my face, or they drive the CPU to 99% because a team of arrogant coders is too lazy to read bug reports, or is helpless overwhelmed by their code base dispersed over a Million tiny *.cpp, *.c and *.h files. Should I be impressed by Windows 7? Wow, it works! The richest and biggest software company in the World has finally succeeded to deliver an OS that does what the userbase wants. Oh my god, miracles happen... no, really, I am not scared of C code. Except when I have to suffer from the results ;-)
Title: Re: High Level Language in MASM
Post by: CommonTater on November 24, 2012, 05:27:58 AM
No offense meant - but I do understand C,

All evidence to the contrary not withstanding.

Quote
And semantics do matter. Print and Write are user-friendly, cout and puts aren't.

Pascal ... write("This is a test");
C ... puts("This is a test");
C++ ...  cout << "This is a test";
Basic ... print "this is a test"

Seriously...  if petty differences annoy you to the point of hatred, I think we're done.

Title: Re: High Level Language in MASM
Post by: hutch-- on November 24, 2012, 08:06:39 AM
if there is one beef I have with C it is strong typing, too many years of assembler where the only factors is size not type. I understand why it is required in a portable language as you have hardware differences from one platform to another which effectively gives you different sizes for a given variable type but it comes at the price of confusing many folks that try and learn assembler programming where the only factor is size.

This is the main reason why I have never gone that way with MASM, there have been many attempts over the years to straight jacket MASM with C style data naming and typing but it always came at the price of obscuring one of MASM's main advantages, always knowing the size of the data and how this factor works directly with registers.
Title: Re: High Level Language in MASM
Post by: CommonTater on November 24, 2012, 11:02:41 AM
if there is one beef I have with C it is strong typing, too many years of assembler where the only factors is size not type. I understand why it is required in a portable language as you have hardware differences from one platform to another which effectively gives you different sizes for a given variable type but it comes at the price of confusing many folks that try and learn assembler programming where the only factor is size.

This is the main reason why I have never gone that way with MASM, there have been many attempts over the years to straight jacket MASM with C style data naming and typing but it always came at the price of obscuring one of MASM's main advantages, always knowing the size of the data and how this factor works directly with registers.

Hi Hutch...
I find it rather amusing that you think C is typed too strongly, when one of the concerns in the language is that variable typing can be misused through pointers.

Without knowing for certain I believe C became typed very early in it's inception as a means of detecting programming errors such as trying to stuff an int (32/64bits) into a char (8bits) and so on.  While it is still mainly a size and signed vs unsigned issue, there have been many times when the compiler has helped me catch serious mistakes by erroring off when I misused a variable. 

Also there are different storage formats... ints are obvious, they're simple copies of registers, float and double are not so obvious since they are formatted into groups of 32 bit (or 64 bit) values for sign, exponent, integer and decimals, etc.  The real bogeyman is structs, coder defined blobs of memory where misuse could result in severe data corruption which, as I'm sure you can guess, is strongly undesirable... "Ok, how the heck does this thing think we have 23823904857 chrome plated skyhooks in stock?" and such.

ASM affords more lattitude, but it also places the onus upon the programmer to make sure that data is manipulated correctly. Get it wrong and it will happily do it wrong.  It is thus (IMO) more flexible and more dangerous, at the same time. 

Moreover; given that the relative skills of ASM vs C programmers covers a gap roughly equivalent to that between C and Java... I'd have to suggest that perhaps we should be glad of that.  (If only I had a dollar for every time I've had to explain why we free memory in C to a java programmer...  ;)  )

No, I don't think MASM (or any other assembler) should be made to be more like anything else... in fact one of my beefs with compiler development is that people do try to create tools that are "like _____ " when in fact they should focus on the strengths and improvement of what they've got.  Similarity does not breed innovation and progress. Diversity does.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 24, 2012, 06:52:51 PM
Also there are different storage formats... ints are obvious, they're simple copies of registers, float and double are not so obvious since they are formatted into groups of 32 bit (or 64 bit) values for sign, exponent, integer and decimals, etc.  The real bogeyman is structs, coder defined blobs of memory...

MASM has all the requisites to avoid this kind of problems.

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
.data
MyQword   dq 123456789012345678
MyDword   dd 123456789
MyWord   dw 12345
MyByte   db 123
MyReal4   REAL4 1234567890.12345678
MyReal8   REAL8 1234567890.12345678
MyReal10   REAL10 1234567890.12345678
MyRect   RECT <12, 34, 56, 78>       ; a coder defined blob of memory

   Init
   PrintLine Str$("Qword: \t %i", MyQword)
   PrintLine Str$("Dword: \t %i", MyDword)
   PrintLine Str$("Word: \t %i", MyWord)
   PrintLine Str$("Byte: \t %i", MyByte)

   PrintLine Str$("Real4:   \t %If", MyReal4)
   PrintLine Str$("Real8:   \t %If", MyReal8)
   PrintLine Str$("Real10: \t %If", MyReal10)

   ; PrintLine Str$("Rect:     \t %i", MyRect)   ; Error A2049: Invalid instruction operands
   PrintLine Str$("Rect:     \t %i", MyRect.left)
   PrintLine Str$("Rect:     \t %i", MyRect.bottom)

   fldpi   ; load PI into FPU
   PrintLine Str$("PI on FPU: \t %If", ST(0))
   fstp MyReal8   ; store ST(0) to memory as float
   movlps xmm0, MyReal8
   PrintLine Str$("PI as xmm: \t %If", f:xmm0)

    Inkey
   Exit
end start

Output:
Qword:   123456789012345678
Dword:   123456789
Word:    12345
Byte:    123
Real4:           1234567936.00000000
Real8:           1234567890.12345672
Real10:          1234567890.12345678
Rect:            12
Rect:            78
PI on FPU:       3.14159265358979324
PI as xmm:       3.14159265358979312
Title: Re: High Level Language in MASM
Post by: hutch-- on November 24, 2012, 09:04:47 PM
CommonTater,

Probably the real difference is how the data is described, strong typing depends of the prototypes where size casting alone means you are dependent on the documentation to know if a single variable is a handle, signed or unsigned integer, pointer, structure address etc ...

I am old enough to remember C that was far more loosely typed and you could write it more like untyped MASM but progressive demand for safer code meant ansi89 then 99 supported stronger typing but fortunately for experienced C programmers they could type cast a variable as another data type if necessary.

In my own case i would rather something that crashed in development so I could fix it then rather than climbing through a mountain of safety measures to find out why. You will probably laugh at this but I prefer to write "suicide" code that really will go bang if you get it wrong because it does not leave you guessing if something is wrong. It forces onto you the discipline of getting it right every time.
Title: Re: High Level Language in MASM
Post by: CommonTater on November 24, 2012, 10:28:26 PM
I am old enough to remember C that was far more loosely typed and you could write it more like untyped MASM but progressive demand for safer code meant ansi89 then 99 supported stronger typing but fortunately for experienced C programmers they could type cast a variable as another data type if necessary.

My own programming history comes from strongly typed languages... first several incarnations of Basic in the late 70s to mid-80s, then a couple of  flavours of Pascal running up to 2004  when I switched to C.  So my history is largely in strongly typed languages.  Past forets into ASM have all been utilitiarian, where I needed to do something the language couldn't. 

Quote
In my own case i would rather something that crashed in development so I could fix it then rather than climbing through a mountain of safety measures to find out why. You will probably laugh at this but I prefer to write "suicide" code that really will go bang if you get it wrong because it does not leave you guessing if something is wrong. It forces onto you the discipline of getting it right every time.

As it turns out we agree on this point... although I'm sure our experiences of it are somewhat different.  I definately want my code to fail while I still have it contained and under my control....

I just love it when the compiler catches me messing up. It saves me a ton of trouble and always gives me a line number for reference.  Having never written a program of any size that didn't spit out at least one compiler error,  I can well imagine the chaos if this didn't happen. 

Run time errors present an entirely different challenge... alpha testing usually shows up a lot of the worst problems but in any code more complex than "Can you guess my number" there is bound to be at least one subtle error that won't show up until your code gets out into the wild.  (Hense the Beta phase of Easy Build.)

We can see changes in the industry because of so called "type safe" languages, garbage collectors, etc.  The new trend is to trust the compiler, releasing practically untested code and then fixing the problems as they are reported; essentially using your own customers as alpha testers. While this does let you be far more prolific with your keyboard it certainly isn't leading to safe or stable code. 

But then what do we expect in a world that wants it NOW and at "deep discount" prices to boot.
Title: Re: High Level Language in MASM
Post by: dedndave on November 25, 2012, 01:52:20 AM
that's really the difference between assembly programmers and those of all other languages
we are aware that it is easier to screw up, and prefer to keep tabs on it, ourselves   :biggrin:
if you don't want to take that extra measure, assembler isn't for you
Title: Re: High Level Language in MASM
Post by: CommonTater on November 25, 2012, 02:01:05 AM
that's really the difference between assembly programmers and those of all other languages
we are aware that it is easier to screw up, and prefer to keep tabs on it, ourselves   :biggrin:
if you don't want to take that extra measure, assembler isn't for you

Agreed! 

I don't mind going the extra inch, in fact I probably already do it as a routine matter of general precaution.

Title: Re: High Level Language in MASM
Post by: nidud on November 25, 2012, 04:19:28 AM
If people chose to write in their own native language in this forum (or create a new language as they go along) it will generate some problems with regards to communication in general. This is the reason why a specific language is used. Not because the language itself is superior, but because history made it so. This thread is about MASM which has it’s own history.

Quote
Version 6.0, released in 1992, added high-level programming support and a more C-like syntax.
Quote
It incorporates conveniences of high-level languages while offering all the traditional advantages of assembly-language programming.
MASM is maintained by Microsoft, but since version 6.12 has not been sold as a separate product, it is instead supplied with various Microsoft SDKs and C compilers. Recent versions of MASM are included with Microsoft Visual Studio.
This means that the ocean is still open, so you don’t have to use the Panama or Suez canal, you can still go (or code) around if you chose to do so.

Quote
Loop-Generating Directives
The high-level control structures generate loop structures for you. These directives are similar to the while and repeat loops of C or Pascal, and can make your assembly programs easier to code and to read.
Easier to code is one thing, but the most important thing is of course to enable OTHER PEOPLE to be able to read your code.

I know this is the wrong place to do this, but since I already have implemented some changes to the hll section to make my assembly programs easier to code and read, I may ass well share some of this progress.

The first thing I removed was the FUNC() and CStr() macros, since these were the most frequently used. For portability reasons I also target the names of the registers, so RAX will now expand to AX, EAX, or RAX.

The prologue and epilogue definitions will make it possible to make portable source in ASM:
Code: [Select]
IOCreateSource proc
    .if IOOpenSource("w+")
        invoke IOOnCreate,fp_src,option_src
        invoke fclose,fp_src
        mov rax,1
    .else
        invoke IORemoveTemp
    .endif
    ret
IOCreateSource endp

This code will compile in all memory models (tiny, small, compact, large, flat, 64), in C, Pascal, Stdcall, and also Fastcall. The norm will be 32/64-bit, but since I’m a bit old fashioned, I also include the 16-bit stuff (as MASM does).

The size of integer is size_t (from C), and I think MS uses IWORD for signed values? The RAX definition was used in VC a long time before 64-bit was around (for AX and EAX), and now used in 64-bit.
Code: [Select]
IOOnCreate proc uses rsi rdi rbx fp:ptr S_FILE, ftype:size_t
The result looks like this:
Code: [Select]
    .if ftype == SOURCE_C
        invoke fprintf,fp, addr cp_head,
            "/*", addr file,
            " *", addr identifier,
            " *",
            " *",
            " *", rbx, rdi, rsi,
            " */\n\ntypedef unsigned short WORD;"
    .elseif ftype == SOURCE_ASM
        invoke fprintf,fp, addr cp_head,
            ";", addr file,
            ";", addr identifier,
            ";",
            ";",
            ";", rbx, rdi, rsi,
            "\ninclude clib.inc\n\n.data"
    .endif
The C code will include function calls like this:
Code: [Select]
            " *", getmnd(), getday(), getyear() - 2000,
With regards to implement C in assembly, I think it would be much better to implement asm { } in C instead. :P
Title: Re: High Level Language in MASM
Post by: frktons on November 30, 2012, 10:09:50 AM
Woauiextpd!!!!!

I can't believe it. We've done it again.  :lol:
Title: Re: High Level Language in MASM
Post by: dedndave on November 30, 2012, 11:33:00 AM
Woauiextpd!!!!!

I can't believe it. We've done it again.  :lol:

you are a little too excited about code, Frank   :biggrin:
Title: Re: High Level Language in MASM
Post by: hutch-- on November 30, 2012, 04:23:25 PM
There is another factor that sticks in my head hen it comes to choosing what language to write an application with and it depends on the frequency of use. I often use a console basic compiler to perform write once, run once code, usually for constructing messy tables and similar. Then you have at a commercial level code that is only used occasionally in house and this is where I see the use of visual garbage as it gets the job of writing it done quickly.

Further up the scale for higher volume usage like release commercial software sold on the open market it becomes justifiable to write the application in C++ or C and with either written properly and tuned to the required result the price per user actually goes down. Now when you write a large commercial operating system, a portable high performance language is the right way to go as it is capable of delivering the performance in all but the most demanding tasks.

When you know what the platform is (the OS Windows, Unix etc...) you can then target if necessary the occasional hotspot in assembler as it has the flexibility and capacity to do things that the very best of compiler don't do well.

Variation of what you write with what are then effected by what you have the most experience in writing. Any language that you use required practice and the more you write with it, the better you get with it. This is very much the case with assembler, it is still an art, not a science and that requires practice.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 30, 2012, 05:42:42 PM
I often use a console basic compiler to perform write once, run once code

Yeah, there are powerful tools to do so ;-)
Title: Re: High Level Language in MASM
Post by: Gunther on December 02, 2012, 07:06:02 AM
Hi Jochen,

Yeah, there are powerful tools to do so ;-)

Of course: PowerBASIC, MasmBASIC and the like.  :t

Gunther
Title: Re: High Level Language in MASM
Post by: nidud on December 10, 2012, 07:24:57 PM
Here is new modified version using JWasm version 2.09
Title: Re: High Level Language in MASM
Post by: habran on December 10, 2012, 10:23:00 PM
looks promising :eusa_clap:
 but where is the source? :icon_confused:
Title: Re: High Level Language in MASM
Post by: nidud on December 11, 2012, 04:32:28 AM
It is used to compile the Doszip Commander
Source files and more information is included in the dzsrc242.zip file

Download: https://sourceforge.net/projects/doszip/files/
Title: Re: High Level Language in MASM
Post by: habran on December 12, 2012, 12:15:31 AM
Thanks nidud
that is very nice programming :eusa_clap:
when you write your own code it is easy
but to hack someone else's code is hard thing to do

I admire your effort and code

best regards
Title: Re: High Level Language in MASM
Post by: nidud on December 12, 2012, 01:48:49 AM
Well, thanks habrab, but it is still just a hack, and I don’t think japheth will approve of this butchering.

However brutal the approach, it is at least a start..
Title: Re: High Level Language in MASM
Post by: habran on December 12, 2012, 05:55:18 AM
Of course that japheth will !approve what we are doing
however, it gives him some new ideas e.g. shadow spacing
BTW you've got so used to hack that you even hacked my name :lol:
b for Brutus? or Butcher? :bgrin:
Title: Re: High Level Language in MASM
Post by: nidud on January 15, 2014, 01:29:09 AM
This is a small update to ASM (still using JWasm v2.09)

A switch is added to compile a directory structure:
Code: [Select]
ASM -r \LIB\SRC\*.asm
This will compile all *.asm files in the directory and all subdirectories of \LIB\SRC.

The result (*.OBJ) may be used as argument to LIB (and also LINK?)
Including this feature in JWLIB/JWLINK could reduce the scripting in the make process.
Title: Re: High Level Language in MASM
Post by: nidud on January 16, 2014, 11:38:57 PM
This version uses JWasm v2.10
Title: Re: High Level Language in MASM
Post by: nidud on August 11, 2014, 09:40:43 PM
This is the C-Stack version of ASM

changes to 1.04:

   push   ebp
   mov   ebp,esp
   push   esi
   push   edi
   push   ebx

is changed to:

   push   esi
   push   edi
   push   ebx
   push   ebp
   mov   ebp,esp

alloca may then be used to allocate memory from the stack
Code: [Select]
OPTION PROLOGUE:NONE, EPILOGUE:NONE

alloca  proc bsize:dword
lea eax,[esp+4]
mov ecx,[eax] ; size to probe
     @@:
cmp ecx,PAGESIZE ; probe pages
jb @F
sub eax,PAGESIZE
test [eax],eax
sub ecx,PAGESIZE
jmp @B
     @@:
sub eax,ecx
and al,0F0h ; align 16
test [eax],eax ; probe page
mov ecx,esp
mov esp,eax
push [ecx+8+4] ; preserve 8 byte
push [ecx+8+0]
push [ecx]
ret
alloca  endp

The default stack is 1M, so this should be safe
Code: [Select]
main proc c
local StackFrame
mov eax,esp
push 1
push 2
push 3
invoke  printf,"ESP:%08X\nPUSH 1 2 3\nalloca(65536) x 15\n",eax
xor  edi,edi
.repeat
    invoke alloca,10000h
    invoke printf,"EAX:%08X\n",eax
    inc edi
.until edi == 15
pop eax
pop ecx
pop edx
invoke printf,"POP EAX ECX EDX\nEAX: %d (3)\nECX: %d (2)\nEDX: %d (1)\n",eax,ecx,edx
sub eax,eax
ret
main endp

result:
ESP:0012FFB8
PUSH 1 2 3
alloca(65536) x 15
EAX:0011FFA0
EAX:0010FF90
EAX:000FFF80
EAX:000EFF70
EAX:000DFF60
EAX:000CFF50
EAX:000BFF40
EAX:000AFF30
EAX:0009FF20
EAX:0008FF10
EAX:0007FF00
EAX:0006FEF0
EAX:0005FEE0
EAX:0004FED0
EAX:0003FEC0
POP EAX ECX EDX
EAX: 3 (3)
ECX: 2 (2)
EDX: 0 (1)

More memory may be allocated by using the LINK /STACK:<size> option.
Title: Re: High Level Language in MASM
Post by: dedndave on August 11, 2014, 10:30:56 PM
1 MB is the default reserved stack size
but, less than that is committed

as your program uses more and more stack space, more is committed
the OS commits space in 4 KB pages
you can cause more space to be committed by "probing" the stack

oddly, if you attempt to access stack space below the committed pages,
the program is likely to terminate - without generating an exception   :(

here's a little routine that can be used to probe the stack down to a specified "depth"
Code: [Select]
;*****************************************************************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

ProbeStack PROC    uSize:UINT

;Probe Stack to Bytes Requested
;Copyright Dedndave 6-2012
;
;  Returns: EAX = probed-to stack pointer
;           ECX = bytes requested
;           EDX = top of stack

;---------------------------------------------------

        ASSUME  FS:Nothing

        mov     eax,esp
        mov     ecx,[esp+4]
        add     eax,8
        push    ebp
        sub     eax,ecx
        mov     ebp,esp
        and     al,-16                    ;must be 4-aligned, 16-aligned optional

Probe0: push    ecx
        mov     esp,fs:[8]
        cmp     eax,esp
        jb      Probe0

        mov     edx,esp
        leave
        ret     4

        ASSUME  FS:ERROR

ProbeStack ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;*****************************************************************************************************

i quite often just place the loop inline, as it doesn't take that much code   :P
Title: Re: High Level Language in MASM
Post by: dedndave on August 11, 2014, 10:37:36 PM
here is an example
http://masm32.com/board/index.php?topic=3326.msg35046#msg35046 (http://masm32.com/board/index.php?topic=3326.msg35046#msg35046)

in a couple of the following posts you will find different variations
Title: Re: High Level Language in MASM
Post by: nidud on August 11, 2014, 11:20:49 PM
1 MB is the default reserved stack size
but, less than that is committed

The alloca function commits the reserved stack

Quote
you can cause more space to be committed by "probing" the stack

My conclusion was (http://masm32.com/board/index.php?topic=2517.msg26546#msg26546) that you don't have to do that  :biggrin:

Quote
oddly, if you attempt to access stack space below the committed pages,
the program is likely to terminate - without generating an exception   :(

Using 16 instead of 15 in the above test generates a stack fault exception
Title: Re: High Level Language in MASM
Post by: nidud on August 12, 2014, 04:51:22 AM
oddly, if you attempt to access stack space below the committed pages,
the program is likely to terminate - without generating an exception   :(

Using 16 instead of 15 in the above test generates a stack fault exception

I assume it does generate an exception. However, if you use ESP directly to access stack below committed pages you destroy the stack (ESP) in the process, so the exception code will probably not be able to execute.

Using EAX:
Code: [Select]
lea eax,[esp+4]
mov ecx,[eax] ; size to probe
     @@:
cmp ecx,PAGESIZE ; probe pages
jb @F
sub eax,PAGESIZE
test [eax],eax ; exception: ESP intact
sub ecx,PAGESIZE
jmp @B
     @@:
sub eax,ecx
and al,0F0h ; align 16
test [eax],eax ; exception: ESP intact
mov ecx,esp
mov esp,eax

Using ESP:
Code: [Select]
mov eax,esp
sub esp,4
mov ecx,[esp] ; size to probe
     @@:
cmp ecx,PAGESIZE ; probe pages
jb @F
sub esp,PAGESIZE
test [esp],eax ; exception: ESP destroyed
sub ecx,PAGESIZE
jmp @B
     @@:
sub esp,ecx
and esp,0FFFFFFF0h  ; align 16
test [esp],eax ; exception: ESP destroyed
Title: Re: High Level Language in MASM
Post by: dedndave on August 12, 2014, 09:40:06 PM
I assume it does generate an exception. However, if you use ESP directly to access stack below committed pages you destroy the stack (ESP) in the process, so the exception code will probably not be able to execute.

good point   :biggrin:
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2014, 01:57:48 AM
Here is a version using JWasm v2.12

Some of the functions was removed, like the use of RAX in 16/32/64-bit
Here is a list of the functions implemented:

   - use full or relative path on source files (as given)
   - do not convert short file names (DOS) to long file names
   - the switch -r to compile a directory tree
   - no macros or function expanded above labels
   - use TEST REG,REG on testing result -- not AND/OR
   - do not use LOOPx in .UNTILCXZ  -- DEC ECX, JNZ .REPEAT
   - use a C-Stack frame: push "USES" regs before EBP
   - "C-Strings\n" used directly in INVOKE an HLL functions
   - functions and labels used directly in HLL functions
   - the switch -? insert a "Hit any key to continue..." (screen page)

Title: Re: High Level Language in MASM
Post by: Gunther on September 04, 2014, 02:58:44 AM
Hi nidud,

thank you for providing the new source.  :t

Gunther
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2014, 04:01:45 AM
thank you for providing the new source.  :t

well   :P

the source code was to big so I uploaded source and binaries to the site for those who interested.
Title: Re: High Level Language in MASM
Post by: anta40 on September 04, 2014, 11:22:24 AM
the source code was to big so I uploaded source and binaries to the site for those who interested.

I'd like to see the source code.  :biggrin:
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2014, 09:46:44 PM
I'd like to see the source code.  :biggrin:

just click on the green thing to the left
the files are in the ASM directory
Title: Re: High Level Language in MASM
Post by: nidud on September 11, 2014, 02:05:42 AM
Some bugs fixed in ASM.EXE

The first one is a JWASM bug from v2.11

HLL3.ASM
Code: [Select]
; JWASM - hll.c v2.11/12 -- missing label

.386
.model flat

.code

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

end

The next two is the handling of HLL/MACRO in .while and .elseif

ASM1.ASM
Code: [Select]

; ASM v1.05 - generate an error
; ASM v1.06 - fixed

.386
.model flat

foo macro reg
inc reg
exitm <reg>
endm

.code

.while foo(eax)
    nop
.endw

end

Generated code:

JMP SHORT CS004
CS002:  NOP
INC EAX
CS004:  TEST EAX,EAX
JNZ SHORT CS002

MASM/JWASM - fails -- no error:

INC EAX
JMP SHORT CS004
CS003:  NOP
CS004:  OR EAX,EAX
JNZ SHORT CS003

ASM2.ASM
Code: [Select]

; ASM v1.05 - generate an error
; ASM v1.06 - fixed

.386
.model flat

foo macro reg
inc reg
exitm <reg>
endm

.code

.if eax
    nop
.elseif foo(eax)
    nop
.endif

end

Generated code:

TEST EAX,EAX
JZ SHORT CS0007
NOP
JMP SHORT CS000D
CS0007: INC EAX
TEST EAX,EAX
JZ SHORT CS000D
NOP
CS000D:

MASM/JWASM fails -- no error:

OR EAX,EAX
JZ SHORT CS0008
NOP
INC EAX
JMP SHORT CS000D
CS0008: OR EAX,EAX
JZ SHORT CS000D
NOP
CS000D:
Title: Re: High Level Language in MASM
Post by: nidud on September 11, 2014, 03:15:00 AM
new update   :biggrin:

Code: [Select]

; ASM v1.05 - generate an error
; ASM v1.06 - fixed
; ASM v1.07 - push label before expanding macro..

.386
.model flat

foo macro reg
inc reg
exitm <reg>
endm

.code

.while foo(eax)
    nop
.endw

end

Generated code:

JMP SHORT CS0003
CS0002: NOP
CS0003: INC EAX
TEST EAX,EAX
JNZ SHORT CS0002

Version 1.06: fails..

JMP SHORT CS0004
CS0002: NOP
INC EAX
CS0004: TEST EAX,EAX
JNZ SHORT CS0002

MASM/JWASM fails -- no error:

INC EAX
JMP SHORT CS004
CS003:  NOP
CS004:  OR EAX,EAX
JNZ SHORT CS003
Title: Re: High Level Language in MASM
Post by: nidud on January 03, 2015, 08:47:38 AM
ASMC version 1.12

this is a bug-fix discussed here (http://masm32.com/board/index.php?topic=3915.msg41214#msg41214)

Code: [Select]

; ASMC v1.12 - invoke.c
; stack error on types not aligned 4: 6, 10, 14, ...

.386
.model flat

foo proto c :VARARG

.data

num dt 3.14159265358979323846264338327

.code

invoke  foo,num

end

ASM.EXE is now renamed to ASMC.EXE -- there appear to be a Microsoft tool named ASM.EXE

The changes done is in invoke.c: (should be applied to JWASM)
Code: [Select]
static int PushInvokeParam( ... )
{
...
while ( asize > 0 ) {

    if ( asize & 2 ) {

/* ensure the stack remains dword-aligned in 32bit */
if ( ModuleInfo.Ofssize > USE16 ) {
    /* v2.05: better push a 0 word? */
    //AddLineQueueX( " pushw 0" );
    /* ASMC v1.12: dword-aligned stack in 32bit */
    if (pushsize == 4)
size_vararg += 2;
    /******/
#if AMD64_SUPPORT
    AddLineQueueX( " sub %r, 2", stackreg[ModuleInfo.Ofssize] );
#else
    AddLineQueueX( " sub %r, 2", T_ESP );
#endif
}
AddLineQueueX( " push word ptr %s+%u", fullparam, NUMQUAL asize-2 );
asize -= 2;
    } else {
Title: Re: High Level Language in MASM
Post by: Gunther on January 03, 2015, 09:55:25 AM
Hi nidud,

ASMC version 1.12

this is a bug-fix discussed here (http://masm32.com/board/index.php?topic=3915.msg41214#msg41214)

good and fast reaction.  :t At least our discussion did help you a bit.

Gunther
Title: Re: High Level Language in MASM
Post by: nidud on September 03, 2015, 08:04:14 AM
Inspired by the PDF produced by QWORD I did a profile of (JW)ASM to see if it was possible to port some of the code to assembly.
Code: [Select]
        Func          Func+Child           Hit
        Time   %         Time      %      Count  Function
---------------------------------------------------------
     255,316  22,9      255,316  22,9      505 _open_files (_assemble.obj)
      98,520   8,9       98,520   8,9   237603 _my_fgets (input.obj)
      56,082   5,0      142,999  12,9   647207 _get_id (tokenize.obj)
      55,787   5,0     1103,735  99,2      505 _AssembleModule (_assemble.obj)
      53,689   4,8       53,689   4,8   634653 _get_hash (_reswords.obj)
      42,141   3,8       42,141   3,8      505 _close_files (_assemble.obj)
      41,178   3,7       41,178   3,7   439239 _hashpjw (symbols.obj)
      39,122   3,5       51,139   4,6     1486 _SearchFile (input.obj)
      37,253   3,3      219,720  19,7   290412 _Tokenize (tokenize.obj)
      33,819   3,0       86,917   7,8   631298 _FindResWord (_reswords.obj)
      24,653   2,2       65,577   5,9   435514 _SymFind (symbols.obj)
      23,151   2,1      181,951  16,4   976825 _GetToken (tokenize.obj)
      22,623   2,0       26,050   2,3   237058 _SymAlloc (symbols.obj)
      14,688   1,3      223,301  20,1   166997 _ParseLine (parser.obj)
      14,674   1,3       14,674   1,3      507 _omf_set_filepos (omf.obj)
      14,181   1,3      112,729  10,1   237725 _GetTextLine (input.obj)
      10,989   1,0       12,392   1,1      505 _omf_write_module (omf.obj)
      10,953   1,0       10,953   1,0      990 _open_file_in_include_path (input.obj)
      10,567   0,9       39,968   3,6   197188 _doExpandLine (_expans.obj)
       9,553   0,9       10,961   1,0   269138 _get_special_symbol (tokenize.obj)
       9,445   0,8       30,196   2,7   273875 _ExpandToken (_expans.obj)
       9,363   0,8        9,363   0,8    70014 _myatoi128 (expreval.obj)
       9,211   0,8      533,614  48,0   261718 _PreprocessLine (_preproc.obj)
       8,784   0,8       26,990   2,4    45266 _ParseParams (_proc.obj)
       8,485   0,8        8,485   0,8   515730 _LclAlloc (_memalloc.obj)
       7,627   0,7       47,591   4,3   197285 _ExpandLine (_expans.obj)
       7,296   0,7     1111,281  99,9       42 _AssembleSubdir (_main.obj)
       6,664   0,6        8,188   0,7   112986 _GetQualifiedType (_types.obj)
       5,920   0,5       16,184   1,5   126273 _get_operand (expreval.obj)
       5,523   0,5        5,523   0,5      505 _MemFini (_memalloc.obj)
       5,520   0,5        7,585   0,7      505 _SymInit (symbols.obj)
       4,821   0,4        4,840   0,4    60480 _get_number (tokenize.obj)
       4,185   0,4       25,153   2,3   120343 _evaluate (expreval.obj)
       4,168   0,4        4,168   0,4   364282 _LabelMacro (parser.obj)
       3,982   0,4        6,803   0,6    54809 _output_opc (codegen.obj)
       3,886   0,3       35,500   3,2   111810 _EvalOperand (expreval.obj)
       3,704   0,3        3,704   0,3   207296 _is_expr_item (expreval.obj)
       3,671   0,3        5,700   0,5    37889 _StoreLine (_fastpass.obj)
       3,411   0,3        7,210   0,6    19118 _AddLineQueueX (_lqueue.obj)
       3,368   0,3       31,504   2,8    52493 _ParseProc (_proc.obj)
       3,319   0,3        3,319   0,3   136341 _init_expr (expreval.obj)
       3,191   0,3       17,830   1,6    54809 _codegen (codegen.obj)
       3,102   0,3       53,110   4,8   197285 _ExpandLine_xlabel (_preproc.obj)
       2,851   0,3        4,303   0,4    16622 _CreateStructField (_types.obj)
       2,688   0,2        2,847   0,3    84292 _OutputByte (_assemble.obj)
       2,542   0,2       57,956   5,2     9405 _RunLineQueue (_lqueue.obj)
       2,508   0,2        2,508   0,2    27401 _MemAlloc (_memalloc.obj)
       2,424   0,2       37,060   3,3    50796 _CreateConstant (_equate.obj)
       2,294   0,2       16,766   1,5    51617 _CreateProc (_proc.obj)
       2,238   0,2        8,181   0,7    36300 _match_phase_3 (codegen.obj)
       2,099   0,2        2,589   0,2     1012 _CmdlParamsInit (_assemble.obj)
       2,073   0,2        2,073   0,2    22904 _SearchNameInStruct (_types.obj)
       2,046   0,2        6,969   0,6    20989 _data_item (data.obj)
       2,039   0,2       34,341   3,1   125680 _SymCreate (symbols.obj)
       2,000   0,2        2,489   0,2    50976 _OutputBytes (_assemble.obj)
       1,899   0,2      607,088  54,6     1991 _ProcessFile (parser.obj)
       1,872   0,2        3,840   0,3    53415 _output_data (codegen.obj)
       1,620   0,1        6,001   0,5      505 _omf_write_header_initial (omf.obj)
       1,600   0,1        3,373   0,3    24531 _calculate (expreval.obj)
       1,569   0,1        3,677   0,3    25884 _AddLineQueue (_lqueue.obj)
       1,569   0,1        1,569   0,1    42393 _process_register (parser.obj)
       1,496   0,1        5,334   0,5     8656 _PushInvokeParam (_invoke.obj)
       1,410   0,1       13,699   1,2    18984 _data_dir (data.obj)
       1,399   0,1        4,410   0,4    14191 _memory_operand (parser.obj)
       1,363   0,1        2,228   0,2    25647 _check_size (parser.obj)
       1,360   0,1       56,126   5,0    51694 _CreateProto (_extern.obj)
       1,352   0,1        1,355   0,1     7318 _get_string (tokenize.obj)
       1,336   0,1        2,147   0,2    12214 _process_branch (branch.obj)
       1,335   0,1        1,335   0,1   117537 _SizeFromMemtype (parser.obj)
       1,316   0,1        1,316   0,1     3983 _GetFNamePart (input.obj)
       1,316   0,1       14,486   1,3    64001 _check_operand_2 (codegen.obj)
       1,280   0,1        1,280   0,1    59663 _sym_remove_table (parser.obj)
       1,162   0,1        1,162   0,1     8154 _safeWrite (omfint.obj)
       1,125   0,1        2,287   0,2     8154 _WEndRec (omfint.obj)
       1,021   0,1        1,071   0,1     2013 _PushSrcItem (input.obj)
       0,996   0,1      698,544  62,8     1012 _OnePass (_assemble.obj)

As you see most of the time is used on IO. The functions of interest for optimisation:
Code: [Select]
      56,082   5,0      142,999  12,9   647207 _get_id (tokenize.obj)
      53,689   4,8       53,689   4,8   634653 _get_hash (_reswords.obj)
      41,178   3,7       41,178   3,7   439239 _hashpjw (symbols.obj)
      37,253   3,3      219,720  19,7   290412 _Tokenize (tokenize.obj)
      33,819   3,0       86,917   7,8   631298 _FindResWord (_reswords.obj)
      24,653   2,2       65,577   5,9   435514 _SymFind (symbols.obj)
      23,151   2,1      181,951  16,4   976825 _GetToken (tokenize.obj)
      22,623   2,0       26,050   2,3   237058 _SymAlloc (symbols.obj)
       9,553   0,9       10,961   1,0   269138 _get_special_symbol (tokenize.obj)
       9,363   0,8        9,363   0,8    70014 _myatoi128 (expreval.obj)
       8,485   0,8        8,485   0,8   515730 _LclAlloc (_memalloc.obj)
       5,523   0,5        5,523   0,5      505 _MemFini (_memalloc.obj)
       4,821   0,4        4,840   0,4    60480 _get_number (tokenize.obj)
       2,508   0,2        2,508   0,2    27401 _MemAlloc (_memalloc.obj)
       2,099   0,2        2,589   0,2     1012 _CmdlParamsInit (_assemble.obj)
       2,000   0,2        2,489   0,2    50976 _OutputBytes (_assemble.obj)
       1,352   0,1        1,355   0,1     7318 _get_string (tokenize.obj)

So I rewrote the memory functions, the tokenizer, the assembler, and a few other functions (in assembly). In addition to this I compile using my own library (no SSE).
Code: [Select]
      95,299  18,6 95,374 18,6   4476 __sopen (_sopen.obj)
      72,390  14,1 93,702 18,3 237603 _my_fgets@12 (input.obj)
      71,684  14,0 71,684 14,0   3136 _oswrite@12 (oswrite.obj)
      36,589   7,1 67,391 13,1 290412 _Tokenize@16 (_tokenize.obj)
      30,945   6,0 30,945   6,0   2496 __close@4 (_close.obj)
      29,168   5,7 29,168   5,7 631298 @FindResWord@8 (_memalloc.obj)
      28,775   5,6 28,775   5,6 258903 _memzero@8 (memzero.obj)
      20,785   4,1 20,785   4,1   4155 _osread@12 (osread.obj)
      13,291   2,6 13,371   2,6    505 _remove@4 (remove.obj)
       8,153   1,6 64,707 12,6 166997 _ParseLine@4 (parser.obj)
       7,877   1,5   7,877   1,5 439239 @hashpjw@4 (_memalloc.obj)
       5,076   1,0 14,262   2,8 197188 _doExpandLine@8 (_expans.obj)
       4,928   1,0   6,852   1,3 45266 _ParseParams@16 (_proc.obj)
       4,800   0,9   9,603   1,9 273875 _ExpandToken@24 (_expans.obj)
       4,794   0,9 483,281 94,2      1 _main (_main.obj)
       3,852   0,8   5,594   1,1 126273 _get_operand@16 (expreval.obj)
       3,637   0,7   3,612   0,7 11974 __output@12 (_output.obj)
       3,275   0,6   3,581   0,7 54809 _output_opc@4 (codegen.obj)
       3,260   0,6   2,974   0,6 112986 _GetQualifiedType@12 (_types.obj)
       3,223   0,6   3,223   0,6 815814 _strlen@4 (strlen.obj)
       2,520   0,5 12,848   2,5 435514 _SymFind@4 (symbols.obj)
       2,290   0,4   2,924   0,6 19118 _AddLineQueueX (_lqueue.obj)
       2,244   0,4   9,283   1,8 52493 _ParseProc@20 (_proc.obj)
       2,002   0,4   2,002   0,4 338308 _memcpy@12 (memcpy.obj)
       1,931   0,4   8,284   1,6 54809 _codegen@8 (codegen.obj)
       1,896   0,4   1,896   0,4 136341 _init_expr@4 (expreval.obj)
       1,868   0,4   2,592   0,5 24531 _calculate@12 (expreval.obj)
       1,754   0,3   1,754   0,3   2020 _ftell@4 (ftell.obj)
       1,741   0,3   1,741   0,3 119648 _strcpy@8 (strcpy.obj)
       1,620   0,3   1,620   0,3 207296 _is_expr_item@4 (expreval.obj)
       1,487   0,3   1,515   0,3   1515 __lseeki64@16 (_lseeki64.obj)
       1,451   0,3   1,553   0,3 53415 _output_data@12 (codegen.obj)
       1,178   0,2   1,178   0,2 29455 _malloc@4 (alloc.obj)
       0,248   0,0   0,248   0,0   3355 @get_hash@8 (_memalloc.obj)

SymAlloc:
Code: [Select]
      22,623   2,0       26,050   2,3   237058 _SymAlloc (symbols.obj)
--
       0,000   0,0   0,000   0,0   237058 _SymAlloc@4 (symbols.obj)

FindResWord:
Code: [Select]
      53,689   4,8       53,689   4,8   634653 _get_hash (_reswords.obj)
      33,819   3,0       86,917   7,8   631298 _FindResWord (_reswords.obj)
--
      29,168   5,7 29,168   5,7 631298 @FindResWord@8 (_memalloc.obj)

Tokenize: (the functions below are merged in the new version)
Code: [Select]
      56,082   5,0      142,999  12,9   647207 _get_id (tokenize.obj)
      37,253   3,3      219,720  19,7   290412 _Tokenize (tokenize.obj)
      23,151   2,1      181,951  16,4   976825 _GetToken (tokenize.obj)
       9,553   0,9       10,961   1,0   269138 _get_special_symbol (tokenize.obj)
       4,821   0,4        4,840   0,4    60480 _get_number (tokenize.obj)
--
      36,589   7,1 67,391 13,1 290412 _Tokenize@16 (_tokenize.obj)

The original use FASTCALL (or WATCALL) and this use STDCALL, so the Open Watcom build is still fast and compact. However, it would be interesting to get some test result given all the changes made especially the memory functions. It’s a more conservative way of memory usage limited to 8M total so it may choke on large include files or projects.

I use the ASM name again (good name) and call it the Doszip Macro Assembler. Additional features will now default according to naming of the .EXE. In case of ML.EXE the switch –Zne (Disable syntax extensions not supported by Masm) is set, and getenv("ML") is used. In case of ASM a new switch –cc (C stack frame: push USER regs first) is set. For JWASM none of the above switches are set.
Title: Re: High Level Language in MASM
Post by: jj2007 on September 03, 2015, 08:41:42 AM
Great job :t

But there are still some glitches:
- it appears that not all options are handled like in MASM or JWasm
- more precisely, it segfaults when launched from RichMasm
- more complex code doesn't perform well, even from the commandline:

J:\Masm32\bin>ml /c /coff TestMasmBasic.asm
Microsoft (R) Macro Assembler Version 6.15.8803
Copyright (C) Microsoft Corp 1981-2000.  All rights reserved.

 Assembling: TestMasmBasic.asm

J:\Masm32\bin>asm /c /coff TestMasmBasic.asm
Doszip Macro Assembler Version 2.14, BETA  09/02/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

TestMasmBasic.asm(172) : Error A2147: Empty (null) string
 repargA(58)[MasmBasic.inc]: Macro called from
  PushString(91)[MasmBasic.inc]: Macro called from
   MacroLoop(2): iteration 1: Macro called from
    Print(37)[MasmBasic.inc]: Macro called from
     TestMasmBasic.asm(172): Main line code
TestMasmBasic.asm(347) : Error A2139: String or text literal too long
TestMasmBasic.asm(349) : Fatal error A1089: Out of Memory

Strangely enough, this fails also with JWasm - but the same source compiles just fine with JWasm when built with RichMasm. AFAIK RichMasm sends the same command line options ::)
Title: Re: High Level Language in MASM
Post by: nidud on September 03, 2015, 09:19:45 AM
Thanks for the test  :t

It chokes on memory, I gave it 16M

jwasm /c /coff TestMasmBasic.asm
Code: [Select]
JWasm v2.12pre, Nov 27 2013, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.

TestMasmBasic.asm(151) : Error A2150: Missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(151): Main line code
TestMasmBasic.asm(151) : Error A2048: Operands must be the same size: 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(151): Main line code
TestMasmBasic.asm(153) : Error A2049: Invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(153): Main line code
TestMasmBasic.asm(155) : Error A2150: Missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(155): Main line code
TestMasmBasic.asm(155) : Error A2048: Operands must be the same size: 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(155): Main line code
TestMasmBasic.asm(157) : Error A2049: Invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(157): Main line code
TestMasmBasic.asm(172) : Error A2163: Empty (null) string
 repargA(58)[MasmBasic.inc]: Macro called from
  PushString(81)[MasmBasic.inc]: Macro called from
   MacroLoop(2): iteration 1: Macro called from
    Print(37)[MasmBasic.inc]: Macro called from
     TestMasmBasic.asm(172): Main line code
## psapi included
TestMasmBasic.asm: 704 lines, 1 passes, 359 ms, 0 warnings, 7 errors

asm /c /coff TestMasmBasic.asm
Code: [Select]
Doszip Macro Assembler Version 2.14, BETA  09/03/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

TestMasmBasic.asm(151) : Error A2134: Missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(151): Main line code
TestMasmBasic.asm(151) : Error A2032: Operands must be the same size: 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(151): Main line code
TestMasmBasic.asm(153) : Error A2033: Invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(153): Main line code
TestMasmBasic.asm(155) : Error A2134: Missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(155): Main line code
TestMasmBasic.asm(155) : Error A2032: Operands must be the same size: 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(155): Main line code
TestMasmBasic.asm(157) : Error A2033: Invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  TestMasmBasic.asm(157): Main line code
TestMasmBasic.asm(172) : Error A2147: Empty (null) string
 repargA(58)[MasmBasic.inc]: Macro called from
  PushString(81)[MasmBasic.inc]: Macro called from
   MacroLoop(2): iteration 1: Macro called from
    Print(37)[MasmBasic.inc]: Macro called from
     TestMasmBasic.asm(172): Main line code
## psapi included
TestMasmBasic.asm(347) : Error A2139: String or text literal too long

The error handling is also rewritten so the error ID's are not the same.
It also failed to produce the correct end result

Code: [Select]
## psapi included
TestMasmBasic.asm: 704 lines, 1 passes, 359 ms, 0 warnings, 7 errors
--
## psapi included
TestMasmBasic.asm(347) : Error A2139: String or text literal too long
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 03, 2015, 09:45:12 AM
hi nidud,

thanks it's a great idea to rewrite JWasm in asm (if that's your goal)

It works on some simple 32-bit progs, I'll try to keep using it see what happens

But had errors in other cases, seems to have something to do with "addr"

Both these lines give "Error A2192: Syntax error: addr"

Code: [Select]
.if BYTE PTR [edi]=="c"

;also

.if bx=="//"

As you can see "addr" doesn't appear in these lines.

Also using "addr ThreadProc" in invoke CreateThread statement says ThreadProc doesn't exist. Now this may have something to do with my include files, (altho it works with HJWasm), so perhaps ignore this for now

So problem appears to occur with ".if" HLL statements, at least
Title: Re: High Level Language in MASM
Post by: nidud on September 03, 2015, 09:58:12 AM
But had errors in other cases, seems to have something to do with "addr"

Both these lines give "Error A2192: Syntax error: addr"

Code: [Select]
.if BYTE PTR [edi]=="c"

;also

.if bx=="//"

As you can see "addr" doesn't appear in these lines.

Also using "addr ThreadProc" in invoke CreateThread statement says ThreadProc doesn't exist. Now this may have something to do with my include files, (altho it works with HJWasm), so perhaps ignore this for now

So problem appears to occur with ".if" HLL statements, at least

yes, everything inside double quotes are converted strings in the HLL section. This should probably be limited to procs: .if fopen("src\\hll.c", "rt")
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 03, 2015, 10:26:24 AM
So I should use single quotes instead, in these cases
Title: Re: High Level Language in MASM
Post by: nidud on September 03, 2015, 11:39:50 AM
Yes, that will work, but the idea of this tread is to emulate a C-style code in assembly without breaking existing code or make any compromise in the functionality of the assembler. More probing by the function that creates the strings is probably a better solution.

The strings are only used in function calls:
Code: [Select]
mov edi,Options.names[OPTN_LNKDEF_FN*4]
.if edi
    .if !fopen(edi,"w")
mov eax,errno
invoke EmitErr,CANNOT_OPEN_FILE,edi,sys_errlist[eax*4]
    .else
mov edi,eax
mov esi,SymTables[TAB_EXT*sizeof(symbol_queue)].head
.while esi
    mov ebx,[esi].asym.dll
    .if [esi].asym.flag & SFL_ISPROC && [esi].asym.dll && [ebx].dll_desc.dname \
     && (!([esi].asym.sint_flag & SINT_WEAK) || [esi].asym.flag & SFL_IAT_USED)
invoke Mangle,esi,ModuleInfo.stringbufferend
invoke sprintf,ModuleInfo.currsource, "import '%s'  %s.%s\n",
    ModuleInfo.stringbufferend,
    addr [ebx].dll_desc.dname,
    [esi].asym._name
mov ebx,eax
.if fwrite(ModuleInfo.currsource,1,ebx,edi) != ebx
    call WriteError
.endif
     .endif
     mov esi,[esi].dsym.next
.endw
invoke fclose,edi
    .endif
.endif
mov eax,NOT_ERROR

Code: [Select]
    if ( Options.names[OPTN_LNKDEF_FN] ) {
FILE *ld;
ld = fopen( Options.names[OPTN_LNKDEF_FN], "w" );
if ( ld == NULL ) {
    return( EmitErr( CANNOT_OPEN_FILE, Options.names[OPTN_LNKDEF_FN], ErrnoStr() ) );
}
for ( curr = SymTables[TAB_EXT].head; curr != NULL ; curr = curr->next ) {
    if ( curr->sym.isproc && ( curr->sym.weak == FALSE || curr->sym.iat_used ) &&
curr->sym.dll && *(curr->sym.dll->name) != NULLC ) {
int size;
Mangle( &curr->sym, StringBufferEnd );
size = sprintf( CurrSource, "import '%s'  %s.%s\n", StringBufferEnd, curr->sym.dll->name, curr->sym.name );
if ( fwrite( CurrSource, 1, size, ld ) != size )
    WriteError();
    }
}
fclose( ld );
    }
    return( NOT_ERROR );
Title: Re: High Level Language in MASM
Post by: jj2007 on September 03, 2015, 05:13:27 PM
Thanks for the test  :t

It chokes on memory, I gave it 16M

jwasm /c /coff TestMasmBasic.asm
Code: [Select]
JWasm v2.12pre, Nov 27 2013, Masm-compatible assembler.
...

This is really odd. Works absolutely fine in RichMasm (and has worked for years, this is my ML+JWasm testbed):

Code: [Select]
*** Assemble using JWasm /nologo /c /coff  /Fl /Sn /Fo "TestMasmBasic" ***
Tmp_File.asm: 705 lines, 3 passes, 421 ms, 0 warnings, 0 errors

Exactly the same options as commandline:
Code: [Select]
\Masm32\bin\JWasm /nologo /DSusy=CONSOLE /c /coff  /Fl /Sn /Fo "TestMasmBasic" TestMasmBasic.asm
TestMasmBasic.asm(172) : Error A2163: Empty (null) string
 repargA(58)[MasmBasic.inc]: Macro called from etc etc

Same but jwasm replaced with ML assembles without errors... ::)

And asm.exe chokes with an access violation (somewhere in no man's land, maybe stack corruption) when launched from RichMasm:

Code: [Select]
00401BCC                  ³.  E8 6F2A0100            call 00414640                   ; Àasm.00414640
00401BD1                  ³.  FF35 74854300          push dword ptr [438574]         ; ÚArg1 = 0
00401BD7                  ³.  E8 94AB0100            call 0041C770                   ; Àasm.0041C770
00401BDC                  ³.  FF35 74854300          push dword ptr [438574]         ; ÚArg1 = 0
00401BE2                  ³.  E8 B9FBFFFF            call 004017A0                   ; Àasm.004017A0
...
004017A0                  Ú$  55                     push ebp                        ; asm.004017A0(guessed Arg1)
004017A1                  ³.  8BEC                   mov ebp, esp
004017A3                  ³.  837D 08 00             cmp dword ptr [ebp+8], 0
004017A7                  ³. 75 27                  jne short 004017D0
004017A9                  ³.  E8 3BFFFFFF            call 004016E9
...
0040171D                  ³.  52                     ³push edx                       ; ÚArg3 = 5
0040171E                  ³.  56                     ³push esi                       ; ³Arg2
0040171F                  ³.  50                     ³push eax                       ; ³Arg1
00401720                  ³.  E8 2BD30200            ³call 0042EA50                  ; Àasm.0042EA50
00401725                  ³.  C64402 FF 00           ³mov byte ptr [eax+edx-1], 0
0040172A                  ³.  43                     ³inc ebx
0040172B                  ³.  8BF0                   ³mov esi, eax
0040172D                  ³>  6A 00                  ³push 0                         ; ÚArg2 = 0
0040172F                  ³.  56                     ³push esi                       ; ³Arg1
00401730                  ³.  E8 8BD20200            ³call 0042E9C0                  ; Àasm.0042E9C0
00401735                  ³.  85C0                   ³test eax, eax
00401737                  ³. 75 10                  ³jnz short 00401749
00401739                  ³.  56                     ³push esi
0040173A                  ³.  68 C0000000            ³push 0C0
0040173F                  ³.  E8 08FBFFFF            ³call 0040124C
00401744                  ³.  83C4 08                ³add esp, 8
00401747                  ³. EB 39                  ³jmp short 00401782
00401749                  ³>  56                     ³push esi                       ; ÚArg1
0040174A                  ³.  E8 3DB30200            ³call 0042CA8C                  ; Àasm.0042CA8C
0040174F                  ³.  85C0                   ³test eax, eax
00401751                  ³. 75 0A                  ³jnz short 0040175D
00401753                  ³.  56                     ³push esi                       ; ÚArg1
00401754                  ³.  E8 ABB50200            ³call 0042CD04                  ; Àasm.0042CD04
00401759                  ³.  C640 10 0A             ³mov byte ptr [eax+10], 0A
0040175D                  ³>  8078 10 0A             ³cmp byte ptr [eax+10], 0A
00401761                  ³. 74 0D                  ³je short 00401770
00401763                  ³.  56                     ³push esi
00401764                  ³.  6A 28                  ³push 28
00401766                  ³.  E8 E1FAFFFF            ³call 0040124C
0040176B                  ³.  83C4 08                ³add esp, 8
0040176E                  ³. EB 12                  ³jmp short 00401782
00401770                  ³>  66:8348 12 22          ³or word ptr [eax+12], 0022
00401775                  ³.  8958 08                ³mov [eax+8], ebx
00401778                  ³.  8B3F                   ³mov edi, [edi]
0040177A                  ³>  85FF                   +test edi, edi
0040177C                  ³. 0F85 75FFFFFF          Àjnz 004016F7
00401782                  ³>  5B                     pop ebx
00401783                  ³.  5F                     pop edi
00401784                  ³.  5E                     pop esi
00401785                  À.  C3                     retn  <<<<<< returns to no man's land,

At the retn, stack is fddc instead of fde4. The culprit seems the /DSusy=CONSOLE option; when I eliminate it, stack looks fine and asm.exe terminates normally but with errors
tmp_file.asm(348) : Error A2139: String or text literal too long
tmp_file.asm(350) : Fatal error A1089: Out of Memory

So apart from the memory problem, it has a problem with handling of the /D option, which sets off the stack. When I correct the stack manually back to fde4, it terminates normally.

How did you do the conversion? Compiling with C, but linking in selected asm routines as *.obj or *.lib files?
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2015, 01:06:31 AM
I added some more probing to string creation so the .if issue is now gone. The memory issue is also fixed with dynamic alloc. The error output is also fixed.

The stack jump table needs a fixup, so the MasmBasic test provide a good testcase for that. The startup modules needs to be rewritten to set the stack limit for the jumps to create an exception. There is currently no test done there:
Code: [Select]
setjmp PROC
mov eax,[esp+4]
mov [eax].J_EBP,ebp
mov [eax].J_EBX,ebx
mov [eax].J_EDI,edi
mov [eax].J_ESI,esi
mov [eax].J_ESP,esp
mov [eax].J_EDX,edx
mov [eax].J_ECX,ecx
mov ecx,[esp]
mov [eax].J_EIP,ecx
mov ecx,[eax].J_ECX
xor eax,eax
ret
setjmp ENDP

ASSUME edx: PTR S_JMP

longjmp PROC
mov edx,[esp+4]
mov eax,[esp+8]
mov ecx,[edx].J_ECX
mov ebp,[edx].J_EBP
mov ebx,[edx].J_EBX
mov edi,[edx].J_EDI
mov esi,[edx].J_ESI
mov esp,[edx].J_ESP
push [edx].J_EIP
mov edx,[edx].J_EDX
ret 4
longjmp ENDP
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2015, 02:05:38 AM
Code: [Select]
Lower$ macro txIn
  INSTR <ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ>, <arg>

--> p ="ÄÖÜ>, <arg>"

    for( p = line; *p != NULLC; ) {
if ( isdigit( *p) ) {

'Ä' was a digit here..
Code: [Select]
#define isdigit(c)  (__ctype[(c) + 1] & _DIGIT)
--
#define isdigit(c)  (__ctype[(unsigned char)(c) + 1] & _DIGIT)

Still some strange error messages: (JWASM/ASM)
Code: [Select]
## psapi included
mTest.asm: 704 lines, 1 passes, 406 ms, 0 warnings, 7 errors
--
## psapi included
mtest.asm(347) : Error A2139: String or text literal too long
mtest.asm: 704 lines, 1 passes, 1 ms, 0 warnings, 8 errors

from masm 9.00
Code: [Select]
Assembling: mtest.asm
mtest.asm(153) : error A2070:invalid instruction operands
 MbNext(16): Macro Called From
  mtest.asm(153): Main Line Code
mtest.asm(157) : error A2070:invalid instruction operands
 MbNext(16): Macro Called From
  mtest.asm(157): Main Line Code
## psapi included
mtest.asm(152) : error A2050:real or BCD number not allowed
 MbFor(13): Macro Called From
  mtest.asm(152): Main Line Code
mtest.asm(152) : error A2050:real or BCD number not allowed
 MbFor(23): Macro Called From
  mtest.asm(152): Main Line Code
mtest.asm(152) : error A2022:instruction operands must be the same size
 MbFor(25): Macro Called From
  mtest.asm(152): Main Line Code
mtest.asm(156) : error A2050:real or BCD number not allowed
 MbFor(9): Macro Called From
  mtest.asm(156): Main Line Code
mtest.asm(156) : error A2050:real or BCD number not allowed
 MbFor(10): Macro Called From
  mtest.asm(156): Main Line Code
mtest.asm(156) : error A2050:real or BCD number not allowed
 MbFor(23): Macro Called From
  mtest.asm(156): Main Line Code
mtest.asm(156) : error A2022:instruction operands must be the same size
 MbFor(25): Macro Called From
  mtest.asm(156): Main Line Code

Quote
So apart from the memory problem, it has a problem with handling of the /D option, which sets off the stack. When I correct the stack manually back to fde4, it terminates normally.

I found the proc:
Code: [Select]
add_cmdline_tmacros PROC USES esi edi ebx
;
; no arguments and no locals, so no stack frame
;
mov edi,Options.queues[OPTQ_MACRO*4]
.while edi
    .else
mov    edx,ebx
sub    edx,esi
inc    edx
invoke alloca,edx  ; <<< sub esp,ebx
invoke memcpy,eax,esi,edx
mov    BYTE PTR [eax+edx-1],0
; boom..
ret
add_cmdline_tmacros ENDP

well, new test case for the quoted strings and memory issue added...
Title: Re: High Level Language in MASM
Post by: jj2007 on September 04, 2015, 03:04:34 AM
well, new test case for the quoted strings and memory issue added...

The exceptions are gone, but TestMasmBasic.asm still throws many error messages of the 'string literal too long' type... and no workaround.

In contrast, most if not all examples in \Masm32\MasmBasic\Res\MbSnippets.asc work just fine when launched from RichMasm :t
Title: Re: High Level Language in MASM
Post by: nidud on September 04, 2015, 04:08:58 AM
The jump routine basically jumps into lala-land and consumes as much stack and memory it can get its hands on. When trouble occurre, which usually happens when the nesting level gets to deep, the stack and IP is reset: it jumps back.

In this process, depending on how the stack probing is done, ESP may be used directly. This is debated up-tread (I think) with regards to exceptions in the alloca() function. If ESP is "off" when this happens all pending error messages are suppressed and the assembler just continues as nothing happened.

Well, this is just a theory, but I assume there are some real errors in the test code that generate exceptions, and depending on how this is handled they may just be suppressed and thereby being camouflaged by the IDE.
Title: Re: High Level Language in MASM
Post by: nidud on September 10, 2015, 03:49:06 AM
Ok, new a new test version.

The name ASM.EXE seems to also be some sort of virus, so it’s back to ASMC again.

The error messages and text output have now been rewritten to emulate MASM. This means that the error and warning ID’s correspond to the numbers used by ML. The command line arguments are also changed, so the warning level is from /W0..3 like MASM.

Error messages without a corresponding ID in MASM have been moved as follow:
Code: [Select]
1. Fatal errors

   MASM: A1000..A1901

2. Nonfatal errors

   MASM: A2002..A2217
   ASMC: A3000..A3018

3. Warnings

   MASM: A4003..A4910
   ASMC: A8000..A8020
   MASM: A6003..A6004 - switch /W3
   ASMC: A7000..A7007 - switch /W3

The error output for the MasmBasic test is now equal to JWASM except new ID’s:
Code: [Select]
Doszip Macro Assembler Version 2.14, BETA  09/09/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: mtest.asm
mtest.asm(151) : error A2206: missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  mtest.asm(151): Main line code
mtest.asm(151) : error A2022: instruction operands must be the same size : 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  mtest.asm(151): Main line code
mtest.asm(153) : error A2070: invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  mtest.asm(153): Main line code
mtest.asm(155) : error A2206: missing operator in expression
 MbFor(60)[MasmBasic.inc]: Macro called from
  mtest.asm(155): Main line code
mtest.asm(155) : error A2022: instruction operands must be the same size : 10 - 4
 MbFor(138)[MasmBasic.inc]: Macro called from
  mtest.asm(155): Main line code
mtest.asm(157) : error A2070: invalid instruction operands
 MbNext(15)[MasmBasic.inc]: Macro called from
  mtest.asm(157): Main line code
mtest.asm(172) : error A2047: empty (null) string
 repargA(58)[MasmBasic.inc]: Macro called from
  PushString(81)[MasmBasic.inc]: Macro called from
   MacroLoop(2): iteration 1: Macro called from
    Print(37)[MasmBasic.inc]: Macro called from
     mtest.asm(172): Main line code
## psapi included
Note also the missing last line, so there is less output now. The jump code is also removed as a result of this. The output from JWASM will then be different:
Code: [Select]
..\aso\ABS1.ASO(13) : Error A2228: Invalid operand for SEG:    0
..\aso\ABS1.ASO(16) : Error A2228: Invalid operand for LENGTH: 0
..\aso\ABS1.ASO(17) : Error A2228: Invalid operand for SIZE:   0
..\aso\ABS1.ASO(18) : Error A2228: Invalid operand for LENGTHOF: 0
..\aso\ABS1.ASO(19) : Error A2228: Invalid operand for SIZEOF: 0
..\aso\ABS1.ASO(21) : Error A2228: Invalid operand for SEG: bx
..\aso\ABS1.ASO(22) : Error A2228: Invalid operand for OFFSET: bx
..\aso\ABS1.ASO(23) : Error A2228: Invalid operand for LENGTH: bx
..\aso\ABS1.ASO(24) : Error A2228: Invalid operand for SIZE: bx
..\aso\ABS1.ASO(25) : Error A2228: Invalid operand for LENGTHOF: bx
..\aso\ABS1.ASO(26) : Error A2228: Invalid operand for SIZEOF: bx
..\aso\ABS1.ASO(27) : Error A2228: Invalid operand for HIGH: bx
..\aso\ABS1.ASO(28) : Error A2228: Invalid operand for LOW: bx
..\aso\ABS1.ASO(29) : Error A2228: Invalid operand for HIGHWORD: bx
..\aso\ABS1.ASO(30) : Error A2228: Invalid operand for LOWWORD: bx
..\aso\ABS1.ASO(32) : Error A2228: Invalid operand for SEG:    [bx]
..\aso\ABS1.ASO(33) : Error A2228: Invalid operand for OFFSET: [bx]
..\aso\ABS1.ASO(34) : Error A2228: Invalid operand for LENGTH: [bx]
..\aso\ABS1.ASO(35) : Error A2228: Invalid operand for SIZE:   [bx]
..\aso\ABS1.ASO(36) : Error A2228: Invalid operand for LENGTHOF: [bx]
..\aso\ABS1.ASO(37) : Error A2228: Invalid operand for SIZEOF: [bx]
..\aso\ABS1.ASO(38) : Error A2228: Invalid operand for HIGH:   [bx]
..\aso\ABS1.ASO(39) : Error A2228: Invalid operand for LOW:    [bx]
..\aso\ABS1.ASO(40) : Error A2228: Invalid operand for HIGHWORD: [bx]
..\aso\ABS1.ASO(41) : Error A2228: Invalid operand for LOWWORD:  [bx]
..\aso\ABS1.ASO(45) : Error A2232: Expected data label
..\aso\ABS1.ASO(46) : Error A2232: Expected data label
..\aso\ABS1.ASO(47) : Error A2232: Expected data label
..\aso\ABS1.ASO(48) : Error A2232: Expected data label
..\aso\ABS1.ASO(51) : Error A2228: Invalid operand for HIGHWORD: _TEXT
ASMC MASM-style output:
Code: [Select]
..\aso\ABS1.ASO(13) : error A2094: operand must be relocatable
..\aso\ABS1.ASO(16) : error A2009: syntax error in expression
..\aso\ABS1.ASO(17) : error A2009: syntax error in expression
..\aso\ABS1.ASO(18) : error A2009: syntax error in expression
..\aso\ABS1.ASO(19) : error A2009: syntax error in expression
..\aso\ABS1.ASO(21) : error A2094: operand must be relocatable
..\aso\ABS1.ASO(22) : error A2032: invalid use of register
..\aso\ABS1.ASO(23) : error A2009: syntax error in expression
..\aso\ABS1.ASO(24) : error A2009: syntax error in expression
..\aso\ABS1.ASO(25) : error A2009: syntax error in expression
..\aso\ABS1.ASO(26) : error A2009: syntax error in expression
..\aso\ABS1.ASO(27) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(28) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(29) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(30) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(32) : error A2094: operand must be relocatable
..\aso\ABS1.ASO(33) : error A2098: invalid operand for OFFSET
..\aso\ABS1.ASO(34) : error A2081: missing operand after unary operator
..\aso\ABS1.ASO(35) : error A2081: missing operand after unary operator
..\aso\ABS1.ASO(36) : error A2081: missing operand after unary operator
..\aso\ABS1.ASO(37) : error A2081: missing operand after unary operator
..\aso\ABS1.ASO(38) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(39) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(40) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(41) : error A2105: HIGH and LOW require immediate operands
..\aso\ABS1.ASO(45) : error A2143: expected data label
..\aso\ABS1.ASO(46) : error A2143: expected data label
..\aso\ABS1.ASO(47) : error A2143: expected data label
..\aso\ABS1.ASO(48) : error A2143: expected data label
..\aso\ABS1.ASO(51) : error A2105: HIGH and LOW require immediate operands

The C-stack option is now an option:
Code: [Select]
.386
.model flat, stdcall
.code

OPTION CSTACK: 1

cstack PROC USES esi edi ebx arg
sub esp,arg
ret
cstack ENDP

OPTION CSTACK: 0

astack PROC USES esi edi ebx arg
sub esp,arg
ret
astack ENDP

END

Generated code:
Code: [Select]
_cstack@4 PROC NEAR
        push    esi                                     ; 0000 _ 56
        push    edi                                     ; 0001 _ 57
        push    ebx                                     ; 0002 _ 53
        push    ebp                                     ; 0003 _ 55
        mov     ebp, esp                                ; 0004 _ 8B. EC
        sub     esp, dword ptr [ebp+14H]                ; 0006 _ 2B. 65, 14
        leave                                           ; 0009 _ C9
        pop     ebx                                     ; 000A _ 5B
        pop     edi                                     ; 000B _ 5F
        pop     esi                                     ; 000C _ 5E
        ret     4                                       ; 000D _ C2, 0004
_cstack@4 ENDP

_astack@4 PROC NEAR
        push    ebp                                     ; 0010 _ 55
        mov     ebp, esp                                ; 0011 _ 8B. EC
        push    esi                                     ; 0013 _ 56
        push    edi                                     ; 0014 _ 57
        push    ebx                                     ; 0015 _ 53
        sub     esp, dword ptr [ebp+8H]                 ; 0016 _ 2B. 65, 08
        pop     ebx                                     ; 0019 _ 5B
        pop     edi                                     ; 001A _ 5F
        pop     esi                                     ; 001B _ 5E
        leave                                           ; 001C _ C9
        ret     4                                       ; 001D _ C2, 0004
_astack@4 ENDP

The long-line message was also a bug in the Tokenizer so this is also rewritten in addition to converting numbers, so this needs some testing. The code used is a rewrite of myatoi128() written by a man whose thrill is gone (https://www.youtube.com/watch?v=FMEzFgCLv8c), currently hanging on a vibrating steel wire  :P
Code: [Select]
_atoow PROC USES esi edi ebx dst, src, radix, bsize

mov esi,src
mov edx,dst
mov ebx,radix
mov edi,bsize

xor eax,eax
mov [edx],eax
mov [edx+4],eax
mov [edx+8],eax
mov [edx+12],eax

cmp ebx,10
je radix_10
jb do_slow
cmp edi,16 ; default to HEX DWORD
ja do_slow

radix_16:
xor edx,edx
xor ecx,ecx
cmp edi,8
ja radix_16_QWORD

ALIGN 4
radix_16_DWORD: ; FFFFFFFF = 8
mov al,[esi]
add esi,1
and eax,not 30h
bt eax,6
sbb ebx,ebx
and ebx,55
sub eax,ebx
shl ecx,4
add ecx,eax
dec edi
jnz radix_16_DWORD
jmp done8

ALIGN 4
radix_16_QWORD: ; FFFFFFFFFFFFFFFF = 16
mov al,[esi]
add esi,1
and eax,not 30h
bt eax,6
sbb ebx,ebx
and ebx,55
sub eax,ebx
shld edx,ecx,4
shl ecx,4
add ecx,eax
adc edx,0
dec edi
jnz radix_16_QWORD
jmp done8

ALIGN 4
radix_10:
cmp edi,20
ja do_slow
xor edx,edx
xor ecx,ecx
mov cl,[esi]
add esi,1
sub cl,'0'
cmp edi,10
ja radix_10_QWORD

ALIGN 4
radix_10_DWORD: ; FFFFFFFF - 4294967295 = 10
dec edi
jz done8
mov al,[esi]
add esi,1
sub al,'0'
lea ebx,[ecx*8+eax]
lea ecx,[ecx*2+ebx]
jmp radix_10_DWORD

ALIGN 4
radix_10_QWORD: ; FFFFFFFFFFFFFFFF - 18446744073709551615 = 20
dec bsize
jz done8
mov al,[esi]
add esi,1
sub al,'0'
mov ebx,edx
mov edi,ecx
shld edx,ecx,3
shl ecx,3
add ecx,edi
adc edx,ebx
add ecx,edi
adc edx,ebx
add ecx,eax
adc edx,0
jmp radix_10_QWORD

ALIGN 4
do_slow:
mov edi,edx
ALIGN 4
do:
mov al,[esi]
and eax,not 30h
bt eax,6
sbb ecx,ecx
and ecx,55
sub eax,ecx
mov ecx,8

ALIGN 4
@@:
movzx edx,WORD PTR [edi]
imul edx,ebx
add eax,edx
mov [edi],ax
add edi,2
shr eax,16
dec ecx
jnz @B
sub edi,16
add esi,1
dec bsize
jnz do
mov eax,dst
jmp toend

ALIGN 4
done8:
mov eax,dst
mov [eax],ecx
mov [eax+4],edx
toend:
ret
_atoow ENDP

The memory functions are also changed a bit from using 512 kB blocks to using 4K (one page) blocks. This seems faster at least for small files, but I’m currently using the regress test for benchmarks so this may change. However, the Masm Basic test also seems faster using this approach so there may be some cache benefits using small blocks.
Title: Re: High Level Language in MASM
Post by: jj2007 on September 10, 2015, 04:45:16 AM
the Masm Basic test also seems faster

It's roughly 30% faster than JWasm :t

Still, it's a mystery why it throws errors from the command line. From RichMasm, hitting F6 works just fine.
To test different assemblers, RichMasm checks line 6 of TestMasmBasic.asm
; OxPT_Assembler     mlv10   ; the x disactivates the option
; OPT_Assembler     asmc   
; OPT_Assembler     JWasm
etc - the last valid OPT_ is being taken.

The library source itself throws several errors, inter alia it doesn't like the equate
Code: [Select]
signed equ sdword ptr

J:\Masm32\MasmBasic\libtmpAB.asm(1926) : error A2008: syntax error : addr

There is no single addr in that file, except as part of comments.

Code: [Select]
  xchg eax, edx ; ret address to eax
  and dword ptr [edi], 0 ; set delimiter in case no element found
  .if sdword ptr ebx<=0 ; ebx>0 = no element found
.if esi>eax
mov dl, [esi-1] ; edx now trash reg
.if !dl || (dl=="," && dword ptr [esp+4]==MbFlagCsv) ######## line 1926, no addr here! #########

This one is also weird:
*** Assemble using asmc /nologo /c /coff  /Fl /Sn /Fo "MasmBasic" ***
 Assembling: tmp_file.asm
\masm32\include\windows.inc(26889) : fatal error A1000: cannot open file : winextra.inc


Code: [Select]
;;;; end gdiplus

include winextra.inc

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; It is not recomended that WINDOWS.INC be modified but if you need to add

Might be a problem with a wrongly set current folder.
Title: Re: High Level Language in MASM
Post by: nidud on September 10, 2015, 05:45:06 AM
Quote
Still, it's a mystery why it throws errors from the command line. From RichMasm, hitting F6 works just fine.

What does that mean? Is a valid .OBJ file produced? No .ERR file? If so then some switches or other additional settings must be added?

Quote
Might be a problem with a wrongly set current folder.

In the base file:
Code: [Select]
include \masm32\include\masm32rt.incmasm32rt.inc:
Code: [Select]
      include \masm32\include\windows.inc       ; main windows include file
      include \masm32\include\masm32.inc        ; masm32 library include
the end of windows.inc:
Code: [Select]
;;;; end gdiplus

include winextra.inc

The path (\masm32\include) is saved so this should work, and it does from the command line. If this only happens when using ASMC and not with JWASM it's a bug.

Quote
J:\Masm32\MasmBasic\libtmpAB.asm(1926) : error A2008: syntax error : addr

The "," is converted to a string me think, same as the .if issue above. Need some more probing..
Title: Re: High Level Language in MASM
Post by: jj2007 on September 10, 2015, 06:34:17 AM
I've found a trick to make it assemble from the command line:
Code: [Select]
J:\Masm32\MasmBasic>..\bin\asmc.exe /c /coff /Fl /Fo "TestMbCl" tmp_file.asm
Doszip Macro Assembler Version 2.14, BETA  09/09/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: tmp_file.asm
ASMC : fatal error A1901: Internal Assembler Error

J:\Masm32\MasmBasic>..\bin\asmc.exe /c /coff /Fl /Sn /Fo "TestMbCl" tmp_file.asm
Doszip Macro Assembler Version 2.14, BETA  09/09/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: tmp_file.asm

J:\Masm32\MasmBasic>

The "good" command line has the /Sn option (Suppress symbol-table listing).
Title: Re: High Level Language in MASM
Post by: nidud on September 10, 2015, 07:50:03 AM
Applied a new test to make sure there is a proc in front of the quoted text so the test code will now compile, but it still may break existing code.
Code: [Select]
.if fopen("file.txt","rt")
.elseif fopen("file.txt","rt")
.while fopen("file.txt","rt")
invoke fopen,"file.txt","rt"

The three first ones are safe given use of proc's in HLL is not allowed, so this will not break existing code. The last one however is allowed and arguments may also be quoted text used as numbers.

Code: [Select]
invoke strchr,ebx,"."

So, what to do. The only safe method seems to be excluding invoke, or maybe add an option for extend usage inside a scope.

Code: [Select]
ASMC : fatal error A1901: Internal Assembler Error
It's a memory problem. I reduced the memory used outside the assembler to a minimum (0x20000) but the stdio functions needs a bit more. I increased it to 0x40000 and this produced a 8M list file using /Fl /Sg from the MB test.

The content seems ok, but there is a 02: label added in the end for some reason.
Title: Re: High Level Language in MASM
Post by: jj2007 on September 10, 2015, 10:49:35 AM
Still that problem...:
Code: [Select]
\masm32\include\windows.inc(26889) : fatal error A1000: cannot open file : winextra.inc
\masm32\include\windows.inc(26889) : warning A4910: cannot open file : tmp_file.err

Even if I supply the full path to winextra, it doesn't work.
Title: Re: High Level Language in MASM
Post by: nidud on September 10, 2015, 12:34:04 PM
Appear to be something wrong with the last build. Not sure what that was but the IO functions failed for some reason. The list problem is now solved so that may be the problem. I also end up in a recursive loop now where the last build assemble the next one.

Well, if this version fails I need a test case, but the last error suggests an IO failure so I will assume it’s the same problem.
Title: Re: High Level Language in MASM
Post by: jj2007 on September 10, 2015, 06:39:15 PM
Mixed news:
- I managed to build the whole library by eliminating some equates and macros, in particular
signed aka sdword ptr: .While signed ebx>=...
Mirror$: .if eax==Mirror$("USE:")
- it still can't find WinExtra.inc :(

; v v v delete x to choose a specific assembler
; OPT_Assembler        mlv615      ; 40.5kB, 827 ms
; OxPT_Assembler       mlv10       ; 40.5kB, 827 ms
; OxPT_Assembler       JWasm       ; 40.0kB, 484 ms
; OxPT_Assembler       asmc        ; 40.0kB, 359 ms


Speed-wise, I like it a lot :t
Title: Re: High Level Language in MASM
Post by: nidud on September 11, 2015, 03:44:41 AM
The problem here is that this works:
Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc

.code

.if eax==Mirror$("USE:")
    nop
.endif

END

Without a specific test case it’s difficult to figure out what’s wrong. The include file is found, so it’s not an IO problem. I also tested this in a 27M-source file (200K lines) and this also works so I doubt it’s a memory problem.

I compiled a version with some additional output in the include function with file name and system error so maybe that will give some more information.

This however is a bug:
Code: [Select]
signed equ sdword ptr

.while signed ebx==0
   nop
.endw

.while and .elseif are not expanded before the offset of the end-labels are sorted out. Some error messages needs to be suppressed before this expansion, so I have to look into that.
Title: Re: High Level Language in MASM
Post by: HSE on September 11, 2015, 10:09:37 AM
Work very well with my mess of ObjAsm32 and SmplMath :t

Regards. HSE.

PD: a little frightening at first the no error messages,   :shock:

Title: Re: High Level Language in MASM
Post by: nidud on September 11, 2015, 01:24:38 PM
Work very well with my mess of ObjAsm32 and SmplMath :t

 :biggrin:

Keep in mind it’s just a test-bed at the moment and their some experimental coding involved. However it seems to be somewhat stable now but it probably needs a few adjustments.

There was some mix-up with the /Zp[n] switch to set alignment. This was needed to synchronize the C-structs with the assembly implementation so this is now corrected. The .while signed bug is also fixed.

As mention above invoke may fail if quoted strings are used as a number-argument not intended to be converted. The switch /cc is on as default, and this will now include all additional features like quoted strings, C-stack, and the ability of using proc's and labels in HLL code.

If you rename the .EXE to ML or JWASM this switch will not be set. In that case these features may be turned on and off with the option cstack.
Title: Re: High Level Language in MASM
Post by: qWord on September 12, 2015, 02:27:23 AM
If you would fix the broken HIGHWORD operator (highword_op@expreval.c), you test the speed improvement of following macro code to calculate 1000!:
Code: [Select]
option casemap:none
include real_math.inc

    MREAL x = 1, y = 1, cOne = 1
    MREAL_TEST_INEXACT = -1
    px = 1
    py = 1
    cntr = 0
    WHILE cntr NE 1000 ; max. ca. 1700
        MR_XMUL x,x,y,%px+py,px,py
        IF MREAL_INEXACT
            .err <this should not happen>
            EXITM
        ELSE
            px = MR_GET_N_SIGNIFICANT_WORDS(x,%px+py)
            MR_ADD y,y,cOne,,py
            cntr = cntr + 1
        ENDIF
    ENDM
    %echo Factorial @CatStr(%cntr) calculated.
    MR_RAW_OUT x,px
    %echo precision WORDs: @CatStr(%px)
    %echo x = ca. MR_TO_DECIMAL(x,50,px)

end
real_math.inc (http://masm32.com/board/index.php?action=dlattach;topic=3225.0;attach=3069)
Title: Re: High Level Language in MASM
Post by: nidud on September 12, 2015, 04:25:19 AM
The output from the (time-consuming) test:
Code: [Select]
hw.asm(23) : error A2052: forced error : this should not happen
Code: [Select]
static int highword_op( int oper, struct expr *opnd1, struct expr *opnd2, struct asym *sym, char *name )
{
    TokenAssign( opnd1, opnd2 );
    if ( opnd2->kind == EXPR_ADDR && opnd2->instr != T_SEG ) {
opnd1->instr = T_HIGHWORD;
opnd1->mem_type = MT_EMPTY;
    }
    opnd1->value = opnd1->value >> 16;
    return( NOT_ERROR );
}

I changed this to:
Code: [Select]
    opnd1->value = (opnd1->value >> 16) & 0xFFFF;

The result is now:
Code: [Select]
precision WORDs: 471
x = ca. 4.0238726007709377354370243392300398571937486421071E+2567

There are a few other issues at the moment. The error limit message is currently recursive, so if you insist on feeding it erroneous code make sure there are less then hundred of them.
Title: Re: High Level Language in MASM
Post by: nidud on September 12, 2015, 04:36:00 AM
I applied the changes also to JWASM

ASMC:
Code: [Select]
ClockTicks: 10109JWASM:
Code: [Select]
ClockTicks: 16437
Title: Re: High Level Language in MASM
Post by: nidud on September 12, 2015, 04:41:28 AM
ML 9:
Code: [Select]
ClockTicks: 11235
Title: Re: High Level Language in MASM
Post by: nidud on September 15, 2015, 01:51:49 AM
High level parsing:
Code: [Select]
.hll eax==macro(args) || eax==macro(args) ...

ASMC: [.hll] [eax] [==] [macro] [(] [args] [)] [||] [eax] [==] [macro] [(] [args] [)] ...
JWASM: [.hll] [eax] [==] [macro] [(] [args] [)] [||] [eax] [==macro(] [args] [)] ...

The first macro trigger a C-expression switch in case the rest of the line is <literal text>
Code: [Select]
.if @SubStr(<ebx==1 && edi==2, xxx>, 1, 16) ; EXPANS39.ASM

However, this line is different:
Code: [Select]
.hll eax == macro(args) || eax == macro(args) ...

This create some problems given all macros needs to be detected in order to handle them correctly. The high level parsing is for this reason switched off when this is detected with a level 3 warning.

Code: [Select]
option cstack: 0 ; auto off by @CatStr(<, @SubStr(<

enumval = 1
res macro tok, string, type, value, bytval, flags, cpu, sflags
@CatStr(<T_>,@SubStr(<tok>,2)) equ enumval
enumval = enumval + 1
endm

T_NULL equ 0
include special.h
include directve.h
SPECIAL_LAST equ enumval

option cstack: 1 ; reset HLL

There are ways around this but I need to set some logical rules on how to handle the HLL section first.

I fixed some of the bugs pointed out by JJ and QWORD and a few others. I also compile a ASMCERR.TXT file with the MASM/ASMC error numbers.
Title: Re: High Level Language in MASM
Post by: nidud on September 16, 2015, 05:31:07 AM
Small adjustment with large impact:
Code: [Select]
or [ecx].asym.flag,not SFL_ISDEFINED
Should be:
Code: [Select]
and [ecx].asym.flag,not SFL_ISDEFINED

The STDIO functions used was somewhat limited with a _iob[10] table. The standard is 20. Subtracting stdin, stdout, and stderr only 7 free streams is left.

Some probing into the missing include file issue show the return from fopen() was zero. When using the /Fl switch the file-stack may look like this:
Code: [Select]
source _iob[3]
object _iob[4]
list file _iob[5]
MasmBasic.inc _iob[6]
-masm32rt.inc _iob[7]
--windows.inc _iob[8]
---winextra.inc _iob[9]

If no error occur this will work. Adding one more file by creating two include files:
Code: [Select]
Doszip Macro Assembler Version 2.14, BETA  09/14/15
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: test.asm

***********
ASCII build
***********

\masm32\include\windows.inc(26889) : fatal error A1000: cannot open file : winextra.inc
\masm32\include\windows.inc(26889) : warning A4910: cannot open file : test.err
 \masm32\include\windows.inc(26889): Included by
  \masm32\include\masm32rt.inc(38): Included by
   \masm32\include\1.inc(2): Included by
    \masm32\include\0.inc(2): Included by
     test.asm(1): Main line code

This still doesn't explain why it fails in the MasmBasic IDE and work on the command line given there is one file missing (or added), but the error output is at least similar. I increased the file table to 20 so maybe that helps.
Title: Re: High Level Language in MASM
Post by: jj2007 on September 16, 2015, 09:01:19 AM
This still doesn't explain why it fails in the MasmBasic IDE and work on the command line given there is one file missing (or added), but the error output is at least similar. I increased the file table to 20 so maybe that helps.

Great - the MasmBasic library assembles without errors :t

Result for the 17,000 lines of the RichMasm source:

*** Assembling and linking took 561 milliseconds ***

 :t :t :t :t :t
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 16, 2015, 10:09:00 AM
nidud,

works with all my projects now. It's faster and smaller build also. Thanks!, and Congrats :t
Title: Re: High Level Language in MASM
Post by: nidud on September 17, 2015, 11:44:51 PM
 :biggrin:

If it manages to assemble MasmBasic then it’s truly a Macro Assembler  :lol:

I leave the .ZIP file then. The changes below are only high-level stuff.

I’ve implemented recursive parsing for rendering procedures in HLL. This means that a proc may be used as argument in a proc. However, their can only one proc-test in each expression.
Code: [Select]
.if malloc( strlen1( token ) )
    mov edi,eax
    .if !_memicmp( strcpy( eax, token ), ".386", 4 )

As long as the logic of using EAX is reserved this could be nested at any level.
Code: [Select]
.if strcmp( strcat( strcat( strcpy("buf", "a") ,"b" ), "c"), "abc")
    invoke printf, "ASMC : fatal error A1901: Internal Assembler Error\n"
.endif

It’s possible to circumvent this limitation by using macros
Code: [Select]
proc1 macro args
invoke procA,args
mov ebx,eax
exitm <ebx>
endm

proc2 macro args
invoke procB,args
mov edi,eax
exitm <edi>
endm

procC proto :dword

.if proc1(args) || proc2(args) || procC(args)
Well, bit fuzzy but possible.
Title: Re: High Level Language in MASM
Post by: TWell on September 18, 2015, 12:53:42 AM
@ninud
Can you give changes list with each version too?
Title: Re: High Level Language in MASM
Post by: nidud on September 18, 2015, 01:48:28 AM
Hi Twell,

In the .Zip file there is a directory called HLL. There you find a test case for each of the changes made so far. Some bug fixes and other changes are missing but I will try to make change-log file when released.

The major change in this version is that I use my own C-library so I need to make additional code for inline code used by various compilers, in this case Open Watcom and MSVC. In addition to this the alignment of data in C (mostly structs) also have to be synchronized with the assembly code, so there is a lot of fine-tuning involved in the make process.

This means that there are not so many changes made except that it’s a bit faster, smaller, and more MASM compatible than before. In addition to the bug pointed out by QWORD there are two files for the 2.14 version so far:

ASMC214.ASM
Code: [Select]
; ASMC 2.14 -- EQU's not expanded in .while/.elseif

.386
.model flat

signed equ sdword ptr

.code

strlen:

.while signed strlen() < 0
   nop
.endw
.if signed ebx < 0
   nop
.elseif signed ebx < 0
   nop
.endif

END

ASMC214B.ASM
Code: [Select]
; ASMC v2.14 - use proc as argument in HLL proc

.386
.model flat, stdcall
.code

foo proto :DWORD
bar proto :DWORD

.while foo( bar( 1 ) )
    nop
.endw

end

Generated code:

JMP CS0003
CS0002: NOP
CS0003: PUSH 1
CALL _bar@4
PUSH EAX
CALL _foo@4
TEST EAX,EAX
JNZ CS0002
Title: Re: High Level Language in MASM
Post by: jj2007 on September 20, 2015, 08:56:33 PM
it’s a bit faster, smaller, and more MASM compatible than before.

So far it works extremely well with MasmBasic.

What about other major packages, like ObjAsm or SmplMath?

Can we speed up AsmC, e.g. with faster StrLen and Instr() routines?
Recall (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1172) is another candidate, with an even faster version by rrr34159 (http://masm32.com/board/index.php?topic=4057.msg42723#msg42723).
Title: Re: High Level Language in MASM
Post by: qWord on September 21, 2015, 09:00:19 AM
I applied the changes also to JWASM

ASMC:
Code: [Select]
ClockTicks: 10109JWASM:
Code: [Select]
ClockTicks: 16437
ML 9:
Code: [Select]
ClockTicks: 11235
thx, for testing.
Interestingly your optimization currently just push jWasm at ML level (at least for the used code) .

regards
Title: Re: High Level Language in MASM
Post by: nidud on September 22, 2015, 06:58:03 AM
There was a missing argument (/fpc Disallow floating-point instructions) and a bug on passing arguments not found.

The same logic of using a proc as argument is now added to invoke.
Code: [Select]
invoke foo, bar(1, 2), 3

PUSH 2
PUSH 1
CALL _bar@8
PUSH 3
PUSH EAX
CALL _foo@8

.switch, .case, .default, and .endsw added.

Code: [Select]
.switch
.endsw
;-------------------------
jmp @C0001
@C0001:
@C0002:

Code: [Select]
.switch eax
.case 3..7
.endsw
;-------------------------
jmp @C0001
@C0003: jmp @C0002
@C0001: cmp eax,3
jb @F
cmp eax,7
jbe @C0003
@@:
@C0002:

Code: [Select]
.switch al
.case 0Dh
.case 0Ah
    xor eax,eax
    .break
.case '\'
.case '/'
    inc ecx
.default
    mov eax,1
.endsw
;-------------------------
jmp @C0001
@C0003:
@C0004: xor eax,eax
jmp @C0002
@C0005:
@C0006: inc ecx
@C0007: mov eax,1
jmp @C0002
@C0001: cmp al,0Dh
je @C0003
cmp al,0Ah
je @C0004
cmp al,'\'
je @C0005
cmp al,'/'
je @C0006
jmp @C0007
@C0002:
Title: Re: High Level Language in MASM
Post by: jj2007 on September 22, 2015, 09:43:31 AM
Works fine with all my major sources :t
Title: Re: High Level Language in MASM
Post by: nidud on September 23, 2015, 01:46:36 AM
Quote
Can we speed up AsmC, e.g. with faster StrLen and Instr() routines? Recall is another candidate, with an even faster version by rrr34159.

Maybe.

The input is done by fetching one line at the time (re)using small stream buffers so the actual parsing is one line at the time. The tokenizer also shift methods based on flags and types and each of these have a different way of separating tokens.

I tried using the SSE string library but this was no success.
Code: [Select]
SSE 17,483 1,8   17,483   1,8 815814 _strlen@4 (strlen.obj)
386 12,751 1,2   12,751   1,2 815814 _strlen@4 (strlen.obj)
The reason for this may be that the average size of tokens (AL, CMP, WORD) is small. The functions with small overhang will then be faster. I tried the MASM32 StrLen but it’s apparently not page-safe. The MasmBasic Len() works but most of these "fast" versions seems slow on short strings.
Code: [Select]
-- string length 0..9
  1246108 cycles - ( 41) proc_8: 386 1
  1247646 cycles - ( 86) proc_7: 386 4
  1355038 cycles - (673) proc_4: SSE Intel Silvermont
  1401979 cycles - ( 56) proc_6: 386 2
  1507531 cycles - (  0) proc_0: ??? crt_strlen
  1539519 cycles - ( 89) proc_2: 386 4
  1589396 cycles - (105) proc_3: SSE 32
  1627366 cycles - (818) proc_5: SSE Intel Atom
  2221679 cycles - ( 23) proc_1: 386 scasb
  2239869 cycles - (  0) proc_9: ??? MasmBasic Len()
Title: Re: High Level Language in MASM
Post by: nidud on September 28, 2015, 12:04:03 AM
And now a bit faster version:

Code: [Select]
ASMC ClockTicks: 7500
JWASM ClockTicks: 9078  - Open Watcom build
ML-9 ClockTicks: 11281
JWASM ClockTicks: 16563 - MSVC build

The test was done using the math sample provided by QWORD. Note also the difference between the two versions of JWASM.

Some more changes done to the .SWITCH construct.

The basic logic of the switch:
Code: [Select]
switch: arg
jmp start
 case_1:
 case_n:
jmp break
 start:
 continue:
cmp <switch_arg>,<case_arg>
je <case_label>
...
 break:
 endsw:


The first case inserts the jump to start to avoid code generation if empty.

Code: [Select]
.switch eax
;
; no code generated
;
.endsw

A jump to break is inserted above start so no .BREAK is needed for the last case. Note also that .CONTINUE is equal to start.

Code: [Select]
.switch al
  .case 1
.break
  .case 3..7
stosb
;
; fall thru
;
  .default
.break .if !al
lodsb
.continue
;
; break inserted after last case
;
; jmp break
; start:
; cmp al,1
;
.endsw ; break:

A .SWITCH with no arguments will handle the test as a regular HLL expression. No auto-break is then inserted.

Code: [Select]
switch:
jmp start
 case_1:
 case_n:
 start:
 continue:
<regular HLL expression>
Jxx <case_x>
 break:
 endsw:

Code: [Select]
.switch ; no args
  .case al == 1
.break
  .case al >= 3 && al <= 7
stosb
;
; fall thru
;
  .default
.break .if !al
lodsb
;
; no break inserted
;
; start:
; continue:
;
.endsw

So this now works with the standard version:
Code: [Select]
.switch foo( bar( 2 ) )

And this works with the "regular expression" version:
Code: [Select]
  .case foo( bar( 2 ) )

Title: Re: High Level Language in MASM
Post by: jj2007 on September 28, 2015, 02:01:56 AM
And now a bit faster version

About 5% faster than version 17 September for the MasmBasic library, but a bit slower for the RichMasm source.
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 28, 2015, 03:48:00 AM
Hi nidud,

Thanks for your efforts!

It would be useful to have documentation of all the hll capabilities of jwasm, AFAIK it doesn't exist; certainly not in regular jwasm docs. In the jwasm forum some features are documented but most are not. Someday I'll have to look in the jwasm code to find out what's available. In fact, just a post of the relevant tokens in jwasm would be useful (such as .if, etc)

BTW there was a bug in the .if when a macro was used for the condition, I wonder if it's still there

Is watcom usually that much faster? Or is there something unusual about your jwasm changes?

I've been using a previous version of your assembler quite a bit, continues to work fine, when you have a final version please let us know

Quote from: nidud
most of these "fast" versions seems slow on short strings.

- Most "fast" tokenizers (mine, at least) were optimized for particular cases, in the laboratory, and not designed to be fast in general

- I've noticed this is often true of such algos, in "real world" circumstances they may not be so satisfactory. In particular, to memcopy large buffers, rep movsb seems to be as good as anything (as dedndave, hutch and others have said). Only on shorter buffers do you get an advantage with SSE and such "advanced" techniques
Title: Re: High Level Language in MASM
Post by: jj2007 on September 28, 2015, 04:11:28 AM
Most "fast" tokenizers (mine, at least) were optimized for particular cases, in the laboratory, and not designed to be fast in general

Both your and my tokenizers are far ahead of anything similar I've seen so far. What nidud meant was more the Instr() type of algo, which tends to have some overhead. But rep scasb is really slow...
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 28, 2015, 08:45:29 AM
I'm glad to hear our tokenizers hold up well under actual use ... thought nidud said they weren't so fast with short tokens, but guess he's talking about searching for tokens (with instr), or something else. What I said is still true: when making faster routines in the laboratory (in my case at least) we're specifically optimizing for the problem at hand, ignoring all other considerations, since the task is hard (actually more "frustrating", than "hard") enough as it is.

Talking about frustration, zedd151 just spent a day eking out a few cycles with his long-number-adder routine - asks others to test it - for them, it takes longer! I know how he feels - the trap is, optimizations on your own machine often don't apply to other's. Co-operative colleagues testing your work on different computers are vital, if u want it to apply generally.

Agree, rep scasb not particularly useful ... but rep movsb kicks butt at 30030 bytes (prime number segment size), with just 4 lines of code ... ! rep movsd is no faster, at least if there's a tail (i.e. the number of bytes is not divisible by 4)

As long as I'm at it, let me reiterate 2 questions,

- jwasm hll documentation?

- If watcom is so much faster, why does everyone use inferior product VC? Perhaps, same reason C programmers use their inferior product, instead of assembler? :P
Title: Re: High Level Language in MASM
Post by: jj2007 on September 28, 2015, 09:05:22 AM
If watcom is so much faster, why does everyone use inferior product VC?

Willus.com's 2011 Win32/64 C Compiler Benchmarks: (http://www.willus.com/ccomp_benchmark2.shtml?p19)
Quote
Digital Mars ... 2.3X slower than Intel. ... I also want to give a nod to Open Watcom. Although it was not included in the results because it had trouble compiling all of the benchmarks (it is similar in capability and vintage to Digital Mars), ...
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 28, 2015, 09:46:38 AM
Apparently I'm missing something! According to Willus,

- performance advantage of Intel-compiled code over MS: about 13-22% (2011)
- Digital Mars is 2.3X slower than Intel (Intel advantage 127%)
- therefore perf advantage of MS-compiled code over Digital Mars, 100% or more
- Open Watcom similar in capability to Digital Mars
- therefore MS-compiled code twice as fast as Open Watcom.

However,

Quote from: nidud
ASMC   ClockTicks: 7500
JWASM   ClockTicks: 9078  - Open Watcom build
ML-9   ClockTicks: 11281
JWASM   ClockTicks: 16563 - MSVC build

nidud says the opposite: Watcom-compiled jwasm almost twice as fast as MSVC jwasm.

Conclusion: Apparently I'm missing something! QED
Title: Re: High Level Language in MASM
Post by: jj2007 on September 28, 2015, 04:19:05 PM
Apparently I'm missing something!

I fully agree with your conclusion :biggrin:

@nidud: Could you give us two versions based on identical sources but one compiled with Open Watcom, the other with GCC or MS VC? It's time for some timings ;)
Title: Re: High Level Language in MASM
Post by: nidud on September 28, 2015, 07:37:39 PM
Is watcom usually that much faster? Or is there something unusual about your jwasm changes?

Open Watcom optimise good but not that good. The test case written by QWORD is special in the sense that it does not produce any code. Normally most of the time is used on IO operations but this test using only macros use a specific part of the assembler repeatedly.

Normal assembly: Tokenize 1.6%
Code: [Select]
    3156,999  53,5     3156,999  53,5     4151 _osread@12 (osread.obj)
    1457,810  24,7     1458,052  24,7     4470 __osopen@24 (_osopen.obj)
     534,867   9,1     5883,090  99,7        1 _main (_main.obj)
      81,223   1,4       81,223   1,4   268532 _memzero@8 (memzero.obj)
      78,772   1,3     3237,139  54,9   238240 _my_fgets@12 (input.obj)
      58,613   1,0       58,613   1,0     3131 _oswrite@12 (oswrite.obj)
      54,527   0,9       94,688   1,6   291288 _Tokenize@16 (_tokenize.obj)
      37,293   0,6       37,293   0,6   633269 @FindResWord@8 (_memalloc.obj)

Test case: Tokenize 34.2%
Code: [Select]
    2298,455  21,8     3604,708  34,2  8310112 _Tokenize@16 (_tokenize.obj)
    1822,469  17,3     1822,469  17,3 34489871 _SymFind@4 (_symbols.obj)
    1331,330  12,6     1331,330  12,6 29369899 @FindResWord@8 (_memalloc.obj)
     452,406   4,3      973,067   9,2 13335545 _get_operand@16 (expreval.obj)
     390,832   3,7     2156,943  20,5  8994797 _evaluate@20 (expreval.obj)
     387,861   3,7    10484,620  99,6  5621028 _ExpandToken@24 (_expans.obj)
     356,394   3,4      356,394   3,4 15239093 @init_expr@4 (expreval.obj)
     298,620   2,8      298,620   2,8 22893471 @is_expr_item@4 (expreval.obj)

So improvement in the test-case speed may not have large impact on average usage, but it’s a good benchmark for the functions used.

The JWASM versions are built from the same source so the result was a bit strange. I added a few switches to CL and the result are now somewhat within normal range.

Code: [Select]
ASMC ClockTicks: 7297
JWASM ClockTicks: 9172 - Open Watcom
JWASM ClockTicks: 9719 - MSVC: CL /O2 /Ot
/O2 maximize speed
/Ot favor code speed
ML-9 ClockTicks: 11391
Title: Re: High Level Language in MASM
Post by: nidud on September 28, 2015, 08:52:43 PM
@nidud: Could you give us two versions based on identical sources but one compiled with Open Watcom, the other with GCC or MS VC? It's time for some timings ;)

 :biggrin:

here you go

EDIT: jwasm212A.zip removed, jwasm212B.zip added

Changes in 2.12B - 3 Feb 2016
- corrected encodings for 4 AVX instructions:
  - vpermilpd xmm0, xmm1, 1
  - vpermilpd ymm0, ymm1, 1
  - vpermilps xmm0, xmm1, 1
  - vpermilps ymm0, ymm1, 1
Title: Re: High Level Language in MASM
Post by: jj2007 on September 28, 2015, 09:21:34 PM
JWasmVC gives me general failure :(

Besides, I wanted your new asmC, not JWasm.
Title: Re: High Level Language in MASM
Post by: nidud on September 28, 2015, 10:34:06 PM
JWasmVC gives me general failure :(

It depended on some specific import apparently. You may build a version from the 2.12 source and apply the changes above for the HIGHWORD operator. This is needed for the math test.

The version 2.12A includes two bug fixes in addition to the one above. The first is the stack problems in invoke mention up tread.
Code: [Select]
; JWASM v2.12 - invoke.c
; stack error on types not aligned 4: 6, 10, 14, ...

foo proto c :VARARG

num dt 3.14159265358979323846264338327

invoke foo, num

The second is a HLL issue in version 2.11 and 2.12
Code: [Select]
; JWASM 2.11/12 hll.c -- missing label

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

Quote
Besides, I wanted your new asmC, not JWasm.

Well, this is the latest build. I removed a few of the DIV instructions used to access [I % TABLE_SIZE]. This reduced the math test from 7500 to 7250. That’s more or less the difference between this version and the last one, so I don’t expect much change.

EDIT:
Converted a few strategic invokes to jumps, so now it’s down to 6800
Title: Re: High Level Language in MASM
Post by: nidud on September 29, 2015, 12:37:16 AM
It would be useful to have documentation of all the hll capabilities of jwasm, AFAIK it doesn't exist; certainly not in regular jwasm docs. In the jwasm forum some features are documented but most are not. Someday I'll have to look in the jwasm code to find out what's available. In fact, just a post of the relevant tokens in jwasm would be useful (such as .if, etc)

It's the same as in MASM

Conditional Control Flow Directives in MASM

.BREAK [.IF <expression>]
.CONTINUE [.IF <expression>]
.ELSE
.ELSEIF <expression>
.ENDIF
.ENDW
.IF <expression>
.REPEAT
.UNTIL <expression>
.UNTILCXZ
.WHILE <expression>

Added in ASMC

.SWITCH
.SWITCH <expression>
.CASE <value>
.CASE <expression>
.DEFAULT
.ENDSW
Title: Re: High Level Language in MASM
Post by: jj2007 on September 29, 2015, 01:14:45 AM
Converted a few strategic invokes to jumps, so now it’s down to 6800

RichMasm assembles with asmc in less than 600 ms on my i5, as compared to 680 for JWasm and 1230 for ML :t
Title: Re: High Level Language in MASM
Post by: rrr314159 on September 29, 2015, 04:35:03 AM
@nidud,

thanks for listing the new non-ML control flow directives ... didn't realize jwasm and asmc were two different progs (thought asmc was jwasm with some parts coded in assembler), guess I understand it now
Title: Re: High Level Language in MASM
Post by: jj2007 on September 30, 2015, 12:38:54 AM
I've stumbled over a problem: MasmBasic.lib behaves differently when assembled with asmc. And unfortunately it breaks code. Attached two versions of the same dll, as dll and disassembled, plus source. I'am afraid right now I can't dig into this :(
Title: Re: High Level Language in MASM
Post by: nidud on September 30, 2015, 04:08:58 AM
I get more or less the same output from JWASM and ASMC.
The only thing that seems to differ is the use of TEST.

Code: [Select]
JWASM:
        call    _InstrCi@16                             ; 1155 _ E8, 00000000(rel)
        and     edx, edx                                ; 115A _ 23. D2
jz ?_082 ; 115C _ 74, 68
ASMC:
        call    _InstrCi@16                             ; 1155 _ E8, 00000000(rel)
        test    edx, edx                                ; 115A _ 85. D2
        jz      ?_082                                   ; 115C _ 74, 68
Title: Re: High Level Language in MASM
Post by: jj2007 on September 30, 2015, 12:33:23 PM
test vs or vs and doesn't change much :(

The real issue could be the handling of uses, but I am just guessing now. I hope I'll find the time...
Title: Re: High Level Language in MASM
Post by: nidud on September 30, 2015, 11:36:18 PM
Quote
And unfortunately it breaks code

Yes, there is still the issue with INVOKE and "quoted strings" as debated up tread. I found one of these cases (I think) in the mldis.txt file:

Code: [Select]
1000320B ³.  6A 4F        push 4F              ; ÚArg3 = 4F
1000320D ³.  50           push eax             ; ³Arg2
1000320E ³.  6A 09   push 9        ; ³Arg1 = 9
10003210 ³.  E8 CEF2FFFF  call 100024E3        ; ÀCompileBasFilesML.100024E3

Assuming something like this:
Code: [Select]
invoke foo, 9, eax, "O"

If the -cc flag is set this will turn into a string (acdis.txt):
Code: [Select]
10003211 ³.  68 A8A20010  push offset 1000A2A8 ; ÚArg3 = CompileBasFilesAC.1000A2A8
10003216 ³.  50   push eax        ; ³Arg2
10003217 ³.  6A 09        push 9               ; ³Arg1 = 9
10003219 ³.  E8 C7F2FFFF  call 100024E5        ; ÀCompileBasFilesAC.100024E5

Normally including MasmBasic.inc will turn off the C-parsing, but from the acdis.txt it seems to be on. Currently the only options are to switch off the C-parsing or use 'O'.

Switching off the C-parsing (without renaming the EXE):

MASM: ASMC /Zne
JWASM (in a common include file):
Code: [Select]
ifdef __ASMC__
OPTION CSTACK:0
endif
Title: Re: High Level Language in MASM
Post by: jj2007 on October 01, 2015, 03:27:06 AM
Thanks, it seems option cstack:0 solves the problem :t
Title: Re: High Level Language in MASM
Post by: nidud on October 01, 2015, 05:47:53 AM
In HLL a macro should be handled at the same level as a procedure. The header file may then control the expansion:
Code: [Select]
ifdef __INLINE__
strlen macro string
...
endm
else
strlen proto :dword
endif

This is currently possible in the HLL section:
Code: [Select]
.if strlen( esi )

The simplest solution to avoid breaking code will be to exclude invoke given the alternative is to extend it to allow invoke macro, args.
 
Without invoke a proc will work as a macro.
Code: [Select]
strcpy( esi, "string" )
.if strlen( eax ) == 6

Expansion of "quoted text" will then be limited to HLL proc's:
Code: [Select]
proc( "", ... )
Title: Re: High Level Language in MASM
Post by: jj2007 on October 01, 2015, 06:29:58 AM
This is currently possible in the HLL section:
Code: [Select]
.if strlen( esi )

This has always been possible, at least since ML 6.14. I am afraid I don't quite understand your point... ::)
Title: Re: High Level Language in MASM
Post by: nidud on October 01, 2015, 06:38:12 AM
This has always been possible, at least since ML 6.14.

Not if strlen() is a proc.
Title: Re: High Level Language in MASM
Post by: jj2007 on October 01, 2015, 07:42:04 AM
Code: [Select]
include \masm32\include\masm32rt.inc
.code
start:
.if rv(StrLen, chr$("123"))
print str$(eax), " bytes"
.else
print "empty string"
.endif
exit
end start
Title: Re: High Level Language in MASM
Post by: nidud on October 01, 2015, 08:36:05 AM
 :biggrin:

Not if rv() is a proc.

I am afraid I don't quite understand your point... ::)
Title: Re: High Level Language in MASM
Post by: dedndave on October 01, 2015, 04:10:01 PM
rv is a macro   :biggrin:
Title: Re: High Level Language in MASM
Post by: nidud on October 03, 2015, 07:54:44 AM
Some changes.

Invoke is removed (not needed) from the HHL code.

Strings not expanded in invoke or any other places except in HLL proc( "" ).

To synchronize the behaviour of the C implementation of SWITCH, CONTINUE will now jump to the test label of the innermost WHILE or REPEAT loop, the same behaviour as IF.

The version with no arguments will now also auto-break at the end of the last CASE, so no need to use BREAK there. In case of <value> the test will be CMP <SWITCH>,<CASE> so the value may be a function call or macro, but not an expression. With no switch-value an expression is assumed after each CASE, same as IF.

.CASE <expression>
.WHILE <expression>
.ELSEIF <expression>

Code: [Select]
.while macro( ebx ) && macro( ebp ) || macro( ecx )

Macros in these three cases needs to be expanded after the labels have been sorted out. It’s difficult to know at this early stage if these macros will generate any code; all macros will therefore be delayed.

A common method is now written to handle this better and some of these combinations may have failed in earlier versions.
Title: Re: High Level Language in MASM
Post by: jj2007 on October 03, 2015, 12:25:45 PM
Testbed with dialog handler. Extract all, then open *.asc in \Masm32\MasmBasic\RichMasm.exe

P.S.: Improved version attached.
Title: Re: High Level Language in MASM
Post by: nidud on October 03, 2015, 10:18:18 PM
It's an interesting test case

You have this C PROC (or a missing RET 16 ?)
Code: [Select]
OPTION PROLOGUE:NONE ; handlers get a 4k buffer in edi
OPTION EPILOGUE:NONE ; OPT_Susy Console
MyHandler proc hDlg, uMsg, wParam, lParam

push Language
call SetLanguage

retn

SetLanguage:

invoke GetDlgItem, hDlg, IDFIRST
retn 4
MyHandler endp

You then try to access the arguments without a stack frame.
Code: [Select]
  SWITCH uMsg
  CASE WM_COMMAND
movzx eax, word ptr wParam+2
movzx ecx, word ptr wParam
invoke EndDialog, hDlg, 0

Arguments: [ebp+8..n]
Code: [Select]
mov eax,hDlg
mov ecx,uMsg
mov edx,wParam
mov ebx,lParam

output from ASMC/JWASM/MASM:
Code: [Select]
mov eax, dword ptr [ebp+8H] ; 0006 _ 8B. 45, 08
mov ecx, dword ptr [ebp+0CH] ; 0009 _ 8B. 4D, 0C
mov edx, dword ptr [ebp+10H] ; 000C _ 8B. 55, 10
mov ebx, dword ptr [ebp+14H] ; 000F _ 8B. 5D, 14
...
invoke EndDialog, hDlg, 0
?_018: push 0 ; 055A _ 6A, 00
push dword ptr [ebp+8H] ; 055C _ FF. 75, 08
call _EndDialog@8 ; 055F _ E8, 00000000(rel)
?_019: ret ; 0564 _ C3

Then you insert this:
Code: [Select]
MyHandler proc hDlg0, uMsg0, wParam0, lParam0
if useAsmC eq 1 ; use 2 to see the bug in action...
  hDlg equ hDlg0[12]
  uMsg equ uMsg0[12]
  wParam equ wParam0[12]
  lParam equ lParam[12] ; ?
else
  hDlg equ hDlg0
  uMsg equ uMsg0
  wParam equ wParam0
  lParam equ lParam ; ?
endif

And the output from ASMC is then [ebp+8+12]:
Code: [Select]
?_018: push 0 ; 055A _ 6A, 00
push dword ptr [ebp+14H] ; 055C _ FF. 75, 14
call _EndDialog@8 ; 055F _ E8, 00000000(rel)
?_019: ret ; 0564 _ C3

Removing the above changes the output from ASMC is equal to the output of JWASM except for one line:
Code: [Select]
        and     eax, eax                                ; 02F9 _ 23. C0
...
        test    eax, eax                                ; 02F9 _ 85. C0
Title: Re: High Level Language in MASM
Post by: jj2007 on October 04, 2015, 04:25:39 AM
It's an interesting test case

You have this C PROC (or a missing RET 16 ?)
Code: [Select]
OPTION PROLOGUE:NONE ; handlers get a 4k buffer in edi
OPTION EPILOGUE:NONE ; OPT_Susy Console
MyHandler proc hDlg, uMsg, wParam, lParam
...
retn

Neither C, nor missing ret16. The handler is a simple call with no parameters, and relies on the locals of its "parent". The problem lies in the different way of handling uses:

a) your version:
Code: [Select]
; MbDlgP                    Ú$  57                       push edi                            ; HEX DlgMultiLanguageAsmCTestbed.MbDlgP(guessed hWnd,Msg,wParam,lParam)
; 00404B31                  ³.  56                       push esi
; 00404B32                  ³.  53                       push ebx
; 00404B33                  ³.  55                       push ebp
; 00404B34                  ³.  8BEC                     mov ebp, esp
; 00404B36                  ³.  81EC A00F0000            sub esp, 0FA0
; 00404B3C                  ³.  E8 DF080000              call ClearLocalsP

b) ML version:
Code: [Select]
; MbDlgP                    Ú$  55                       push ebp                            ; HEX DlgMultiLanguageAsmCTestbed.MbDlgP(guessed hWnd,Msg,wParam,lParam)
; 00404B41                  ³.  8BEC                     mov ebp, esp
; 00404B43                  ³.  81C4 60F0FFFF            add esp, -0FA0
; 00404B4E                  ³.  56                       push esi
; 00404B4F                  ³.  57                       push edi
; 00404B50                  ³.  53                       push ebx
; 00404B49                  ³.  E8 D2080000              call ClearLocalsP

The handler has no prologue, so it does not create locals, but it does have locals, in the sense: it can use the locals of the parent proc, i.e.
mov somelocal, eax translates to
mov [ebp+n], eax

This works with ML because it does somehow incorporate the extra offset needed for the uses esi edi ebx

For MasmBasic, I can use a simple workaround to overcome the different behaviour of AsmC: I simply drop the uses and push & pop them by hand. Tested and works fine, but you will have to decide whether this case is rare enough not to be handled. One argument for handling it correctly is that this bug was really difficult to find...

Pushing the "uses" regs before the frame is an interesting idea, because you will get the correct regs popped back even if leave handles an unbalanced stack. The question is whether you want to tolerate an unbalanced stack that way. It's another recipe for sleepless nights, bugs due to unbalanced stacks are difficult to find if the application does not show clear signs of problems, such as throwing an exception. To be discussed...

P.S.: Here is an excerpt of the built-in dialog handler; ExProc's call eax is the simple call to MyHandler:
Code: [Select]
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
txBufLen=3000 ; important: user's own handler locals must not exceed 1000 bytes
MbDlgP proc hDlg, uMsg, wParam, lParam ; no uses here (workaround for AsmC behaviour)
LOCAL txBuffer[txBufLen]:BYTE, dlgPuserLocals[4000-txBufLen]:BYTE ; reserved above txBuffer
  ClearLocals
  push esi ; uses esi edi ebx after ClearLocals
  push edi
  push ebx
  pDlgEsi equ <MbFlags[16]>
  mov esi, pDlgEsi
  lea edi, txBuffer
  push MbDLG.dh_ALL ; push the address of the general handler
  Call ExProc
  jne DefProc
  .if uMsg==WM_INITDIALOG
     .....
DefProc:
  mov eax, [esi.MbDLG.dlgRetEax]
  and [esi.MbDLG.dlgRetEax], 0
  pop ebx ; uses esi edi ebx
  pop edi
  pop esi
  ret
ExProc:
  mov eax, [esp+4]
  mov eax, [esi+eax] ; address of specific handler in MbDLG struct
  .if eax
push edi
call eax ; Zero?
pop edi ; txBuffer
inc eax ; or eax, -1 -> inc > eax=0 > Zero?=continue
  .endif
  retn 4
MbDlgP endp
Title: Re: High Level Language in MASM
Post by: nidud on October 04, 2015, 07:39:11 AM
Quote
a) your version:

Not really my idea. Many C compilers to enable easy allocation from the stack use it.

Quote
The handler has no prologue, so it does not create locals, but it does have locals, in the sense: it can use the locals of the parent proc, i.e.
mov somelocal, eax translates to
mov [ebp+n], eax

This works with ML because it does somehow incorporate the extra offset needed for the uses esi edi ebx

This is also done in ASMC, it have to, but there will be problems if you mix these two, so the parent and the handler must be equal.

Quote
For MasmBasic, I can use a simple workaround to overcome the different behaviour of AsmC: I simply drop the uses and push & pop them by hand.

MASM will always have a fixed offset to the arguments in EBP regardless of user registers, so you either have to do that or turn off the CSTACK for the parent(s).

Quote
Pushing the "uses" regs before the frame is an interesting idea, because you will get the correct regs popped back even if leave handles an unbalanced stack. The question is whether you want to tolerate an unbalanced stack that way. It's another recipe for sleepless nights, bugs due to unbalanced stacks are difficult to find if the application does not show clear signs of problems, such as throwing an exception. To be discussed...

There is currently a problem with the whole concept beside the limited usage. The epilogue code does not use LEAVE unless locals are used, so that’s the only time you may safely allocate additional stack. Thought the problem at hand is a special case the same thing may also apply to the CSTACK option, at least for now.

However, all other features added is using the same option so I should probably add a few more, and maybe turn off the stack option by default.
Title: Re: High Level Language in MASM
Post by: nidud on October 16, 2015, 08:56:45 AM
Added some more switches to handle the CSTACK option.

Switch -Xc: Disable ASMC extensions

This will disable syntax extensions, which aren't supported by JWasm.
Currently these are:
-   Delayed expansion of HLL expression in .WHILE, .ELSEIF, and .CASE.
-   Use of procedures in HLL expression and INVOKE
-   Use of procedures without INVOKE
-   Use of "quoted strings" in procedures

Same as OPTION ASMC: 0 (default is 1)

Switch -Cs: C stack: push USER regs first
Same as OPTION CSTACK: 1 (default is 0)

I uploaded the binary (http://sourceforge.net/projects/doszip/files/tools/asmc214.zip/download) to SF and also the current source code (http://sourceforge.net/projects/doszip/files/tools/source/asmc214s.zip/download).
Title: Re: High Level Language in MASM
Post by: ragdog on November 03, 2015, 03:12:51 AM
Quote
nidud
Not if strlen() is a proc.

jj2007

include \masm32\include\masm32rt.inc
.code
start:
   .if rv(StrLen, chr$("123"))
      print str$(eax), " bytes"
   .else
      print "empty string"
   .endif
   exit
end start


I know this post is old but i need it for my project and have make a strlen macro

Code: [Select]
strlen MACRO args:VARARG
      arg equ <invoke crt_strlen>         ;; construct invoke and function name
      FOR var,<args>                    ;; loop through all arguments
        arg CATSTR arg,<,reparg(var)>   ;; replace quotes and append arg
      ENDM
      arg                               ;; write the invoke macro
      EXITM <eax>                       ;; EAX as the return value
ENDM


Code: [Select]

         lea esi,string
         .if (strlen(esi)==20)

or

         .if (strlen(addr string)==16)


Im not good in macro writing i hope it is correct. ?!?

regards,


Title: Re: High Level Language in MASM
Post by: nidud on November 29, 2015, 12:23:55 AM
Some bug fixes added:

- Quoted strings were parsed from token. This fails if the string includes quotes. The string is now parsed from source line.
Code: [Select]
foo( " \"quoted string\" " )
;
; token 3: " \"
; 4: quoted
; 5: string
; 6: \
; 7: " "

- The %OUT directive didn’t work:
Code: [Select]
- .if eax == 'tou' ; %OUT directive?
+ .if eax == 'tuo' ; %OUT directive?

- The switch –D<tmacro>[=<value>] didn’t work correctly.
Title: Re: High Level Language in MASM
Post by: jj2007 on November 29, 2015, 02:45:55 AM
Works fine with my four biggest sources :t
Title: Re: High Level Language in MASM
Post by: nidud on January 25, 2016, 03:19:49 AM
A bug fix from the m32lib test:

http://masm32.com/board/index.php?topic=5035.msg54361#msg54361 (http://masm32.com/board/index.php?topic=5035.msg54361#msg54361)

- ASMC 2.15 failed with more than 64 arguments.
Title: Re: High Level Language in MASM
Post by: nidud on February 04, 2016, 03:06:04 AM
Some new updates.

Changes in 2.17 - 2 Feb 2016
- fixed command line switch -X -- used lower -x
- added command line switches -0..10[p] -- missing

The file ASMC217.ZIP include source code, additional tools (MAKE, LINK, LIB, ..) and a minimal LIBC used to build ASMC. This may be downloaded at doszip.sf.net/ (or use the green button).

ASMC218.ZIP is a small correction of v2.17:

Changes in 2.18 - 3 Feb 2016
- corrected encodings for 4 AVX instructions:
  - vpermilpd xmm0, xmm1, 1
  - vpermilpd ymm0, ymm1, 1
  - vpermilps xmm0, xmm1, 1
  - vpermilps ymm0, ymm1, 1
Title: Re: High Level Language in MASM
Post by: TWell on February 04, 2016, 03:38:06 AM
Thanks for sharing this!
Small and fast, i like that feature in women too :t
Title: Re: High Level Language in MASM
Post by: jj2007 on February 04, 2016, 04:04:49 AM
Some new updates.

error A2008: syntax error : CSTACK:0  ::)
(only with option -Zne)
Title: Re: High Level Language in MASM
Post by: nidud on February 04, 2016, 05:27:45 AM
Confirmed.

However, the combination Disable non Masm extensions (/Zne) and usage of non Masm extensions is ambiguous.

The correct error handling should be:
Code: [Select]
OPTION CSTACK:0 ; no error
OPTION CSTACK:1 ; error

The option cstack is off by default so you have to use the switch –Cs or option cstack:1 to turn it on.
Title: Re: High Level Language in MASM
Post by: nidud on April 21, 2016, 08:42:44 PM
Switch test..

I found a slick way for the dual jump to the table without using any registers. This only works if the switch statement is a label-size register. AX/CX/.. in 16-bit, EAX in 32-bit and so on. Memory or split registers will still be using the stack.

Code: [Select]
cmp sw_reg,max
jg done
cmp sw_reg,min
jl done
jmp [JumpTable+sw_reg*4-min*4]
done:

Timings: Note, I'm using the same version of HJwasm as before (The HJwasm32.zip file is still 64-bit)
Code: [Select]
662       cycles, rep(30), code(480): SWITCH_: MasmBasic
682   cycles, rep(30), code(460): .SWITCH: ASMC -- EAX
1086   cycles, rep(30), code(476): .SWITCH: ASMC -- AL
1214      cycles, rep(30), code(632): .SWITCH: HJWASM
1670   cycles, rep(30), code(440): .elseif chain..

2063      cycles, rep(96), code(1386): .SWITCH: ASMC
2916      cycles, rep(96), code(1404): SWITCH_: MasmBasic
4718      cycles, rep(96), code(1820): .SWITCH: HJWASM
12342     cycles, rep(96), code(1430): .elseif chain..

7126      cycles, rep(250), code(3547): .SWITCH: ASMC
17199     cycles, rep(250), code(4592): .SWITCH: HJWASM
87077     cycles, rep(250), code(3989): .elseif chain..
Title: Re: High Level Language in MASM
Post by: jj2007 on April 21, 2016, 09:43:41 PM
There is something strange:

Code: [Select]
swproc proc value
mov eax,value
int 3
.SWITCH eax
enum = 0

Under the hood:
Code: [Select]
00401B12             Ú.  55                 push ebp
00401B13             ³.  8BEC               mov ebp, esp
00401B15             ³.  8B45 08            mov eax, [arg.1]
00401B18             ³.  CC                 int3                         ; @@@@ BREAKPOINT @@@
00401B19             ³. E9 C5030000        jmp 00401EE3
00401B1E             ³>  B8 00000000        mov eax, 0                         ; Case 0 of switch timeit.401EE3
00401B23             ³. E9 54050000        jmp 0040207C
00401B28             ³>  B8 01000000        mov eax, 1                         ; Case 1 of switch timeit.401EE3
...
00401EBB             ³.ÚE9 BC010000        jmp 0040207C
00401EC0             ³> ³B8 5D000000        mov eax, 5D                        ; Case 5D of switch timeit.401EE3
00401EC5             ³.³E9 B2010000        jmp 0040207C
00401ECA             ³> ³B8 5E000000        mov eax, 5E                        ; Case 5E of switch timeit.401EE3
00401ECF             ³.³E9 A8010000        jmp 0040207C
00401ED4             ³> ³B8 5F000000        mov eax, 5F                        ; Case 5F of switch timeit.401EE3
00401ED9             ³.³E9 9E010000        jmp 0040207C
00401EDE             ³.³E9 99010000        jmp 0040207C
00401EE3             ³> ³83F8 5F            cmp eax, 5F                        ; Switch (cases 0..5F, 97. exits)
00401EE6             ³.³7F 0C              jg short 00401EF4
00401EE8             ³. ³83F8 00            cmp eax, 0
00401EEB             ³.³7C 07              jl short 00401EF4
00401EED             ³.³FF2485 FC1E4000    jmp near [eax*4+401EFC]   ; @@@ ACCESS VIOLATION @@@
00401EF4             ³>³E9 83010000        jmp 0040207C                       ; Default case of switch timeit.401EE3
00401EF9             ³  ³8D40 00            lea eax, [eax]
00401EFC             ³. ³1E1B4000           dd 00401B1E
00401F00             ³. ³281B4000           dd 00401B28
00401F04             ³. ³321B4000           dd 00401B32

Already at the second iteration, I get an access violation ::)
But only if I run it with Olly...

P.S.: Weird. I haven't changed anything, but now I no longer get that access violation :dazzled:


The code generated btw resembles very much the MB Switch_ code.
Title: Re: High Level Language in MASM
Post by: nidud on April 21, 2016, 11:32:04 PM
The code generated btw resembles very much the MB Switch_ code.

Well, they are all more or less the same. That’s why Olly, Objconv, and other tools recognize the code. The ASMC version however is special as it allows dynamic data in the case statement. I assumed skipping the jump table wouldn’t add that much time to the equation. This assumption still holds true up to a point, and this tipping point seems to be around 16 cases. Above this the jump-table is both faster and smaller in size.

The standard C version:
Code: [Select]
switch ( val ) {
case 3:
val = 14;
break;
case 4:
val = 13;
break;
case 5:
val = 12;
break;

MS encoding (from Objconv):
Code: [Select]
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 8B. EC
        push    ecx                                     ; 0003 _ 51
        mov     eax, dword ptr [ebp+8H]                 ; 0004 _ 8B. 45, 08
        mov     dword ptr [ebp-4H], eax                 ; 0007 _ 89. 45, FC
        mov     ecx, dword ptr [ebp-4H]                 ; 000A _ 8B. 4D, FC
        sub     ecx, 3                                  ; 000D _ 83. E9, 03
        mov     dword ptr [ebp-4H], ecx                 ; 0010 _ 89. 4D, FC
        cmp     dword ptr [ebp-4H], 13                  ; 0013 _ 83. 7D, FC, 0D
        ja      ?_001                                   ; 0017 _ 0F 87, 00000086
        mov     edx, dword ptr [ebp-4H]                 ; 001D _ 8B. 55, FC
        jmp     dword ptr [$L54+edx*4]                  ; 0020 _ FF. 24 95, 00000000(d)
...
$L54    label dword                                     ; switch/case jump table
        dd $L37                                         ; 00AC _ 00000000 (d)
        dd $L38                                         ; 00B0 _ 00000000 (d)

OW encoding:
Code: [Select]
        mov     eax, dword ptr [esp+4H]                 ; 0038 _ 8B. 44 24, 04
        lea     edx, [eax-3H]                           ; 003C _ 8D. 50, FD
        cmp     edx, 13                                 ; 003F _ 83. FA, 0D
        ja      ?_017                                   ; 0042 _ 77, 74
        jmp     dword ptr [?_001+edx*4]                 ; 0044 _ FF. 24 95, 00000000(segrel)
...
?_001   label dword                                     ; switch/case jump table
        dd FLAT:?_003                                   ; 0000 _ 0000004B (segrel)

And MasmBasic:
Code: [Select]
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 8B. EC
        mov     eax, dword ptr [ebp+8H]                 ; 0003 _ 8B. 45, 08
        cmp     eax, dword ptr [?_100]                  ; 0006 _ 3B. 05, 000003FC(segrel)
        mov     edx, dword ptr [?_099]                  ; 000C _ 8B. 15, 000003F8(segrel)
        jg      ?_098                                   ; 0012 _ 0F 8F, 000003D9
        add     edx, eax                                ; 0018 _ 03. D0
jl ?_098 ; 001A _ 0F 8C, 000003D1
        jmp     dword ptr [?_101+edx*4]                 ; 0020 _ FF. 24 95, 00000400(segrel)
...
?_099   dd 00000002H                                    ; 03F8 _ 2
?_100   dd 0000005FH                                    ; 03FC _ 95
?_101   label dword                                     ; switch/case jump table
        dd FLAT:?_001                                   ; 0400 _ 00000027 (segrel)
        dd FLAT:?_098                                   ; 0404 _ 000003F1 (segrel)
Title: Re: High Level Language in MASM
Post by: jj2007 on April 22, 2016, 01:32:49 AM
The ASMC version however is special as it allows dynamic data in the case statement.


Which is also true for the standard Masm32 switch macro, as we all know ;-)

For MasmBasic Switch_ / Case_ / Endsw_ this is not possible, though. I consider the whole exercise a bit academic, since (as you found out) you need many cases to make it faster than the if then else chain. Real world examples will be pretty rare. The WndProc is almost irrelevant, given the slowness of most WM_ events. You can put WM_MOUSEMOVE on top to "optimise" things 8)

Nonetheless, it's a nice exercise, so let's keep trying to find the World's best SWITCH :t
Title: Re: High Level Language in MASM
Post by: nidud on April 22, 2016, 06:25:59 AM
The ASMC version however is special as it allows dynamic data in the case statement.

Which is also true for the standard Masm32 switch macro, as we all know ;-)

That’s not a "switch", it’s an elseif-chain.

Quote
For MasmBasic Switch_ / Case_ / Endsw_ this is not possible, though.

But that’s a real switch, as I later found out, and wrongly accuse (or confused) not to be.

Quote
I consider the whole exercise a bit academic, since (as you found out) you need many cases to make it faster than the if then else chain.

 :biggrin:

Totally wrong assumption. A switch will beat an elseif-chain heads down from the first elseif statement.
Code: [Select]
1050      cycles, rep(2), code(38): .SWITCH
1401   cycles, rep(2), code(44): .elseif-chain

My arguments and assumptions were based on a plain switch with no overhang versus using a jump table. My conclusion was that you need a fixed number of cases for the latter one to make up for the overhang.

Quote
Real world examples will be pretty rare.

A quic search in the ASMC directory, a mixed bag of C and ASM:

Switch: 354
Case: 1795
Else if: 473
Elseif: 138

In the Masm32 examples directory:

Switch: 102
Case: 218
Elseif: 1080

One of the main arguments in this tread is to point out that the HLL section may have some benefits beyond readability, but it’s a slow burning fuse.

Quote
Nonetheless, it's a nice exercise, so let's keep trying to find the World's best SWITCH :t

Some healthy competition may speed up this process  :P
Title: Re: High Level Language in MASM
Post by: jj2007 on April 22, 2016, 12:42:38 PM
Some healthy competition may speed up this process  :P

Coming soon:
Code: [Select]
  swCount=-2
  REPEAT 10
Print Str$("ct=%i\t", swCount)
mov eax, swCount ; -1 ... +2
mov ecx, 2 ; for testing
mov edx, 4 ; for testing
Switch@ eax
Case@ 0
PrintLine "Case 0"
Case@ -1
PrintLine "Case -1"
Case@ edx
PrintLine Str$("edx=%i", edx)
Case@ ecx
PrintLine Str$("ecx=%i", ecx)
Case@ 1 .. 4
PrintLine "Case 1 .. 4"
Case@ var1
PrintLine Str$("var1=%i", var1)
Case@ 5
PrintLine "Case 5"
Default@
PrintLine "default"
Endsw@
swCount=swCount+1
  ENDM

Output:
Code: [Select]
ct=-2   default
ct=-1   Case -1
ct=0    Case 0
ct=1    Case 1 .. 4
ct=2    ecx=2
ct=3    Case 1 .. 4
ct=4    edx=4
ct=5    Case 5
ct=6    var1=6
ct=7    default
  :P

Under the hood:
Code: [Select]
0040151D             ³.  B8 02000000        mov eax, 2
00401522             ³.  B9 02000000        mov ecx, 2
00401527             ³.  BA 04000000        mov edx, 4
0040152C             ³.  CC                 int3
0040152D             ³. E9 B2000000        jmp 004015E4
00401532             ³>  68 58704000        push offset 00407058               ; ASCII "Case 0", case 0 of switch SwitchNew.4015F5
00401537             ³.  6A 01              push 1
00401539             ³.  6A 02              push 2
0040153B             ³.  E8 B3160000        call 00402BF3
00401540             ³. E9 DF000000        jmp 00401624
00401545             ³.  68 60704000        push offset 00407060               ; ASCII "Case -1", case -1 of switch SwitchNew.4015F5
0040154A             ³.  6A 01              push 1
0040154C             ³.  6A 02              push 2
0040154E             ³.  E8 A0160000        call 00402BF3
00401553             ³. E9 CC000000        jmp 00401624
00401558             ³>  52                 push edx
00401559             ³.  6A 05              push 5
0040155B             ³.  6A 00              push 0
0040155D             ³.  68 68704000        push offset 00407068               ; ASCII "edx=%i"
00401562             ³.  E8 4F080000        call 00401DB6
00401567             ³.  6A 7F              push 7F
00401569             ³.  6A 01              push 1
0040156B             ³.  6A 02              push 2
0040156D             ³.  E8 81160000        call 00402BF3
00401572             ³. E9 AD000000        jmp 00401624
00401577             ³>  51                 push ecx
00401578             ³.  6A 05              push 5
0040157A             ³.  6A 00              push 0
0040157C             ³.  68 70704000        push offset 00407070               ; ASCII "ecx=%i"
00401581             ³.  E8 30080000        call 00401DB6
00401586             ³.  6A 7F              push 7F
00401588             ³.  6A 01              push 1
0040158A             ³.  6A 02              push 2
0040158C             ³.  E8 62160000        call 00402BF3
00401591             ³. E9 8E000000        jmp 00401624
00401596             ³>  68 78704000        push offset 00407078               ; ASCII "Case 1 .. 4", cases 1, 2, 3, 4 of switch SwitchNew.4015F5
0040159B             ³.  6A 01              push 1
0040159D             ³.  6A 02              push 2
0040159F             ³.  E8 4F160000        call 00402BF3
004015A4             ³. EB 7E              jmp short 00401624
004015A6             ³>  FF73 80            push dword ptr [ebx-80]
004015A9             ³.  6A 05              push 5
004015AB             ³.  6A 00              push 0
004015AD             ³.  68 84704000        push offset 00407084               ; ASCII "var1=%i"
004015B2             ³.  E8 FF070000        call 00401DB6
004015B7             ³.  6A 7F              push 7F
004015B9             ³.  6A 01              push 1
004015BB             ³.  6A 02              push 2
004015BD             ³.  E8 31160000        call 00402BF3
004015C2             ³. EB 60              jmp short 00401624
004015C4             ³>  68 8C704000        push offset 0040708C               ; ASCII "Case 5", case 5 of switch SwitchNew.4015F5
004015C9             ³.  6A 01              push 1
004015CB             ³.  6A 02              push 2
004015CD             ³.  E8 21160000        call 00402BF3
004015D2             ³. EB 50              jmp short 00401624
004015D4             ³>  68 94704000        push offset 00407094               ; ASCII "default", default case of switch SwitchNew.4015F5
004015D9             ³.  6A 01              push 1
004015DB             ³.  6A 02              push 2
004015DD             ³.  E8 11160000        call 00402BF3
004015E2             ³. EB 40              jmp short 00401624
004015E4             ³>  3BC2               cmp eax, edx
004015E6             ³. 0F84 6CFFFFFF      je 00401558
004015EC             ³.  3BC1               cmp eax, ecx
004015EE             ³. 74 87              je short 00401577
004015F0             ³.  3B43 80            cmp eax, [ebx-80]
004015F3             ³. 74 B1              je short 004015A6
004015F5             ³.  83F8 05            cmp eax, 5                         ; Switch (cases -1..5, 5 exits)
004015F8             ³. 7F DA              jg short 004015D4
004015FA             ³.  83F8 FF            cmp eax, -1
004015FD             ³. 7C D5              jl short 004015D4
004015FF             ³. FF2485 0C164000    jmp near [eax*4+40160C]  <<<<<<<<<<<<< HERE IT IS
00401606             ³   8BFF               mov edi, edi
00401608             ³.  45154000           dd 00401545
0040160C             ³.  32154000           dd 00401532
00401610             ³.  96154000           dd 00401596
00401614             ³.  96154000           dd 00401596
00401618             ³.  96154000           dd 00401596
0040161C             ³.  96154000           dd 00401596
00401620             ³.  C4154000           dd 004015C4
Title: Re: High Level Language in MASM
Post by: nidud on April 22, 2016, 08:52:49 PM
Now that’s the spirit  :biggrin:

Assuming the size issue is fixed, and if a default case is omitted this will be the "fill" label used in the table instead of the exit label, this will be a good solution given no registers is used in the process.

Good thinking (as per usual)  :t

The logic for an optional default case:
Code: [Select]
.switch edx
...
  .default
mov eax,COP_NONE
.break
.endsw
ret

Code: [Select]
mov eax,COP_NONE
        .switch edx
...
.endsw
ret

Coming soon:
Code: [Select]
  .case CHARS_EQ: mov eax,COP_EQ: .break
  .case CHARS_NE: mov eax,COP_NE: .break
  .case CHARS_GE: mov eax,COP_GE: .break
  .case CHARS_LE: mov eax,COP_LE: .break
  .case CHARS_OR: mov eax,COP_OR: .break
Title: Re: High Level Language in MASM
Post by: nidud on April 23, 2016, 10:05:14 AM
New test..

All three 16/32/64-bit tables are now implemented but only the 16 and 32-bit version are tested. I added a 64-bit test case to see if that actually works.

The scaled version uses the stack to preserve regs and the
.case <statement> : <code> : ... is also implemented.
It only test for segment register in front (as in DS:...)

new timings: a bit faster and more compact
Code: [Select]
149198    cycles, rep(97), code(1403): .SWITCH: ASMC
205966   cycles, rep(97), code(1416): SWITCH_: MasmBasic
374192    cycles, rep(97), code(1838): .SWITCH: HJWASM
867748   cycles, rep(97), code(1445): .elseif chain..
Title: Re: High Level Language in MASM
Post by: jj2007 on April 23, 2016, 07:46:30 PM
new timings: a bit faster and more compact

My 2 cts :biggrin:
Code: [Select]
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
31 ms   case 64, MB Switch_ ret
25 ms   case 64, MB Switch_ jmp
455 ms  case 64, Masm32 switch
25 ms   case 64, AsmC .Switch

26 ms   case -1, MB Switch_ ret
26 ms   case -1, MB Switch_ jmp
665 ms  case -1, Masm32 switch
27 ms   case -1, AsmC .Switch

807     bytes for MBSret   <<<<<<<<<<<<<<<<<<<<
1186    bytes for MBSjmp
1208    bytes for Masm32
1179    bytes for asmc

Valid syntax:
Code: [Select]
Switch_ eax
Case_ 0
PrintLine "Case 0"
Case_ -1
PrintLine "Case -1"
Case_ edx
PrintLine Str$("edx=%i", edx)
Case_ ecx
PrintLine Str$("ecx=%i", ecx)
Case_ 1 .. 4
PrintLine "Case 1 .. 4"
Case_ var1
PrintLine Str$("var1=%i", var1)
Case_ 5
PrintLine "Case 5"
Default_
PrintLine "Default"
Endsw_
Title: Re: High Level Language in MASM
Post by: nidud on April 24, 2016, 04:27:52 AM
Some more probing of the one-line-case thing.

The expansion situation is now more or less like this:
Code: [Select]
.if <expression> - expand
.elseif <expression> - delay expansion
.until <expression> - expand
.while <expression> - delay expansion
.switch <expression> - expand
.case <expression> - delay expansion

So these may be safely expanded without delay:
Code: [Select]
.if <expression> - expand
.until <expression> - expand
.switch <expression> - expand

Some macros generate code so they have to be expanded after a label has been created in case, while, and elseif.
Code: [Select]
foo macro reg ; generate codes
bswap reg
exitm  <reg>
endm

bar macro const:req ; no code generated
local string
string equ <>
forc q, <const>
string catstr <q>, string
endm
exitm <string>
endm

A simple test of code generation:
Code: [Select]
.switch foo( eax )
  .case foo( ecx )

The result should be something like this:
Code: [Select]
        bswap   eax                                     ; 0000 _ 0F C8
        jmp     ?_006                                   ; 0002 _ EB, 11
?_001:  jmp     ?_007                                   ; 0004 _ EB, 33
?_006:  bswap   ecx                                     ; 0015 _ 0F C9
        cmp     eax, ecx                                ; 0017 _ 3B. C1
        jz      ?_001                                   ; 0019 _ 74, E9

Not like this:
Code: [Select]
        bswap   eax                                     ; 0000 _ 0F C8
        jmp     ?_006                                   ; 0002 _ EB, 11
; Note: No jump seems to point here
        bswap   ecx                                     ; 0004 _ 0F C9
?_001   LABEL NEAR
        jmp     ?_013                                   ; 0006 _ EB, 7B

The general expression version of the switch (no args) also allow colon after expression.
Code: [Select]
mov eax,"arg3"

.switch foo( eax )
  .case bar( "arg1" ) : inc opt_1 : .break
  .case bar( "arg2" ) : inc opt_2 : .break
  .case bar( "arg3" ) : inc opt_3 : .break
  .case bar( "arg4" ) : inc opt_4 : .break
.endsw

.switch
  .case opt_1 : printf( "option 1 activated\n" ) : .break
  .case opt_2 : printf( "option 2 activated\n" ) : .break
  .case opt_3 : printf( "option 3 activated\n" ) : .break
  .case opt_4 : printf( "option 4 activated\n" ) : .break
.endsw

Quote
Valid syntax:

Including foo()/bar()   :biggrin:

Code: [Select]
807     bytes for MBSret   <<<<<<<<<<<<<<<<<<<<
The table threshold is currently 14 valid cases, so a simple compare is used below this. Habrans version seems to be fast on short counts and it is somewhat important to have good timings there.

I need to write some regression code to lock the changes made so far, and then do some testing.
Title: Re: High Level Language in MASM
Post by: nidud on April 26, 2016, 07:01:04 AM
Here's the test for the optimised table version.
Code: [Select]

; jump table in switch

.386
.model flat

.code

.switch eax
  .case 0 : .break ; no table
  .case 1 : .break
  .case 2
.endsw

.switch eax
  .case 0 : .break ; table - 4
  .case 1 : .break
  .case 2 : .break
  .case 3
.endsw

.switch eax
  .case 0 : .break
  .case 1000 : .break ; -> table - 10
  .case 1001 : .break
  .case 1002 : .break
  .case 1003 : .break
  .case 1004 : .break
  .case 1005 : .break
  .case 1006 : .break
  .case 1007 : .break
  .case 1008 : .break
  .case 1009 : .break ; <-
  .case 10000 : .break
  .case 100000
.endsw

.switch eax
  .case 0 : .break
  .case 100 : .break ; no table
  .case 101 : .break
  .case 102 : .break
  .case 103 : .break
  .case 104 : .break
  .case 1000 : .break ; -> table - 7
  .case 1001 : .break
  .case 1002 : .break
  .case 1003 : .break
  .case 1004 : .break
  .case 1005 : .break
  .case 1006 : .break ; <-
  .case 10000 : .break
  .case 100000
.endsw

.switch al ; extended table
  .case 'e' ; stack used
  .case 'z'
  .case 'c'
  .case 's'
  .case 'p'
  .case 'o'
mov BYTE PTR [ecx+1],al
mov BYTE PTR [ecx],'n'
ret
  .case 'n'
mov BYTE PTR [ecx],ah
mov BYTE PTR [ecx+1],' '
ret
  .case 'a'
mov BYTE PTR [ecx],'b'
.break
  .case 'b'
mov BYTE PTR [ecx],'a'
.break
  .case 'g'
mov BYTE PTR [ecx],'l'
.break
  .case 'l'
mov BYTE PTR [ecx],'g'
.break
  .default
.if al == 'm'
sub ecx,1
mov BYTE PTR [ecx],0
.endif
ret
.endsw

end
Title: Re: High Level Language in MASM
Post by: jj2007 on April 26, 2016, 09:21:42 AM
Ideas and implementation are OK, but why the .break?? It's a horrible C design flaw, even K&R admitted that, and has no right to exist in assembler. Think about it - you are just creating confusion here. If you absolutely believe in the fall-thru behaviour, force it with an optional .continue, but eliminate that .break horror, please :icon_redface:

Re case foo : bar, there might be rare situations where it adds to readability, BUT: the colon is BASIC syntax! I have no firm opinion on that one, and it would be easy to implement in MasmBASIC (where it fits...), but from a design point of view it would appear to me a little bit inconsistent.

Code: [Select]
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
Assembled with AsmC
7 ms    case 260, MB Switch_ ret
5 ms    case 260, MB Switch_ jmp
385 ms  case 260, Masm32 switch
5 ms    case 260, AsmC .Switch

7 ms    case 196, MB Switch_ ret
6 ms    case 196, MB Switch_ jmp
289 ms  case 196, Masm32 switch
6 ms    case 196, AsmC .Switch

7 ms    case 132, MB Switch_ ret
5 ms    case 132, MB Switch_ jmp
196 ms  case 132, Masm32 switch
5 ms    case 132, AsmC .Switch

7 ms    case 68, MB Switch_ ret
5 ms    case 68, MB Switch_ jmp
101 ms  case 68, Masm32 switch
6 ms    case 68, AsmC .Switch

7 ms    case 4, MB Switch_ ret
5 ms    case 4, MB Switch_ jmp
5 ms    case 4, Masm32 switch
5 ms    case 4, AsmC .Switch

2171    bytes for MBSret
3383    bytes for MBSjmp
3962    bytes for Masm32
3380    bytes for asmc

Interesting that the AsmC .switch beats the Masm32 macro hands down at 3380 : 3962 bytes :t
Title: Re: High Level Language in MASM
Post by: hutch-- on April 26, 2016, 11:31:21 AM
The switch in MASM32 is the classic design, sequential comparisons, if you want to go faster, use a tool called "TPROC.EXE" for range specified table based branching, that is what it was designed for and is capable of handling many thousands of options. This is what the base code looks like.


align 4

default proc value:DWORD

  .data
    align 4
    deftbl \
      dd l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10
  .code


    mov eax, value
    cmp eax, 10
    ja error
    jmp DWORD PTR [deftbl+eax*4]

  align 4
  error:
    mov eax, -1
    jmp quit_default

  align 4
  l0:
    mov eax, 0
    jmp quit_default

  align 4
  l1:
    mov eax, 1
    jmp quit_default

  align 4
  l2:
    mov eax, 2
    jmp quit_default

  align 4
  l3:
    mov eax, 3
    jmp quit_default

  align 4
  l4:
    mov eax, 4
    jmp quit_default

  align 4
  l5:
    mov eax, 5
    jmp quit_default

  align 4
  l6:
    mov eax, 6
    jmp quit_default

  align 4
  l7:
    mov eax, 7
    jmp quit_default

  align 4
  l8:
    mov eax, 8
    jmp quit_default

  align 4
  l9:
    mov eax, 9
    jmp quit_default

  align 4
  l10:
    mov eax, 10
    jmp quit_default

  quit_default:


    ret

default endp


This has been tested on 100000 options and does not slow down with very large counts.
Title: Re: High Level Language in MASM
Post by: anunitu on April 26, 2016, 07:19:25 PM
I am wondering where things will go if they get the quantum computer thing working. I mean light speed data transfer? like unlimited data processing. would it be basic at light speed? I would be a doubter,but I have seen a LOT of things come to pass,I would have said could not be done. Brave new world...
Title: Re: High Level Language in MASM
Post by: nidud on April 26, 2016, 10:56:07 PM
Ideas and implementation are OK, but why the .break?? It's a horrible C design flaw

Structured switches are used to execute exclusive blocks in a closed environment. The scripting tools used for this purpose is purely educational so they are (or where) not made to produce real software. These include the Pascal family (Object Pascal, Modula, Oberon, Ada, etc.) as well as modern forms of Fortran and BASIC dialects influenced by Pascal. The "children" using these sandbox tools are called script-kiddies for this very reason.

https://en.wikipedia.org/wiki/Switch_statement (https://en.wikipedia.org/wiki/Switch_statement)

Real programming tools use unstructured switches (scary stuff) where the cases are treated as labels within a single block. In addition to this there is the control table implementation:
Quote
A control table can be constructed along similar lines to a language dependent switch statement but with the added possibility of testing for combinations of input values (using boolean style AND/OR conditions) and potentially calling multiple subroutines (instead of just a single set of values and 'branch to' program labels). (The switch statement construct in any case may not be available, or has confusingly differing implementations in high level languages (HLL). The control table concept, by comparison, has no intrinsic language dependencies, but might nevertheless be implemented differently according to the available data definition features of the chosen programming language.)

https://en.wikipedia.org/wiki/Control_table (https://en.wikipedia.org/wiki/Control_table)

Quote
even K&R admitted that

Not really. It’s just a warning that emphasizes the difference between real programming and scripting:
Quote
Falling through from one case to another is not robust, being prone to disintegration when the program is modified. With the exception of multiple labels for a single computation, fall-throughs should be used sparingly, and commented.

As a matter of good form, put a break after the last case (the default here) even though it's logically unnecessary. Some day when another case gets added at the end, this bit of defensive programming will save you.

If this were a major design flaw we wouldn't be having this conversation given C would just be another scripting language. The problem with real programming tools is the open platform, especially assembly, which opens up an unstructured can of worms of possibilities and chaos.

Quote
, and has no right to exist in assembler. Think about it - you are just creating confusion here. If you absolutely believe in the fall-thru behaviour, force it with an optional .continue, but eliminate that .break horror, please :icon_redface:

 :biggrin:

Yes, chaos is confusing: the joy bringer of possibilities versus the killjoy of restrictions.

One of the problems today is the dependency on software so programmers are mass-produced on assembly lines to feed this demand. As a result of this, inflation occur in the same way that the universe expand by producing voidage, so the complexity of programming have to be reduced. Instead of the usual warning, "don’t forget to add a break at the end of each case" the newer compilers seem to force you to do so. Apparently the replacement is a jump statement as in goto case 1.

However, assembly is a different case all together and the whole concept is based on labels rather than blocks, so I don’t think all these "handholding restrictions" directly applies to the assembly language.
Title: Re: High Level Language in MASM
Post by: nidud on April 26, 2016, 11:45:25 PM
Quote
When implemented as such, a switch statement essentially becomes a perfect hash.

A useful feature could then be to assign names directly to labels.
Code: [Select]
.switch ecx
  .case 8 : movsb : dec ecx
  .case 7 : movsb : dec ecx
  .case 6 : movsb : dec ecx
  .case 5 : movsb : dec ecx
  .case 4 : movsb : dec ecx
  .case 3 : movsb : dec ecx
  .case 2 : movsb : dec ecx
  .case 1 : movsb : dec ecx
.endsw

Using the ASMC -coff -Fl –Sg copy.asm you get this output:
Code: [Select]
00000002                    *   @C0002:
00000002  A4                *   movsb
00000003  49                *   dec ecx
00000004                          .case 7 : movsb : dec ecx
00000004                    *   @C0003:
00000004  A4                *   movsb
00000005  49                *   dec ecx
00000006                          .case 6 : movsb : dec ecx
00000006                    *   @C0004:

Adding this on top of the switch:
Code: [Select]
OPTION LABEL: copy_

May then produce this output:
Code: [Select]
00000002     * copy_8:
00000002  A4                *   movsb
00000003  49                *   dec ecx
00000004                          .case 7 : movsb : dec ecx
00000004     * copy_7:
00000004  A4                *   movsb
00000005  49                *   dec ecx
00000006                          .case 6 : movsb : dec ecx
00000006     * copy_6:
Title: Re: High Level Language in MASM
Post by: jj2007 on April 27, 2016, 01:06:53 AM
If this were a major design flaw we wouldn't be having this conversation

See #1 in What is the greatest design flaw you have faced in any programming language? (http://programmers.stackexchange.com/questions/55047/what-is-the-greatest-design-flaw-you-have-faced-in-any-programming-language)

Kernighan (https://www.cs.cmu.edu/~mihaib/kernighan-interview/):
Quote
There are some trivial things that are wrong with C: the switch statement could have been better designed
- but he blames it on Richie, he he :biggrin:
Title: Re: High Level Language in MASM
Post by: nidud on April 27, 2016, 02:19:37 AM
 :biggrin:

And you concluded from that statement that the solution would be to remove the fall-through option from the switch?

If that was the case then why didn't they correct this in C++?

As I mention there is a small change in C# where an error is produced if you forget to put a break statement at the end of each case, so they didn't remove the break.

This will however still work in C#
Code: [Select]
.switch al ; extended table
  .case 'e' ; stack used
  .case 'z'
  .case 'c'
  .case 's'
  .case 'p'
  .case 'o'
mov BYTE PTR [ecx+1],al
mov BYTE PTR [ecx],'n'
ret
Title: Re: High Level Language in MASM
Post by: hutch-- on April 27, 2016, 04:45:15 AM
Here is a wildcard for you, have both a modern design switch AND a break statement. Both are useful.
Title: Re: High Level Language in MASM
Post by: nidud on April 27, 2016, 06:32:35 AM
Here is a wildcard for you, have both a modern design switch AND a break statement. Both are useful.

The implementation now is rather bendable so adding options to the existing switch later could fix this.
Code: [Select]
OPTION SWITCH: C/PASCAL/AUTOBREAK/TABLE/NOTABLE/...

Well, it’s a laid-back project so there is time to add features and see what works and what’s not (as long as you keep the server running that is  :P).
Title: Re: High Level Language in MASM
Post by: jj2007 on April 27, 2016, 08:12:20 AM
And you concluded from that statement that the solution would be to remove the fall-through option from the switch?

No, I suggested .continue to force fall-through, in the unlikely case that somebody really needed that. The frequently quoted excuse on C sites that you can use
Code: [Select]
Case 1
Case 2
Case 3
  do something
is badly misleading because Masm32 switch allows the much more elegant
Code: [Select]
Case 1, 2, 3
  do something

Quote
If that was the case then why didn't they correct this in C++?

As I mention there is a small change in C# where an error is produced if you forget to put a break statement at the end of each case, so they didn't remove the break.

I would call that a desperate attempt to fix a well-known big problem 8)

Others react differently, for example Apple: (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html)
Quote
Because the cases of a switch statement do not fall through to the next case in Swift, it avoids common C errors caused by missing break statements.

Fallthrough (https://en.wikipedia.org/wiki/Switch_statement#Fallthrough)
Quote
In many languages, only the matching block is executed, and then execution continues at the end of the switch statement. These include the Pascal family (Object Pascal, Modula, Oberon, Ada, etc.) as well as modern forms of Fortran and BASIC dialects influenced by Pascal, most functional languages, and many others. To allow multiple values to execute the same code (and avoid needing to duplicate code), Pascal-type languages permit any number of values per case, given as a comma-separated list, as a range, or as a combination. ... Perl does not fall through by default, but a case may explicitly do so using a continue keyword. This prevents unintentional fallthrough but allows it when desired.

Remember also that Masm32 has had a switch for a decade or so that a) does not fall through and b) is a lot more powerful than its C/C++ counterpart. So far, it was my impression that you were working on extending and improving an assembler, not writing a new C compiler...

P.S.: Note that I am a very selfish person here: I criticise your attempt to cripple AsmC because it is the best and fastest Masm clone so far; I do all my coding in AsmC nowadays, and only when I am really satisfied, I try a final build with ML 6.15 to ensure that my stuff is still compatible with the mainstream 8)
Title: Re: High Level Language in MASM
Post by: nidud on April 27, 2016, 10:09:37 AM
Quote
No, I suggested .continue to force fall-through

.continue is already used in .while and .repeat
.fallthrough may be an option but that’s not going to happen.
Code: [Select]
ASMC -swp
...
        OPTION SWITCH: PASCAL

Problem solved.

Quote
In the unlikely case that somebody really needed that.
:biggrin:
It happens all the time. Ask a programmer and he will tell you.
Code: [Select]
switch( fixup->option ) {
case OPTJ_EXPLICIT:
    return;
case OPTJ_EXTEND: /* Jxx for 8086 */
    size++;   /* will be 3/5 finally */
    /* fall through */
case OPTJ_JXX: /* Jxx for 386 */
    size++;
    /* fall through */
default: /* normal JMP (and PUSH) */

Quote
The frequently quoted excuse on C sites that you can use is badly misleading because Assembly Switch allows the much more elegant

There are no switch implemented in MASM, or any MASM compatible assembler as far as I know, except from ASMC. However, I have no plans on removing or prohibit any usage of these macros you mention  :P

The use, of, comma, in the case argument is a Pascal thing
http://wiki.freepascal.org/Case (http://wiki.freepascal.org/Case)

Quote
I would call that a desperate attempt to fix a well-known big problem

I see this argument used by a few promoting their favourite script tools, but to describe this as a "desperate attempt to fix a well-known big problem" or as the "greatest design flaw you have faced in any programming language" is pure propaganda. The fix above is just "nanny-help" for "script-kiddies". In other words a trivial problem.

Quote
There are some trivial things that are wrong with C: the switch statement could have been better designed, the precedences of some operators are wrong, but those are trivial things and everybody's learned to live with them.

This means that the fall through problem is solved as you suggested by forcing a .continue at the end of each case if that was the intention. However, empty cases are handled as a regular fall through.

What it doesn’t mean is that C, C++, or C# could have been released without a fall through option in the switch, and that is the main point.
Title: Re: High Level Language in MASM
Post by: jj2007 on April 27, 2016, 06:38:56 PM
.continue is already used in .while and .repeat

So what? You are the master of the AsmC source, you are free to treat .continue in a .switch structure as "GOTO next case" aka "fall through". After all, any code written for AsmC using .switch will fail miserably with MASM, so backward compatibility isn't an issue.

Quote
The use, of, comma, in the case argument is a Pascal thing

It's a Masm32 thing, first of all. And it's elegant.

Quote
... pure propaganda. The fix above is just "nanny-help" for "script-kiddies".

Ehm... you think anybody who doesn't code in C/C++ is a script kiddy? Or do you just mean bad coders in general, such as the C coders who wrote OS X (https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/)?
Title: Re: High Level Language in MASM
Post by: nidud on April 27, 2016, 09:09:40 PM
Quote
So what? You are the master of the ...
:biggrin:
Yes, I know: I’m the master of the universe. However, with great power comes great responsibility, so there is that  :lol:

Masm has already assign meaning to .continue, but then again the same logic should apply to .break.

Quote
Microsoft Macro Assembler Reference   

.CONTINUE
.CONTINUE [[.IF condition]]
Generates code to jump to the top of a .WHILE or .REPEAT block if condition is true.

.BREAK
.BREAK [[.IF condition]]
Generates code to terminate a .WHILE or .REPEAT block if condition is true.

Code: [Select]
.repeat
.while edi
.switch eax
  .case 1 : .continue
  .case 2 : .break
.endsw
xor ebx,ebx
.endw
.break .if condition
.continue .if condition
...
.until esi

Code: [Select]
continue1:
.repeat
continue2:
.while edi
.switch eax
  .case 1 : jmp continue2
  .case 2 : jmp break2
.endsw
xor ebx,ebx
.endw
break2:
.if condition
jmp break1
.endif
.if condition
jmp continue1
.endif
...
.until esi
break1:

So there is a logistical problem there.

I implemented these these options:
Code: [Select]
OPTION SWITCH: C ; command line switch -swc (default)
OPTION SWITCH: PASCAL ; command line switch -swp
OPTION SWITCH: TABLE ; command line switch -swt
OPTION SWITCH: NOTABLE ; command line switch -swn
OPTION SWITCH: AUTO ; command line switch -swa (default)

The Pascal option don’t need a break at the end of each case but the C option will. This means that the Pascal option also needs the a, b, c implementation for multiple cases in addition to the double dot but this must apply to both of them.

However, the C or Case-break issue still remains.
Code: [Select]
.case 1 : .cbreak
.cbreak .if condition
Title: Re: High Level Language in MASM
Post by: nidud on April 28, 2016, 10:13:42 AM
New test case for the C/Pascal switch implementation

This optimised implementation also test if the case above ended with an unconditional jump from endc, break, or continue. In terms of the control flow of loops, both break and continue may now be used inside the switch.

The Table version needs some more testing. It demand a size_t register and enumerated values and will potentially create a table of any size.

Code: [Select]
.386
.model flat

.code

OPTION SWITCH: PASCAL
;
; skip jump if .break occure
;
        .while edx
.switch ecx
  .case 0 : mov al,0 : .break
  .case 1 : mov al,1 : .break
  .case 2 : mov al,2 : .break
.endsw
.endw
;
; skip jump if .continue occure
;
        .while edx
.switch ecx
  .case 0 : mov al,0 : .continue
  .case 1 : mov al,1 : .continue
  .case 2 : mov al,2 : .continue
.endsw
.endw
;
; jump...
;
        .while edx
.switch ecx
  .case 0 : mov al,0
  .case 1 : mov al,1
  .case 2 : mov al,2
.endsw
.endw

OPTION SWITCH: C
;
; no jump...
;
        .while edx
.switch ecx
  .case 0 : mov al,0
  .case 1 : mov al,1
  .case 2 : mov al,2
.endsw
.endw
;
; jump...
;
        .while edx
.switch ecx
  .case 0 : mov al,0 : .endc
  .case 1 : mov al,1 : .endc
  .case 2 : mov al,2 : .endc
.endsw
.endw
;
; one jump...
;
.switch ecx
  .case 0, 1, 2 : mov al,3 : .endc
.endsw
;
; one jump - last case
;
.switch ecx
  .case 0, 1, 2 : mov al,3
.endsw

OPTION SWITCH: NOTABLE
;
; one jump - no table
;
.switch ecx
  .case 0, 1, 2, 4 : mov al,4
.endsw

OPTION SWITCH: TABLE
;
; one jump - forced table
;
.switch ecx
  .case 0, 1, 2 : mov al,4
.endsw

end
Title: Re: High Level Language in MASM
Post by: nidud on April 29, 2016, 12:18:15 AM
Now that the switch works independent from the loops and able to control the flow from within, where the cases are treated as labels within a single block, loops may be used inside the switch in the same way.
Code: [Select]
.while arg
.switch arg
.while arg
.endw
.endsw
.endw

From the copy sample used above:
Quote
Duff realized that to handle cases where count is not divisible by eight, the assembly programmer's technique of jumping into the loop body could be implemented by interlacing the structures of a switch statement and a loop, putting the switch's case labels at the points of the loop body that correspond to the remainder of count / 8:

Code: [Select]
register n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7:      *to = *from++;
case 6:      *to = *from++;
case 5:      *to = *from++;
case 4:      *to = *from++;
case 3:      *to = *from++;
case 2:      *to = *from++;
case 1:      *to = *from++;
} while (--n > 0);
}

https://en.wikipedia.org/wiki/Duff%27s_device (https://en.wikipedia.org/wiki/Duff%27s_device)

In ASM it will be something like this:
Code: [Select]
.switch eax
  .case 0: .repeat : movsb
  .case 7: movsb
  .case 6: movsb
  .case 5: movsb
  .case 4: movsb
  .case 3: movsb
  .case 2: movsb
  .case 1: movsb : .untilcxz
.endsw
Title: Re: High Level Language in MASM
Post by: nidud on May 03, 2016, 08:53:42 AM
Some small adjustments to the switch.

The offset +- immediate value was not calculated correctly. Only the offset value was used.

An immediate case value above FFFFFFFFh did not generate an error before + 16, so a value of 10000000Fh was accepted.

A level 3 (-W3) warning is generated if a case does not end with a break.

Test case:
Code: [Select]
; v2.20: offset in switch + missing level 3 (-W3) break warning

.386
.model flat
.code
nop
nop
label$:

.switch eax
  .case 1 : mov al,1 ; warning A7008: .case without .endc: assumed fall through
  .case 2 : .endc
.endsw

.switch eax
  .case label$ - 1 : mov al,1 : .endc
  .case label$ - 2 : mov al,0 : .endc
  .case label$    : mov al,2 : .endc
  .case label$ + 1 : mov al,3 : .endc
  .case label$ + 2 : mov al,4 : .endc
.endsw

OPTION SWITCH: PASCAL
;
; should generate the same code (no warning)
;
.switch eax
  .case label$ - 1 : mov al,1
  .case label$ - 2 : mov al,0
  .case label$    : mov al,2
  .case label$ + 1 : mov al,3
  .case label$ + 2 : mov al,4
.endsw

end

In general terms the HLL section should be able to eliminate all labels to prevent any "spaghetti" jumps. For this to be possible it should have at least the same possibilities as C and the current implementation is even more flexible with regards to control flow. The aim must then be to remove restrictions if possible.

To achieve this the break statement is now removed from the switch and replaced with endc. So to write any code based on the HLL section in ASMC may not be a good idea since the whole concept may be rewritten at any time.

In the debate around the balanced stack in the case entry earlier I made a reference to a masm32 example in the hlldemo directory. In the file redit.asm there is a message loop (one of many) that uses a combination of macros and labels to achieve something similar to the above. This sample would also be difficult to write in C without a GOTO statement from the switch given a break would dispatch the message.
Code: [Select]
MsgLoop proc

    LOCAL rval  :DWORD
    LOCAL msg   :MSG

    StartLoop:
      invoke GetMessage,ADDR msg,NULL,0,0
      cmp eax, 0
      je ExitLoop

      Switch msg.message
      ; ------------------------------------
      ; menu hot key processing CTRL+Hotkey
      ; ------------------------------------
        Case WM_KEYDOWN
          mov rval, FUNC(GetAsyncKeyState,VK_CONTROL)
          cmp WORD PTR rval[2], 1111111111111111b
          jne @F
            Switch msg.wParam
              Case VK_A
                invoke Select_All,hEdit
                invoke SendMessage,hEdit,WM_COPY,0,0
                jmp StartLoop
              Case VK_C
                invoke SendMessage,hEdit,WM_COPY,0,0
                jmp StartLoop
              Case VK_N
                invoke SendMessage,hWnd,WM_COMMAND,1000,0
                jmp StartLoop
              Case VK_O
                invoke SendMessage,hWnd,WM_COMMAND,1001,0
                jmp StartLoop
              Case VK_S
                invoke SendMessage,hWnd,WM_COMMAND,1002,0
                jmp StartLoop
              Case VK_V
                invoke SendMessage,hEdit,EM_PASTESPECIAL,CF_TEXT,0
                jmp StartLoop
              Case VK_X
                invoke SendMessage,hEdit,WM_CUT,0,0
                jmp StartLoop
              Case VK_Z
                invoke SendMessage,hEdit,EM_UNDO,0,0
                jmp StartLoop
            Endsw
          @@:
      Endsw
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage,  ADDR msg
      jmp StartLoop
    ExitLoop:

    mov eax, msg.wParam
    ret

MsgLoop endp

Well, the sample uses continue in this case, but the reason to add the endc was to be able to control the inner loop directly from the switch.
Code: [Select]
MsgLoop proc

    LOCAL msg:MSG

    .while GetMessage( ADDR msg, NULL, 0, 0 )
      .switch msg.message
.case WM_KEYDOWN
  GetAsyncKeyState( VK_CONTROL )
  shr eax,16
  .if eax == 1111111111111111b
    mov eax,msg.wParam
    .switch eax
      .case VK_A: Select_All( hEdit ): SendMessage( hEdit, WM_COPY, 0, 0 ): .continue
      .case VK_C: SendMessage( hEdit, WM_COPY, 0, 0 ): .continue
      .case VK_N: SendMessage( hWnd, WM_COMMAND, 1000, 0 ): .continue
      .case VK_O: SendMessage( hWnd, WM_COMMAND, 1001, 0 ): .continue
      .case VK_S: SendMessage( hWnd, WM_COMMAND, 1002, 0 ): .continue
      .case VK_V: SendMessage( hEdit, EM_PASTESPECIAL, CF_TEXT, 0 ): .continue
      .case VK_X: SendMessage( hEdit, WM_CUT, 0, 0 ): .continue
      .case VK_Z: SendMessage( hEdit, EM_UNDO, 0, 0 ): .continue
    .endsw
  .endif
      .endsw
      TranslateMessage( ADDR msg )
      DispatchMessage ( ADDR msg )
    .endw
    mov eax, msg.wParam
    ret

MsgLoop endp
Title: Re: High Level Language in MASM
Post by: nidud on May 06, 2016, 07:55:54 AM
Assigning value directly to registers.

It appear that Masm allow value to be assigned using brackets, so the current situation looks like this:
Code: [Select]
nop

foo proto :dword
foo2 proto :dword, :dword
bar:
mov edx,foo2( 1, 2 ); MASM: error A2008: syntax error : ,
; ASMC: error A2157: missing right parenthesis
mov edx,foo( 1 ) ; mov edx,1
mov edx,bar( 2 ) ; mov edx,3
add edx,foo( 1 ) ; add edx,1
cmp edx,bar( 1 ) ; cmp edx,2
.if edx > foo( 1 ) ; MASM: cmp edx,2
; ASMC: invoke foo, 1 : cmp edx,eax
.elseif edx > bar( 2 ) ; cmp edx,3
.endif
.while edx > foo( 1 ) ; MASM: cmp edx,2
; ASMC: invoke foo, 2 : cmp edx,eax
.endw
.if byte ptr [ebx + foo( 1 )] == '\'
; MASM: cmp byte ptr [ebx+foo+1],'\'
; ASMC: invoke foo, 1 : cmp byte ptr [ebx+eax],'\'
.endif

Normally offsets are calculated using label+imm or label[imm] and in some cases label + (<expression>), so labels are frequently used in expressions. ASMC hooks up the combination "label(", currently only used as HLL arguments, so there is a minor compatibility conflict there already. However I like to extend this functionality to assign value directly registers, but I first need to produce some errors or warnings in order to validate compatibility of existing code.

Another issue that occur, which may also be an issue with MASM/JWASM, is the combination of assigning types to fastcall arguments and debug information. Object produced by ASMC where this was used created an internal error in LINK.

For better readability format strings should be written directly in the functions that use them if possible. The C-string functions have been rewritten and an internal macro added to assign a string value, same as the CStr() macro, returning an offset to a new string or an already existing string in the string stack. All strings used by functions and the @CStr() macro is now added to this stack.
Code: [Select]
mov eax,@CStr( "\tCreate a \"C\" string: %s%d\n" )
mov ebx,@CStr( "string: %s%d\n" )
mov ecx,@CStr( "%s%d\n" )
mov edx,@CStr( "%d\n" )
mov edi,@CStr( "\n" )

Generated code:
Code: [Select]
00000000                    *   .data
                            *    DS0000 db 9,"Create a ",'"',"C",'"'," string: %s%d",10,0
00000000                    *   .code
00000005  BB0E000000            mov ebx,offset DS0000[14]
0000000A  B916000000            mov ecx,offset DS0000[22]
0000000F  BA18000000            mov edx,offset DS0000[24]
00000014  BF1A000000            mov edi,offset DS0000[26]
Title: Re: High Level Language in MASM
Post by: jj2007 on May 07, 2016, 07:25:36 PM
Some small adjustments to the switch.

Can you explain a little bit what exactly happens here?

Code: [Select]
nops 4
mov eax, ecx
int 3
.switch eax
  .case label$ - 1 : mov al,1
  .case label$ - 2 : mov al,0
  .case label$    : mov al,2
  .case label$ + 1 : mov al,3
  .case label$ + 2 : mov al,4
.endsw
nops 4

Code: [Select]
004010EE             ³.  90                 ³nop
004010EF             ³.  90                 ³nop
004010F0             ³.  8BC1               ³mov eax, ecx
004010F2             ³.  CC                 ³int3
004010F3             ³. EB 2B              ³jmp short 00401120
004010F5             ³.  B0 01              ³mov al, 1                         ; Case 7B ('{') of switch switch32g.401120
004010F7             ³. EB 38              ³jmp short 00401131
004010F9             ³.  B0 00              ³mov al, 0                         ; Case 7A ('z') of switch switch32g.401120
004010FB             ³. EB 34              ³jmp short 00401131
004010FD             ³.  B0 02              ³mov al, 2                         ; Case 7C ('|') of switch switch32g.401120
004010FF             ³. EB 30              ³jmp short 00401131
00401101             ³.  B0 03              ³mov al, 3                         ; Case 7D ('}') of switch switch32g.401120
00401103             ³. EB 2C              ³jmp short 00401131
00401105             ³.  B0 04              ³mov al, 4                         ; Case 7E ('~') of switch switch32g.401120
00401107             ³. EB 28              ³jmp short 00401131
00401109             ³   8D40 00            ³lea eax, [eax]
0040110C             ³.  F9104000           ³dd 004010F9                       ; jump table for five cases
00401110             ³.  F5104000           ³dd 004010F5
00401114             ³.  FD104000           ³dd 004010FD
00401118             ³.  01114000           ³dd 00401101
0040111C             ³.  05114000           ³dd 00401105
00401120             ³>  83F8 7A            ³cmp eax, 7A                       ; Switch (cases 7A..7E, 6 exits)
00401123             ³. 7C 0C              ³jl short 00401131
00401125             ³.  83F8 7E            ³cmp eax, 7E                       ; why eax, why 7E??
00401128             ³. 7F 07              ³jg short 00401131
0040112A             ³. FF2485 240F4000    ³jmp near [eax*4+400F24]
00401131             ³>  90                 ³nop                               ; Default case of switch switch32g.401120
00401132             ³.  90                 ³nop

Full code attached.
Title: Re: High Level Language in MASM
Post by: nidud on May 07, 2016, 10:29:07 PM
Quote
why eax

Because eax is used as argument to the switch.

Quote
why 7E??

Because 7E is the maximum value in the switch (label$ + 2).
In the sample the value of label$ is 2:
Code: [Select]
.code
nop
nop
label$:

The minimum value is then 0 (label$ - 2) and the maximum value is 4 (label$ + 2).
Code: [Select]
00000012                        .switch eax
00000012                          .case label$ - 1 : mov al,1 : .endc
00000012  EB28              *   jmp @C0005
00000014                    *   @C0006:
00000014  B001              *   mov al,1
00000016                    *   .endc
00000016  EB35              *   jmp @C0007
00000018                          .case label$ - 2 : mov al,0 : .endc
00000018                    *   @C0008:
00000018  B000              *   mov al,0
0000001A                    *   .endc
0000001A  EB31              *   jmp @C0007
0000001C                          .case label$    : mov al,2 : .endc
0000001C                    *   @C0009:
0000001C  B002              *   mov al,2
0000001E                    *   .endc
0000001E  EB2D              *   jmp @C0007
00000020                          .case label$ + 1 : mov al,3 : .endc
00000020                    *   @C000A:
00000020  B003              *   mov al,3
00000022                    *   .endc
00000022  EB29              *   jmp @C0007
00000024                          .case label$ + 2 : mov al,4 : .endc
00000024                    *   @C000B:
00000024  B004              *   mov al,4
00000026                    *   .endc
00000026  EB25              *   jmp @C0007
00000028                        .endsw
00000028                    *   ALIGN 4
00000028                    *   @C000C:
00000028  00000000          *   dd @C0008
0000002C  00000000          *   dd @C0006
00000030  00000000          *   dd @C0009
00000034  00000000          *   dd @C000A
00000038  00000000          *   dd @C000B
0000003C                    *   @C0005:
0000003C  83F800            *   cmp eax,0
0000003F  7C0C              *   jl @C0007
00000041  83F804            *   cmp eax,4
00000044  7F07              *   jg @C0007
00000046  FF248500000000    *   jmp [@C000C+eax*4-(0*4)]
0000004D                    *   @C0007:

If you add code above label$, the value of label$ increases.
Code: [Select]
nop
nop
db 7Ah dup(0)
label$:
...
000000B8                    *   @C0005:
000000B8  83F87A     * cmp eax,122 ; 7A
000000BB  7C0C              *   jl @C0007
000000BD  83F87E     * cmp eax,126 ; 7E
000000C0  7F07              *   jg @C0007
000000C2  FF248518FEFFFF    *   jmp [@C000C+eax*4-(122*4)]
000000C9                    *   @C0007:

Quote
Switch (cases 7A..7E, 6 exits)

No, there is only 5: 7A, 7B, 7C, 7D, and 7E.

Note: EAX do not have a meaning in this case, so for a real test move EAX label$ + 1, or something in range.
Title: Re: High Level Language in MASM
Post by: nidud on May 07, 2016, 11:14:26 PM
Here's a test case:
Code: [Select]
;
; build: asmc -pe switch.asm
;
    .486
    .model flat, c
    option casemap:none

option dllimport:<msvcrt>
printf proto :ptr byte, :vararg
exit proto :dword
option dllimport:NONE

.code
nop
nop
label$:

main proc
       
.switch eax
  .case 1 : mov al,1 ; warning A7008: .case without .endc: assumed fall through
  .case 2 : .endc
.endsw

.switch eax
  .case label$ - 1 : mov al,1 : .endc
  .case label$ - 2 : mov al,0 : .endc
  .case label$    : mov al,2 : .endc
  .case label$ + 1 : mov al,3 : .endc
  .case label$ + 2 : mov al,4 : .endc
.endsw

OPTION SWITCH: PASCAL
;
; should generate the same code (no warning)
;
mov edi,-1
xor esi,esi
.while sdword ptr edi < 7
db 4 dup(90h)
mov eax,edi
; int 3
.switch eax
  .case label$ - 1 : mov esi,1
  .case label$ - 2 : mov esi,0
  .case label$    : mov esi,2
  .case label$ + 1 : mov esi,3
  .case label$ + 2 : mov esi,4
.endsw
db 4 dup(90h)
printf( "EAX:%2i, ESI:%i\n", eax, esi )
inc edi
.endw

exit( 0 )
main endp

end main

Output:
Code: [Select]
EAX:-1, ESI:0
EAX: 0, ESI:0
EAX: 1, ESI:1
EAX: 2, ESI:2
EAX: 3, ESI:3
EAX: 4, ESI:4
EAX: 5, ESI:4
EAX: 6, ESI:4

If you insert the db 7Ah dup(0) above the label you get no match in the loop.
Code: [Select]
EAX:-1, ESI:0
EAX: 0, ESI:0
EAX: 1, ESI:0
EAX: 2, ESI:0
EAX: 3, ESI:0
EAX: 4, ESI:0
EAX: 5, ESI:0
EAX: 6, ESI:0
Title: Re: High Level Language in MASM
Post by: nidud on May 11, 2016, 06:19:44 AM
I tested the Mirror$ macro and there was an error there (missing break statement in a switch apparently  :P).

Well, here’s the test used:
Code: [Select]
.486
.model flat, stdcall
.code

foo macro reg ; generate codes
bswap reg
exitm  <reg>
endm

bar macro const:req ; no code generated
local string
string equ <>
forc q, <const>
string catstr <q>, string
endm
exitm <string>
endm

ifdef __ASMC__
option asmc:on
endif
.while eax == bar("abc")
nop
.endw
.while foo(eax)
nop
.endw
.while foo(eax) || ecx == bar("123")
nop
.endw
.while eax == bar("abc") || edx == bar("cba") || ecx == bar("123")
nop
.endw
.while eax == bar("abc") || ( edx == bar("cba") && ecx == bar("123") )
nop
.endw
.while eax == bar("abc") && ( eax == bar("cba") || eax == bar("123") )
nop
.endw
.while foo(eax) || ( eax == bar("cba") && eax == bar("123") )
nop
.endw

END

The manual have some info on the switches and options added and changed. Masm style, including the JWasm file, but not in any way complete.

However the RTFM abbreviation may popup :lol:
Title: Re: High Level Language in MASM
Post by: jj2007 on May 11, 2016, 09:29:37 AM
I tested the Mirror$ macro and there was an error there (missing break statement in a switch apparently  :P).

What exactly is the problem? This snippet builds and runs just fine...

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  push Mirror$("em?")
  push Mirror$("robl")
  push Mirror$("he p")
  push Mirror$("'s t")
  push Mirror$("What")
  Inkey esp
EndOfCode
Title: Re: High Level Language in MASM
Post by: nidud on May 11, 2016, 11:01:28 AM
It actually works very well now. I manage to circumvent the parsing problem but there is a special combination of conditions related to expansion of multiple macros. You mention some problem with the Mirror$ macro so this may be related to some test done earlier, but it has to be used in combination with .WHILE or .ELSEIF.

Here’s a crash test that illustrate the problem.
Title: Re: High Level Language in MASM
Post by: nidud on May 12, 2016, 05:02:56 AM
The problem appears to be some old remains of the previous auto-off switch. By removing that it seems to work as expected.

It still rejects some macros but now on an individually basis as oppose to turning off the parsing. These macros were created for Masm anyway so no need for any special handling.

The generated code for FATAL.ASM:
Code: [Select]
; Disassembly of file: fatal.obj
; Wed May 11 20:39:22 2016
; Mode: 32 bits
; Syntax: MASM/ML
; Instruction set: 80386

.386
.model flat


_text   SEGMENT PARA PUBLIC 'CODE'                      ; section number 1

_text   LABEL NEAR
        jmp     ?_002                                   ; 0000 _ EB, 01

?_001:  nop                                             ; 0002 _ 90
?_002:  cmp     eax, 6513249                            ; 0003 _ 3D, 00636261
        jz      ?_001                                   ; 0008 _ 74, F8
        jmp     ?_004                                   ; 000A _ EB, 01

?_003:  nop                                             ; 000C _ 90
?_004:  bswap   eax                                     ; 000D _ 0F C8
        test    eax, eax                                ; 000F _ 85. C0
        jnz     ?_003                                   ; 0011 _ 75, F9
        cmp     ecx, 3355185                            ; 0013 _ 81. F9, 00333231
        jz      ?_003                                   ; 0019 _ 74, F1
        jmp     ?_006                                   ; 001B _ EB, 01

?_005:  nop                                             ; 001D _ 90
?_006:  bswap   eax                                     ; 001E _ 0F C8
        test    eax, eax                                ; 0020 _ 85. C0
        jnz     ?_005                                   ; 0022 _ 75, F9
        jmp     ?_008                                   ; 0024 _ EB, 01

?_007:  nop                                             ; 0026 _ 90
?_008:  cmp     eax, 6513249                            ; 0027 _ 3D, 00636261
        jz      ?_007                                   ; 002C _ 74, F8
        cmp     edx, 6382179                            ; 002E _ 81. FA, 00616263
        jz      ?_007                                   ; 0034 _ 74, F0
        cmp     ecx, 3355185                            ; 0036 _ 81. F9, 00333231
        jz      ?_007                                   ; 003C _ 74, E8
        jmp     ?_010                                   ; 003E _ EB, 01

?_009:  nop                                             ; 0040 _ 90
?_010:  cmp     eax, 6513249                            ; 0041 _ 3D, 00636261
        jz      ?_009                                   ; 0046 _ 74, F8
        cmp     edx, 6382179                            ; 0048 _ 81. FA, 00616263
        jnz     ?_011                                   ; 004E _ 75, 08
        cmp     ecx, 3355185                            ; 0050 _ 81. F9, 00333231
        jz      ?_009                                   ; 0056 _ 74, E8
?_011:  jmp     ?_013                                   ; 0058 _ EB, 01

?_012:  nop                                             ; 005A _ 90
?_013:  cmp     eax, 6513249                            ; 005B _ 3D, 00636261
        jnz     ?_014                                   ; 0060 _ 75, 0E
        cmp     eax, 6382179                            ; 0062 _ 3D, 00616263
        jz      ?_012                                   ; 0067 _ 74, F1
        cmp     eax, 3355185                            ; 0069 _ 3D, 00333231
        jz      ?_012                                   ; 006E _ 74, EA
?_014:  jmp     ?_016                                   ; 0070 _ EB, 01

?_015:  nop                                             ; 0072 _ 90
?_016:  bswap   eax                                     ; 0073 _ 0F C8
        test    eax, eax                                ; 0075 _ 85. C0
        jnz     ?_015                                   ; 0077 _ 75, F9
        cmp     eax, 6382179                            ; 0079 _ 3D, 00616263
        jnz     ?_017                                   ; 007E _ 75, 07
        cmp     eax, 3355185                            ; 0080 _ 3D, 00333231
; Note: Function does not end with ret or jmp
        jz      ?_015                                   ; 0085 _ 74, EB

_text   ENDS

_data   SEGMENT PARA PUBLIC 'DATA'                      ; section number 2

_data   ENDS

END

Code generated by Masm:
Code: [Select]
; Disassembly of file: fatal.obj
; Wed May 11 20:44:02 2016
; Mode: 32 bits
; Syntax: MASM/ML
; Instruction set: 80386

; Error: symbol names contain illegal characters,
; 1 Symbol names not changed

.386
.model flat

@comp.id equ 001220FCH                                  ; 1188092


_text   SEGMENT PARA PUBLIC 'CODE'                      ; section number 1

_text   LABEL NEAR
        jmp     ?_002                                   ; 0000 _ EB, 01

?_001:  nop                                             ; 0002 _ 90
?_002:  cmp     eax, 6513249                            ; 0003 _ 3D, 00636261
        jz      ?_001                                   ; 0008 _ 74, F8
        bswap   eax                                     ; 000A _ 0F C8
        jmp     ?_004                                   ; 000C _ EB, 01

?_003:  nop                                             ; 000E _ 90
?_004:  or      eax, eax                                ; 000F _ 0B. C0
        jnz     ?_003                                   ; 0011 _ 75, FB
        cmp     ecx, 3355185                            ; 0013 _ 81. F9, 00333231
        jz      ?_003                                   ; 0019 _ 74, F3
        bswap   eax                                     ; 001B _ 0F C8
        jmp     ?_006                                   ; 001D _ EB, 01

?_005:  nop                                             ; 001F _ 90
?_006:  or      eax, eax                                ; 0020 _ 0B. C0
        jnz     ?_005                                   ; 0022 _ 75, FB
        jmp     ?_008                                   ; 0024 _ EB, 01

?_007:  nop                                             ; 0026 _ 90
?_008:  cmp     eax, 6513249                            ; 0027 _ 3D, 00636261
        jz      ?_007                                   ; 002C _ 74, F8
        cmp     edx, 6382179                            ; 002E _ 81. FA, 00616263
        jz      ?_007                                   ; 0034 _ 74, F0
        cmp     ecx, 3355185                            ; 0036 _ 81. F9, 00333231
        jz      ?_007                                   ; 003C _ 74, E8
        jmp     ?_010                                   ; 003E _ EB, 01

?_009:  nop                                             ; 0040 _ 90
?_010:  cmp     eax, 6513249                            ; 0041 _ 3D, 00636261
        jz      ?_009                                   ; 0046 _ 74, F8
        cmp     edx, 6382179                            ; 0048 _ 81. FA, 00616263
        jnz     ?_011                                   ; 004E _ 75, 08
        cmp     ecx, 3355185                            ; 0050 _ 81. F9, 00333231
        jz      ?_009                                   ; 0056 _ 74, E8
?_011:  jmp     ?_013                                   ; 0058 _ EB, 01

?_012:  nop                                             ; 005A _ 90
?_013:  cmp     eax, 6513249                            ; 005B _ 3D, 00636261
        jnz     ?_014                                   ; 0060 _ 75, 0E
        cmp     eax, 6382179                            ; 0062 _ 3D, 00616263
        jz      ?_012                                   ; 0067 _ 74, F1
        cmp     eax, 3355185                            ; 0069 _ 3D, 00333231
        jz      ?_012                                   ; 006E _ 74, EA
?_014:  bswap   eax                                     ; 0070 _ 0F C8
        jmp     ?_016                                   ; 0072 _ EB, 01

?_015:  nop                                             ; 0074 _ 90
?_016:  or      eax, eax                                ; 0075 _ 0B. C0
        jnz     ?_015                                   ; 0077 _ 75, FB
        cmp     eax, 6382179                            ; 0079 _ 3D, 00616263
        jnz     ?_017                                   ; 007E _ 75, 07
        cmp     eax, 3355185                            ; 0080 _ 3D, 00333231
; Note: Function does not end with ret or jmp
        jz      ?_015                                   ; 0085 _ 74, ED

_text   ENDS

_data   SEGMENT PARA PUBLIC 'DATA'                      ; section number 2

        db      135 dup (?)                             ; 0000 _

_data   ENDS

END
Title: Re: High Level Language in MASM
Post by: jj2007 on May 12, 2016, 04:12:38 PM
Lines 4133 to 4146. Note that there is no error for line 4140. Apparently, if eax==Mirror$() is fine but .elseif chokes:
Code: [Select]
  .elseif eax==Mirror$(".hlp") || eax==Mirror$(".chm") || eax==Mirror$(".rtf") ;|| eax==Mirror$(".com")
push eax
mov ecx, selLen ; Len(selected text)
.if !eax
mov [edi], eax
.endif
pop eax
.if eax==Mirror$(".hlp") ; *** line 4140, OK *** ; eax=extension of help file
mov eax, HELP_PARTIALKEY ; gt127, so mov
.if ecx<3
m2m eax, HELP_INDEX ; not enough text selected, use index
.endif
invoke WinHelp, hWnd, esi, eax, edi ; edi points to current selected text
.elseif eax==Mirror$(".rtf") ; MasmBasic help

Code: [Select]
... (multiple line 4133 errors)
tmp_file.asm(4133) : error A2026: constant expected
 Mirror$(5)[MasmBasic.inc]: Macro called from
  tmp_file.asm(4133): Main line code
tmp_file.asm(4146) : error A2008: syntax error : typedef
 Mirror$(1)[MasmBasic.inc]: Macro called from
  tmp_file.asm(4146): Main line code
tmp_file.asm(4146) : error A2026: constant expected
 Mirror$(2)[MasmBasic.inc]: Macro called from
  tmp_file.asm(4146): Main line code
tmp_file.asm(4146) : error A2008: syntax error : typedef
 Mirror$(3)[MasmBasic.inc]: Macro called from
  tmp_file.asm(4146): Main line code
tmp_file.asm(4146) : error A2026: constant expected
 Mirror$(5)[MasmBasic.inc]: Macro called from
  tmp_file.asm(4146): Main line code
tmp_file.asm(7691) : error A2008: syntax error : typedef
 Mirror$(1)[MasmBasic.inc]: Macro called from
  tmp_file.asm(7691): Main line code
tmp_file.asm(7691) : error A2026: constant expected
 Mirror$(2)[MasmBasic.inc]: Macro called from
  tmp_file.asm(7691): Main line code
tmp_file.asm(7691) : error A2008: syntax error : typedef
 Mirror$(3)[MasmBasic.inc]: Macro called from
  tmp_file.asm(7691): Main line code
tmp_file.asm(7691) : error A2026: constant expected
 Mirror$(5)[MasmBasic.inc]: Macro called from
  tmp_file.asm(7691): Main line code
Title: Re: High Level Language in MASM
Post by: nidud on May 13, 2016, 04:23:48 AM
I only used .WHILE in the test apparently and .ELSEIF needed some special handling.

Well, here’s a new test:
Code: [Select]
bar macro const:req
local string
string equ <>
forc q, <const>
string catstr <q>, string
endm
exitm <string>
endm

.while eax==bar(".hlp") || \
eax==bar(".chm") || \
eax==bar(".rtf") || \
eax==bar(".com")
nop
.endw

.if edx
nop
.elseif eax==bar(".hlp") || \
eax==bar(".chm") || \
eax==bar(".rtf") || \
eax==bar(".com")
nop
.endif

Title: Re: High Level Language in MASM
Post by: jj2007 on May 13, 2016, 05:58:08 AM
Well, here’s a new test:

No cigar yet :(

Doszip Macro Assembler Version 2.20
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: tmp_file.asm
tmp_file.asm(4125) : error A2008: syntax error : typedef
 Mirror$(1)[MasmBasic.inc]: Macro called from

Code: [Select]
  .if cx=="sc" ; *.asc or *.qsc
call Snippet ; esi points to filename
  .elseif eax==Mirror$(".dll")

Btw versions 11.5. 20:27 and 12.5. 19:56 are both 2.20
Title: Re: High Level Language in MASM
Post by: nidud on May 13, 2016, 06:59:00 AM
The macro seems to work as expected.
Code: [Select]
mtxt equ MIRROR$ ; chokes with JWasm <1.96
Mirror$ MACRO Src:REQ ;;usg: mirror text: cmp eax, Mirror$("Masm")
LOCAL hasQuotes, tmp$
  hasQuotes INSTR <Src>, <">
  ife hasQuotes
hasQuotes INSTR <Src>, <'>
  endif
  if hasQuotes
tmp$ equ <>
FORC char, <Src>
tmp$ CATSTR <char>, tmp$
ENDM
EXITM <tmp$>
  else
push Src
MbFlipP PROTO
call MbFlipP
EXITM emArr$ ; make sure Let reads it properly
  endif
ENDM

.if cx=="sc"
nop
.elseif eax==Mirror$(".dll")
nop
.elseif eax==mtxt(".dll")
nop
.endif

Output:
Code: [Select]
_text   LABEL NEAR
; Note: Length-changing prefix causes delay on Intel processors
        cmp     cx, 29539                               ; 0000 _ 66: 81. F9, 7363
        jnz     ?_001                                   ; 0005 _ 75, 03
        nop                                             ; 0007 _ 90
        jmp     ?_003                                   ; 0008 _ EB, 12

?_001:  cmp     eax, 1819042862                         ; 000A _ 3D, 6C6C642E
        jnz     ?_002                                   ; 000F _ 75, 03
        nop                                             ; 0011 _ 90
        jmp     ?_003                                   ; 0012 _ EB, 08

?_002:  cmp     eax, 1819042862                         ; 0014 _ 3D, 6C6C642E
        jnz     ?_003                                   ; 0019 _ 75, 01
        nop                                             ; 001B _ 90

Try using the /Xc switch to see if that works differently.
Title: Re: High Level Language in MASM
Post by: jj2007 on May 13, 2016, 10:47:47 AM
Try using the /Xc switch to see if that works differently.

That one works like a charm :t

So what is the difference?
Title: Re: High Level Language in MASM
Post by: nidud on May 14, 2016, 01:27:14 AM
Quote
So what is the difference?
Delayed expansion of macros.

In Masm all macros are expanded in the pre-process part of the assembly and the expanded result used in the next stage. Asmc also expands in this process but delays some of the macros used in the HLL section.

In earlier versions of Asmc this was hacked by turning on the /Xc switch if the code became too complicated. Now this have been removed so it needs to handle the late-expansion correctly, hence the extensive testing.

Asmc have a Masm 8 compatible mode in the same way that Masm 8 has a Masm 5.10 compatible mode. The switch /Xc will the be equal the Masm switch /Zm.

/Zm Enable MASM 5.10 compatibility
/Xc Enable MASM 8.0 compatibility

That will be the same as JWasm 2.12:
/Xc Disable ASMC extensions

The problem at hand has to do with the local label counter that was incorrectly reset when the pre-processing was done. As an effect of the delayed expansion, in this case .ELSEIF, the first local in the Mirror$ macro, hasQuotes, was using the label ??0000. This happens to be a global label used by the macro ArgCount in WINDOWS.INC. The value of the label was typedef PROTO :DWORD, hence the typedef error in Mirror$.

So here’s a new test for the Mirror$ macro (whitout the /Xc switch)
Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc

.code

.if eax
.elseif eax==Mirror$(".dll")
.endif

END
Title: Re: High Level Language in MASM
Post by: jj2007 on May 14, 2016, 02:55:13 AM
Works fine :t
Title: Re: High Level Language in MASM
Post by: nidud on May 16, 2016, 10:09:29 PM
The binaries of version 2.20 are now released to the SF site and I created an account at GitHub for the source code.

https://github.com/nidud/doszip (https://github.com/nidud/doszip)
Title: Re: High Level Language in MASM
Post by: jj2007 on May 17, 2016, 12:51:52 AM
The bin\asmc.exe in https://codeload.github.com/nidud/doszip/zip/master works like a charm 8)

Tested with RichMasm, the MasmBasic library and its testbed (770 lines). Build all timings for the latter:
Code: [Select]
  OxPT_Assembler  mlv615 ; 44.0kB, 1070 ms
  OxPT_Assembler  mlv10 ; 44.0kB, 1070 ms
  OxPT_Assembler  JWasm ; 44.0kB, 650 ms
  OxPT_Assembler  HJWasm ; 44.0kB, 940 ms
  OPT_Assembler  asmc ; 44.0kB, 480 ms

Over twice as fast as MASM - you can feel the difference: build all & run is practically immediate :t
Title: Re: High Level Language in MASM
Post by: nidud on May 28, 2016, 09:15:32 AM
Some new changes:
Code: [Select]
Changes in 2.21 - xx xxx 2016
- added byte index to switch OPTION SWITCH:TABLE
- added error A3022: .CASE redefinition : A(val) : B(val)
- added command line switch /swr - use register [R|E]AX in .SWITCH code
- added OPTION SWITCH:REGAX - use register [R|E]AX in .SWITCH code
- added OPTION SWITCH:NOREGS - use stack in .SWITCH code (default)
- added OPTION SWITCH:NOTEST - skip range test in switch-table jump
- fixed bug in inline macro @CStr()

The jump table code is now recursive so multiple tables may be created in one switch. To simplify table creation an option to use [R|E]AX is added.
Code: [Select]
.switch al
  .case 'A','C','D','E','F','G',
'H','I','J','K','L'
  .case 'M'
  .default
.endsw

Code: [Select]
00000004  3C41              *   cmp al,65
00000006  7CFA              *   jl @C000E
00000008  3C4D              *   cmp al,77
0000000A  7FF6              *   jg @C000E
0000000C  50                *   push eax
0000000D  0FBEC0            *   movsx eax,al
00000010  8B0485FCFEFFFF    *   mov eax,[eax*4+@C0010-(65*4)]
00000017  870424            *   xchg eax,[esp]
0000001A  C3                *   retn

Code: [Select]
OPTION SWITCH:REGAX

Code: [Select]
00000004  3C41              *   cmp al,65
00000006  7CFA              *   jl @C000E
00000008  3C4D              *   cmp al,77
0000000A  7FF6              *   jg @C000E
0000000C  0FBEC0            *   movsx eax,al
0000000F  FF2485FCFEFFFF    *   jmp [eax*4+@C0010-(65*4)]

The NOTEST option is short lived and skips the range-test in the jump code. The option is turned off after usage.

Code: [Select]
.switch eax
  .case 'A','C','D','E','F','G','H','I'
.endsw

Code: [Select]
00000004  83F841            *   cmp eax,65
00000007  7C33              *   jl @C000A
00000009  83F849            *   cmp eax,73
0000000C  7F2E              *   jg @C000A
0000000E  FF2485FCFEFFFF    *   jmp [eax*4+@C000B-(65*4)]

Code: [Select]
OPTION SWITCH:NOTEST

Code: [Select]
00000004  FF2485FCFEFFFF    *   jmp [eax*4+@C000B-(65*4)]
Title: Re: High Level Language in MASM
Post by: jj2007 on May 28, 2016, 09:27:21 AM
Code: [Select]
OxPT_Assembler HJWasm32 ; 2.7
OxPT_Assembler HJWasm64 ; 3.0
OPT_Assembler AsmC ; 2.4 secs
:t

Switch testbed is attached - your new code looks pretty fast:
Code: [Select]
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
Assembled with AsmC
23 ms   case 260, MB Switch_ table
230 ms  case 260, MB Switch_ chain
457 ms  case 260, Masm32 switch
6 ms    case 260, AsmC .Switch

23 ms   case 196, MB Switch_ table
178 ms  case 196, MB Switch_ chain
341 ms  case 196, Masm32 switch
6 ms    case 196, AsmC .Switch

24 ms   case 132, MB Switch_ table
127 ms  case 132, MB Switch_ chain
229 ms  case 132, Masm32 switch
6 ms    case 132, AsmC .Switch

23 ms   case 68, MB Switch_ table
76 ms   case 68, MB Switch_ chain
120 ms  case 68, Masm32 switch
6 ms    case 68, AsmC .Switch

23 ms   case 4, MB Switch_ table
24 ms   case 4, MB Switch_ chain
6 ms    case 4, Masm32 switch
6 ms    case 4, AsmC .Switch

2989    bytes for MbTable
4840    bytes for MbChain
4799    bytes for Masm32
4201    bytes for asmc
:t  :t
Title: Re: High Level Language in MASM
Post by: nidud on June 05, 2016, 01:58:46 AM
With regards to using a jump table as the default in a switch, this seems to have the same effect as using SSE instructions. The test case improves but no increased performance in real applications.

The reason why the SSE implementation failed is a combination of bad or unrealistic test cases: A test case for strlen() using a million byte long string when the average length is less than 20 byte. The switch implementation is language creation so writing creates the language. This means that all testing so far is based on assumptions.

In Asmc the switch was introduced in version 2.14 and there are now above 300 switches in the source base. Testing Asmc with and without a jump table benefit the latter both in size and speed. Using a more aggressive table creation by allowing larger tables to be created just adds more code and reduces the speed even further.

Code: [Select]
\masm32\m32lib\*.asm

4953 ClockTicks: v2.16
4235 ClockTicks: v2.21A - 300544 byte
4015 ClockTicks: v2.21B - 298496 byte

Code: [Select]
real_math.asm

6828 ClockTicks: v2.16
6578 ClockTicks: v2.21A - 300544 byte
6390 ClockTicks: v2.21B - 298496 byte

The only benefit using a jump table will then be a sequential array of values within a specific range. This range was set to 4 in v2.21A, which means that cases like 1, 4, 7, 10, and so on will fit in a table potentially 4 times larger than the number of cases. The range in v2.21B is set to 2.

Of all the switches used in the test none of them have a "perfect" sequential array of values, and only a few will fit within the 4-range value, and even less in the 2-range value. This means that the speed tests used is more or less irrelevant for normal usage of the switch. For this reason the table switch is now turned off by default.

The reason why the increased usage of tables slows things down may be a combination of different things. Inserting a large table in a relatively small switch in combination with loops will convert most short jumps to long jumps so that may be a reason. A long jump is 5 bytes compare to 2 for a short, so the size increases in addition to the size of the table.

There are however still benefits from using tables if the condition is right but this seems to be an exception rather than a rule.
Title: Re: High Level Language in MASM
Post by: nidud on September 22, 2016, 09:49:13 AM
Some new changes:
Code: [Select]
Changes in 2.21 - xx xxx 2016
- added 0x prefix for numbers - regress/0x.asm
- added concat of line follow '(' for HLL call(...) - regress/hllconcat.asm
- added OPTION CSTACK (-Cs) to 64-bit - regress/cstack64.asm
- added OPTION LOOPALIGN:0|1|2|4|8|16 - regress/loopalign.asm
- added OPTION CASEALIGN:0|1|2|4|8|16 - regress/casealign.asm
- dllimport:<dll> external proto <no args> (call) error
   call error A2014: cannot define as public or external : <name>
   invoke handle import prefix ([__imp_]<name>), call do not
   if <name>() is dll-import invoke will be used in HLL(call)
   - regress/PE3.ASM
- set OPTION SWITCH:NOTABLE as default
- removed OPTION SWITCH:AUTO
- removed command line switch /swa - Sets jump-table creation to Auto in .SWITCH
- added command line switch /swr - use register [R|E]AX in .SWITCH code
- added OPTION SWITCH:REGAX - use register [R|E]AX in .SWITCH code
- added OPTION SWITCH:NOREGS - use stack in .SWITCH code (default)
- added OPTION SWITCH:NOTEST - skip range test in switch-table jump
- added byte index to switch (64-bit)
- added error A3022: .CASE redefinition : A(val) : B(val)
- fixed bug in inline macro @CStr()

The expansion of the stack using -Cs
Code: [Select]
.x64
.model flat, fastcall
.code

option win64:3, cstack:off ; default is off..

Cs_OFF PROC USES rsi rdi rbx a1, a2, a3, a4
; mov [rsp+8],rcx
; mov [rsp+16],rdx
; mov [rsp+24],r8
; mov [rsp+32],r9
; push rbp
; mov rbp,rsp
; push rsi
; push rdi
; push rbx
; sub rsp,8 + @ReservedStack
sub rsp,rax
mov ecx,a1 ; [rbp+10H]
mov edx,a2 ; [rbp+18H]
mov r8d,a3 ; [rbp+20H]
mov r9d,a4 ; [rbp+28H]
; add rsp,8 + @ReservedStack
; pop rbx
; pop rdi
; pop rsi
; leave
ret
Cs_OFF ENDP

option cstack:on

Cs_ON PROC USES rsi rdi rbx a1, a2, a3, a4
; mov [rsp+8],rcx
; mov [rsp+16],rdx
; mov [rsp+24],r8
; mov [rsp+32],r9
; push rsi
; push rdi
; push rbx
; push rbp
; mov rbp,rsp
; sub rsp,8 + @ReservedStack
sub rsp,rax
mov ecx,a1 ; [rbp+28H]
mov edx,a2 ; [rbp+30H]
mov r8d,a3 ; [rbp+38H]
mov r9d,a4 ; [rbp+40H]
; leave
; pop rbx
; pop rdi
; pop rsi
ret
Cs_ON ENDP

option stackbase:rsp

Cs_RSP PROC USES rsi rdi rbx a1, a2, a3, a4
; mov [rsp+8],rcx
; mov [rsp+16],rdx
; mov [rsp+24],r8
; mov [rsp+32],r9
; push rsi
; push rdi
; push rbx
; sub rsp,8 + @ReservedStack
sub rsp,rax
mov ecx,a1 ; [rsp+40H]
mov edx,a2 ; [rsp+48H]
mov r8d,a3 ; [rsp+50H]
mov r9d,a4 ; [rsp+58H]
; add rsp,8 + @ReservedStack
; pop rbx
; pop rdi
; pop rsi
ret
Cs_RSP ENDP

END
Title: Re: High Level Language in MASM
Post by: jj2007 on September 22, 2016, 10:31:25 AM
What is the purpose of these lines?
Code: [Select]
mov ecx,a1 ; [rbp+10H]
mov edx,a2 ; [rbp+18H]
mov r8d,a3 ; [rbp+20H]
mov r9d,a4 ; [rbp+28H]
Title: Re: High Level Language in MASM
Post by: nidud on September 22, 2016, 10:50:57 AM
Makes the test case use the arguments to see if the offset is calculated correctly:
Code: [Select]
mov ecx,a1 ; [rbp+28H]
mov edx,a2 ; [rbp+30H]
mov r8d,a3 ; [rbp+38H]
mov r9d,a4 ; [rbp+40H]
Title: Re: High Level Language in MASM
Post by: jj2007 on September 22, 2016, 05:03:25 PM
Oh, I see - thanks :P
Title: Re: High Level Language in MASM
Post by: nidud on September 23, 2016, 11:58:06 PM
Added direct assignment of function call after comma (like the rv(...) macro):
Code: [Select]
.486
.model flat, stdcall
.code

foo proc a
ret
foo endp

mov edi,[ebx + foo(0)]
add esi,foo(0xFFFFFFFF)

end
Title: Re: High Level Language in MASM
Post by: nidud on October 02, 2016, 06:49:19 AM
Fixed a bug in getenv() where %AsmcDir% was accepted as %Asmc%. The direct assignment of function call also failed in some cases where the local stack was used.

Added directive .ASSERT to simplify testing using an HLL expression as argument. It expand to .IF !( <expression> ) do exit(msg) where the message is <file>(<line>): <expression> stored in the code segment.

Code: [Select]
.ASSERT <assert_expression>
.ASSERT:[<Handler> | ON | OFF | PUSH | POP | PUSHF | POPF | CODE | ENDS]

Handler
  The assert macro calls this routine if the assert expression is true. By placing the assert code in a subroutine instead of within the body of the macro, programs that call assert multiple times will save space. The default handler name is assert_exit.

ON/OFF
  Main switch. Same as OPTION ASMC:0x81/0x01.

PUSH/POP
  Save and restore the ASMC flag. Stack level is 128.

PUSHF/POPF
  Saves flags using PUSHF[D|Q] before calling handler if set.

CODE/ENDS
  Same as <IF (ASSERT EQ ON)> and <ENDIF>.


Assert code:
Code: [Select]
.assert eax == 0
Expands to:
Code: [Select]
.if  !( expression )
assert_exit()
db "TEST(43): "
db "eax == 0"
db 0
.endif
continue:

assert(exp) as a proc
Code: [Select]
.assert:code
assert_exit:
pop rax
PrintAssertMsg( rax, rax )
exit( 1 )
.assert:assert_exit ; the default name is assert_exit
.assert:ends

assert(exp) as a macro
Code: [Select]
assert macro
lea rcx,$
lea rdx,@F
PrintAssertMsg( rcx, rdx )
exit( 1 )
@@:
exitm<>
endm

.assert:assert ; install new macro handler
Title: Re: High Level Language in MASM
Post by: nidud on October 05, 2016, 10:25:40 PM
Some return-code-size problems

so this fails:
Code: [Select]
.if GetFileAttributesW( __allocwpath( file ) ) == -1

osmaperr()
.endif

the function returns a DWORD value
Code: [Select]
mov rax,-1 - 0xFFFFFFFFFFFFFFFF
mov eax,-1 - 0x00000000FFFFFFFF
cmp rax,-1 - 0xFFFFFFFFFFFFFFFF

The max imm value for CMP is 32-bit so 0x00000000FFFFFFFF is still -1
Code: [Select]
api proc
mov eax,-1
ret
api endp

.if api() == -1 ; cmp 00000000FFFFFFFF,FFFFFFFFFFFFFFFF

Most return codes are in fact still 32-bit in win64 so .IFD, .IFW, and .IFB is added to downsize the compare. This only apply to 64-bit code where a function call is used in HLL.
Code: [Select]
.ifd api() == -1 ; cmp FFFFFFFF,FFFFFFFF
.ifw api() == -1 ; cmp FFFF,FFFF
.ifb api() == -1 ; cmp FF,FF

Same with .ASSERT
Code: [Select]
.assertd api() == -1
.assertw api() == -1
.assertb api() == -1
Title: Re: High Level Language in MASM
Post by: jj2007 on October 05, 2016, 11:01:49 PM
Interesting, HJWasm codes it like this, ML+AsmC choke on both:
Code: [Select]
  int 3
  mov rbx, 1234567812345678h
  cmp rax, 1234567812345678h
; HJWasm32:
; 48 BB 78 56 34 12 78 56 34 12     | movabs rbx, 1234567812345678                  |
; 48 3D 78 56 34 12                 | cmp rax, 12345678                             |

Is that a known issue?
Title: Re: High Level Language in MASM
Post by: nidud on October 06, 2016, 12:03:46 AM
Yes. It was debated earlier with using .CASE imm64.

It's possible to move/push imm64 but not compare.
Title: Re: High Level Language in MASM
Post by: nidud on October 13, 2016, 08:20:19 AM
Version 2.21 is now released to the SF site. It include a complete tool-chain with assembler, linker, library manager and a simple make utility. There is also libraries and include files to create simple console applications for 32 and 64-bit. Asmc and Doszip is made using this.

Some of the tools are made using the -pe switch, so they don't use any external libraries. The tools.zip file include two of them plus a 64-bit test.
Title: Re: High Level Language in MASM
Post by: nidud on June 07, 2017, 08:41:31 PM
Version 2.24J:

Added & as alias for ADDR in proc( &args )

Simple test case (https://github.com/nidud/asmc/blob/master/source/test/windows/1/test.asm):
Code: [Select]
    DialogBoxIndirectParam(rcx, &Dialog, 0, &DialogFunc, NULL);
Title: Re: High Level Language in MASM
Post by: nidud on June 08, 2017, 01:00:03 AM
Latest benchmark result.

\masm32\m32lib\*.asm
Code: [Select]
4852 ClockTicks: \jwasm\jwasm -q @ml.rsp
6396 ClockTicks: \hjwasm\hjwasm32 -q @ml.rsp
4789 ClockTicks: \hjwasm\hjwasm64 -q @ml.rsp
6646 ClockTicks: \hasm\hasm32 -q @ml.rsp
4961 ClockTicks: \hasm\hasm64 -q @ml.rsp
4976 ClockTicks: \uasm\uasm64 -q @ml.rsp
3907 ClockTicks: \asmc\bin\asmc -q @ml.rsp

real_math.asm
Code: [Select]
10311 ClockTicks: \masm32\bin\ml -c -nologo real_math.asm
 8346 ClockTicks: \jwasm\jwasm -q real_math.asm
11903 ClockTicks: \hjwasm\hjwasm32 -q real_math.asm
 8268 ClockTicks: \hjwasm\hjwasm64 -q real_math.asm
12012 ClockTicks: \hasm\hasm32 -q real_math.asm
 8190 ClockTicks: \hasm\hasm64 -q real_math.asm
 8175 ClockTicks: \uasm\uasm64 -q real_math.asm
 6380 ClockTicks: \asmc\bin\asmc -q real_math.asm
Title: Re: High Level Language in MASM
Post by: nikkho on June 08, 2017, 01:42:53 AM
Latest benchmark result.

This is amazing. Specially considering that ASMC 32 bit, is faster than JWASM and UASM 64 bit.
Title: Re: High Level Language in MASM
Post by: Gunther on June 08, 2017, 04:30:22 AM
Hi nidud,

what is required to work with your latest attachment profile.zip?

Gunther
Title: Re: High Level Language in MASM
Post by: nidud on June 08, 2017, 04:56:28 AM
Hi Gunther,

The test assume the following:

\masm32\bin\ml.exe
\jwasm\jwasm.exe
\hjwasm\hjwasm32.exe
\hjwasm\hjwasm64.exe
\hasm\hasm32.exe
\hasm\hasm64.exe
\uasm\uasm64.exe
\asmc\bin\asmc.exe

\masm32\m32lib\*.asm


You may have to edit the .CMD files to correct the path or remove missing binaries.

m32lib.cmd:
Code: [Select]
@echo off
if not exist ti.exe asmc /pe ti.asm
for %%q in (\masm32\m32lib\*.asm) do echo %%q >> ml.rsp
ti \jwasm\jwasm -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \hjwasm\hjwasm32 -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \hjwasm\hjwasm64 -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \hasm\hasm32 -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \hasm\hasm64 -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \uasm\uasm64 -q @ml.rsp >> result.txt
echo ..
del *.obj
ti \asmc\bin\asmc -q @ml.rsp >> result.txt
echo ..
del *.obj
del *.rsp
type result.txt
pause

math.cmd:
Code: [Select]
@echo off
if not exist ti.exe asmc /pe ti.asm
@ti \masm32\bin\ml -c -nologo real_math.asm > result.txt
echo ..
@ti \jwasm\jwasm -q real_math.asm >> result.txt
echo ..
@ti \hjwasm\hjwasm32 -q real_math.asm >> result.txt
echo ..
@ti \hjwasm\hjwasm64 -q real_math.asm >> result.txt
echo ..
@ti \hasm\hasm32 -q real_math.asm >> result.txt
echo ..
@ti \hasm\hasm64 -q real_math.asm >> result.txt
echo ..
@ti \uasm\uasm64 -q real_math.asm >> result.txt
echo ..
@ti \asmc\bin\asmc -q real_math.asm >> result.txt
echo ..
type result.txt
pause
Title: Re: High Level Language in MASM
Post by: nidud on August 27, 2017, 05:09:21 AM
Made some adjustment to the 64-bit table-switch (https://github.com/nidud/asmc/commit/70a862a15a89c38e8a4651bf3b444eb164ca570f). It failed if the argument was 32-bit and tables was created.

Well, this was related to testing this:
It was my pleasure :biggrin:
I was always disappointed with the garbage which that HLL creates in the code section, even MSV$ does the same, now HASM jumped  far, far ahead, as AUDI says:"vorsprung durch technik" :t
The advantage of that is not only clear debug code but we can put more data there to make it faster and it will not bloat the code section.

Tried that too in the beginning but failed to see any advantage thought.

Quote
I have increased span between lowest and highest case from 512 to 2048 and it can be all executed with a few instructions from the above post.
So, if you need a speed for big amount of cases it can span from 0 to 2048

This crashed with the latest build of Uasm (v2.39):
Code: [Select]

    .x64
    .model  flat, fastcall

    option  dllimport:<msvcrt>
    printf  proto :ptr byte, :vararg
    exit    proto :qword

    .data
    error  db "Uasm Error: %d",10,0

    .code

sw_uasm proc val

    .switch ecx

    enum = 0
    repeat 300
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    enum = 600
    repeat 60
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    enum = 1000
    repeat 1000
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    .default
        xor eax,eax

    .endswitch
    ret

sw_uasm endp

main proc

    mov esi,299
    .while esi
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov esi,659
    .while esi >= 600
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov esi,1999
    .while esi >= 1000
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov edi,1000
    .while edi
        mov esi,2000
        .while esi
            invoke sw_uasm,esi
            dec esi
        .endw
        dec edi
    .endw
    invoke exit,0

main endp

    end main

Quote
UASM has a smart logic to use different kind of solution for different types of cases to keep data as small as possible without affecting the speed, however, smart programmer will chose wisely what cases to put together to create optimal code.
In my opinion every programmer is smart, stupid can not be programmer, they can only think that they are ;)

Well, this works:
Code: [Select]

    .x64
    .model  flat, fastcall

    option  dllimport:<msvcrt>
    printf  proto :ptr byte, :vararg
    exit    proto :qword

    .data
    error  db "Uasm Error: %d",10,0

    .code

sw_uasm proc val

    .switch ecx

    enum = 0
    repeat 300
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    enum = 600
    repeat 60
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    enum = 6000
    repeat 2000
%   .case @CatStr(%enum)
    mov eax,enum
    enum = enum + 1
    endm

    .default
        xor eax,eax

    .endswitch
    ret

sw_uasm endp

main proc

    mov esi,299
    .while esi
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov esi,659
    .while esi >= 600
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov esi,7999
    .while esi >= 6000
        invoke sw_uasm,esi
        .if eax != esi
            invoke printf,addr error,esi
            .break
        .endif
        dec esi
    .endw
    mov edi,1000
    .while edi
        mov esi,8000
        .while esi
            invoke sw_uasm,esi
            dec esi
        .endw
        dec edi
    .endw
    invoke exit,0

main endp

    end main

The code size is 62976 byte versus 60416 byte for Asmc.
benchmark:
Code: [Select]
   93 ClockTicks: sw_asmc
  406 ClockTicks: sw_uasm