News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

GoAsm Syntax Additon - Consens Needed ...

Started by madasm, February 02, 2008, 09:56:46 PM

Previous topic - Next topic

madasm

Here you can vote for or against syntax addition.

A major reason, why I like GoAsm is its syntax. The ability to use different labels as locally scoped re-usable or unscoped re-usable labels helps to read and understand code. It is also a good thing that memory access without the use of [brackets] is not allowed. Even if accessing memory without brackets would be unambiguous, it is still better to require brackets because it gives certainty: no [brackets] in a statement always means, there is no read/write to memory.

I think that every syntax addition that makes code clearer should be a strong candidate for addition to existing syntax. If that syntax is also intuitive to use, non-ambiguous to existing syntax and if there is no better suggestion, then the syntax should be added to the language. Considering existing syntax, things like "invoke", "arg", "push <23,24,25>" (implicit pointer push) and "struct", there are already a number of statements that are not pure assembly but that make GoAsm code more readable and easier to write.


Enough introduction, the two suggestions for addition are:

(1) ==Conditionals==

if  eax > 2  &&  [ebx] <= eax    ;As in C: If eax is <= 2, then do not test "ebx <= eax"
     ...
elif  (invoke isDataWaiting) == 0    ;Call procedure isDataWaiting and test if eax == 0
     ...
else
     ...
endi


while  eax != 0
     ...
     if  ecx == 0
          break    ;No "endi" required because the if body has only one statement.
     ...
endw


do
     ...
while  eax != 0  ||  d[ebp – 8] == 4    ;As in C: Do not test "d[ebp – 8]  == 4" if eax <>0


(2) ==Simple-mov==

[ebp -8] = eax    ;Synonym for "mov [ebp -8], eax"
[ebp -8] = invoke GetModuleHandleA, 0    ;Execute right-hand-side and save eax at [ebp -8]


The suggestions are not written as formal syntax because I am looking for an agreement in general. The decision whether the break-statement should also be allowed in the same line as the if-statement or when parenthesis are required should be discussed only after there is a general agreement.
I would appreciate very much if there is support for most of the additions. Jeremy told me that there needs to be some kind of consensus if new syntax is to be added. To me, the above syntax is
(a) intuitive --> Without knowing the syntax, the reader can understand it.
(b) non-ambiguous --> There is a predictable 1-to-1 correlation to assembly opcodes. Thus the compiler will save us from writing non-critical code that makes our program less readable but at the same time we are in full control of what happens to registers and memory.
(c) there is no better suggestion --> Please comment if you have a superior suggestion.

Since the "=" operator is already used to define constants, I suggest to depreciate this feature in favor of the alternative "equ" for constants. Existing code using "=" should still work. The GoAsm compiler just has to test if the left-hand-side operand is inside [brackets] or if it is a register. In these two cases, the "=" is interpreted as the new simple-mov operator.

Looking forward to comments and reasoned opinions for or against this new syntax!

David

madasm

Please do not leave the page without a comment!
If you think that the suggested C-like syntax makes it more difficult to think about what the processor is actually doing, that's fine. By the way, the reason why there is no SELECT CASE is because, as far as I know, the resulting assembler code is not that straight forward than for IF or WHILE. However to me the argument that the suggested syntax makes thinking in assembly too difficult is not understandable if you accept things like FRAME or INVOKE, but maybe I'm wrong?

donkey

Jeremy has repeatedly said that if there is a large enough call for high level constructs then he would consider adding them. I feel they just introduce more code generation into GoAsm, something that GoAsm avoids and IMHO rightly so. For example a runtime IF/ENDIF block simply inserts a large number of unnecessary jumps and condition checks that do little for code efficiency let alone for the instruction cache and branch prediction. My vote is ambivalent, if this is what people want and Jeremy is OK with it then it's fine by me but I doubt I would be using them, if I feel the need to use a high level language I can just start up visual studio.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

James Ladd

I like GoASM because it is rather flat and close to the metal and I don't support these syntax changes.

Instead of adding these constructs to GoASM, why not write a pre-processor that handles this and outputs
GoASM compatible assembler ?

ChrisLeslie

For me, the appeal of GoAsm is the lack of directives, lack of special symbols and the encouragement to maximize coding with symbols that most closely resemble machine instructions. Using .if/.while is a departure from that direction so I do not support it.

Chris

wjr

(1) Not against - however I would most likely not use these. As for allowing invoke into expressions, not so sure about this...
(2) Against - mov is simple enough. Although easier to write, it does not appear to me to improve clarity and even interrupts the "natural" more readable "mnemonic operand(s)" flow. I would not classify the second example with invoke as a simple mov and it may not be as intuitive/non-ambiguous given the other return value registers available to the assembly language programmer.

Ramon Sala

I think GoAsm maybe might have a switch which would enable some high level instructions (like .IF/.ENDIF and .WHILE/.ENDW) for those who like to use them.

Just a suggestion. I do not need them.

Ramon
Greetings from Catalonia

madasm

Hello GoAsm Programmers,

ok there seems to be no support for C-like syntax.
After thinking about conditionals again, I came up with something different (i.e. more Assembler-like).
Basically it's just two simple macros and some special purpose re-usable labels.

The two first suggestions are just simple macros that combine two statements.
The third suggestion is what helps in making logical blocks of codes easy to recognize.
In other words, the labels "while, elseif, endif" will have a special meaning to the programmer because
they are only used in certain conditional and repetititive code. Since the words "while" and "endif" are more
descriptive as e.g. "w2" and "i4", the addition will likely help to make better programs.

=== Syntax suggestion ===
(1)  Jxxif label, eax, 0          ;Equivalent to: "CMP eax, 0"  followed by  "Jxx label"

(2)  INVOKEM myres, proc1, arg1   ;Euquivalent to: "INVOKE proc1, arg1"  followed by  "mov myres, eax"

(3)  GoAsm will accept the repetitive use of while, elseif and endif labels, even if these labels are nested.



=== Example usage ===

;;GoAsm suggestion which behaves like C-if;;
ifJNE endif, eax, 0   ;Equivalent to: "CMP eax, 0" followed by "JNE > endif"
    invoke proc1      ;If body
endif:


;;GoAsm suggestion which behaves like C-else if;;
ifJNE elseif, eax, 0          ;"CMP eax, 0" followed by "JNE > elseif"
    invoke proc1
elseif: ifJNE endif, eax, 0   ;"CMP eax, 0" followed by "JNE > endif"
    invoke proc2
endif:


;;GoAsm suggestion which behaves like C-while;;
jmp > t1                 ;Jump to while test
while:                   ;Begin of while-loop
    dec eax              ;While body
t1: ifJG while, eax, 0   ;Equivalent to: "CMP eax, 0" followed by "JG < while"


;;GoAsm suggestion which behaves like C-nested while;;
jmp > t1                     ;Jump to test of outer while
while:                       ;Begin of outer while
    dec ebx                  ;Body of outer while
    jmp > t2                 ;Jump to test of inner while
    while:                   ;Begin inner while. Use same while label as in outer loop.
        dec eax              ;Body of inner while
    t2: ifJG while, eax, 0   ;Equivalent to: "CMP eax, 0" followed by "JG < while"
t1: ifJG while, ebx, 0       ;Equivalent to: "CMP eax, 0" followed by "JG < while"



OzzY

I'd like something like:

If EAX == 2
    invoke MessageBox, 0, '2', ' ', 0
EndIf

While ECX > 0
   ...
   DEC ECX
EndW

I think it's more readable than CMP/J## because it does not lead to spaghetti code.
Of course not everybody have to use it.
I personally like to use If/While only in big projects for better readabillity.

Maybe it could be implemented with macros? No need for changing the assembler itself.

donkey

I can think of no way to implement the IF/ENDIF stuff as a macro in GoAsm, GoAsm macros are essentially code equates and are therefore very simple. Most GoAsm users, if this thread is any indication, are like me and don't really see the need for high level constructs, especially the ones you posted like "Jxxif label, eax, 0" which is extremely unclear and frankly confusing. I have no objection to high level constructs but highly doubt that I would use them, I left MASM because I was getting increasingly frustrated with the use of macros to turn it into a crippled version of C and programmers insistence in using the macros through all of their code, making it virtually unreadable. There were cases where I saw whole programs without more than 1 or 2 actual mnemonics, just high level and macro crap. I really do think that there are a few places for improvement in GoAsm...

1: support for nested unnamed structures...
MYSTRUCT Struct
   member1 DD
   UNION
      struct
         submem1 DD
         submem2 DD
      ends
      unionmem2 DQ
   ENDUNION
ENDS

2: support for complex include macros that are calculated at compile time...
#define MAKEFOURCC(ch0,ch1,ch2,ch3)  D(B(ch0)|B(ch1)<<8|B(ch2)<<16|B(ch3)<<24)
#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))

3: Native support for CoInvoke and CInvoke

Beyond those few things I have little that I find missing or wanting in GoAsm.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

OzzY

donkey, I agree with you in one point. I never liked MASM32 because of the overuse of macros too. Sometimes I was thinking that using an optimizing C compiler would do the same effect as using MASM32.

My favorite assemblers are FASM and GoASM because both are very simple and get the job done.

BTW... I love how Golink links directly to *.DLL. No need for *.LIB.  :U

madasm

Hey donkey, I just thought about writing a macro to implement the while/if things. However, of course it is not possible because the GoAsm macro language is just like Cs and therefore too basic for anything useful. Somebody already pointed out that I could use my own preprocessor. While an own preprocessor has the advantage of maximum freedom, it wouldn't be GoAsm code but some non-standard thing.
However, of course, if the dominant opinion is that the GoAsm syntax is already sufficient, then there is no need for a powerful macro language.

ChrisLeslie

madasm:
Quote;;GoAsm suggestion which behaves like C-if;;
ifJNE endif, eax, 0   ;Equivalent to: "CMP eax, 0" followed by "JNE > endif"
    invoke proc1      ;If body
endif:
I also toyed with this kind of syntax using FASM or MASM macros (the only two assemblers I know with versatile macro language) but found in the end that the syntax becomes ugly and confusing with overuse and multiple nesting. In the end plain old cmp and jcond was actually more elegant and readable.

donkey:
QuoteI left MASM because I was getting increasingly frustrated with the use of macros to turn it into a crippled version of C and programmers insistence in using the macros through all of their code, making it virtually unreadable. There were cases where I saw whole programs without more than 1 or 2 actual mnemonics, just high level and macro crap.
I don't entirely agree with this if the language we are talking about has the capacity. After all, nearly all languages have the capacity for coder-defined procedures and methods that may dominate the syntax in places. In assemblers, so long as the macro/proc name is self describing, referable from the source and well explained by comments then I see no justification for rejection based on minimal mnemonic use.  I have tried naming all macros with upper case names to make them more identifyable as macros. But for GoAsm, as we know, macros are hardly worth using. GoAsm's muscles lay instead with compelling the use of more processor mnemonics - and that makes it attractive to me.

OzzY:
QuoteBTW... I love how Golink links directly to *.DLL. No need for *.LIB. 
Me too!

Regards

Chris

Synfire

Jeremy added pretty much all the support I needed a long time ago. He was very patient with me and my suggestions, turned down a few but none without sufficient cause, and I honestly can't say I would support such a dramatic change to the language.

As for the 'ifJNE' macro, why can't it do it? I remember clearly Jeremy adding multiline support to GoASM (It was one of the suggestions he gladly added for me). I'm currently at a campus computer but something like this should work:

ifJNE(t,a,b)= \
cmp a, b \
jne t

...
ifJNE(endif, eax, 0)
   invoke proc1
endif:


If you download the include kit I made (Donkey's is by far better) it has a file called WIN32A.INC which acts as a basis bringing everything together. In that file are several multiline macros I find useful, and show how to actually create decent GoASM macros. One of the reasons Jeremy still kept it around even after Donkey released his header project (it's available on the GoASM site).

Regards,
Bryant Keller

Rockoon

I frown on these sorts of macros because they go too far.

Why not "IF Z", "IF NZ", "IF C", and so forth? .. essentialy IF <flag> ?

IF <flag> generates a J<cond>
ELSE generates a JMP (and a label.)
ENDIF generates no instructions (and a label.)

What is the purpose of these high level constructs? In my book their purpose is only to generate those labels. Each macro emits 1 or fewer opcodes and could essentialy be considered an alias for the opcode they generate. IMHO yhats an OK use of code generating structured control macros.

The IFJNE(blah, blah, blah) macros proposed in this thread dont even seem to generate the labels. What advantages does that offer?? They generate more than one opcode, and seemingly for no good reason since they are just as verbose as what is being replaced.

I am not against code generating macros. I accept three kinds..

1) ones that emits precisely 1 opcode (woohoo!)
2) ones that emit many opcodes (code fragments) in a project-specific way (so a constant can control the extent of loop unrolling and so forth)
3) ones that emit precisely 1 opcode per parameter given to it in a well defined and obvious way, in which a lot of effort can be avoided without a single shred of sacrifice (such as an FPU RPN expression evaluator)

I dont even use the popular "m2m" macro.

That proposal for "While ECX > 0 / Wend" is just gross. Surely you would want to always test the exit condition during the return to the top, avoiding that 1 extra branch instruction per iteration.
When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.