News:

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

GoAsm 0.55.15 and GoLink 26.7

Started by jorgon, December 24, 2006, 01:57:53 PM

Previous topic - Next topic

jorgon

The latest version of GoAsm available from here:-

  • adds some additional conditional assembly support required to use the header files prepared by the GoAsm Header Project
  • in a structure repeat, now allows the number of repeats to be given by simple equate
  • allows a non-scoped re-usable local code label (eg. "L23:") to be referenced in the same way as a unique label if declared earlier in the same source file (this label does not go into the symbol table though)
  • sorts out recently reported bugs

The latest version of GoLink available from here deals with an error if a hyphen is present in a quoted filename in the command line or file.

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

Wistrik

Hello. I just spent the majority of the afternoon reading the documentation for GoAsm and GoLink because I've been looking for an alternative to Masm. I had a question, a suggestion, and a broken link to point out.

The question, which you've probably been asked before but not here as far as my search has revealed, is why did you choose single-pass assembly over two-pass? Many years ago I wrote an assembler for the 6510 processor in my Commodore 64 and gave it two passes so that I wouldn't have to contend with unresolved forward symbols. Sure, it was a bit slower, but I decided it was a worthy sacrifice, especially since I'm more worried about performance in the application the assembler builds. Besides, even under a 1mhz clock my assembler weighed in at 4k and assembled thousands of lines of code (often itself, in the beginning) in mere seconds. It made generous use of fast, efficient page zero instructions.

The idea for a suggestion came after I read that you always encode forward jumps to unique symbols as absolute, while giving the user a choice of relative or absolute encodings on backward jumps. I suggest allowing the user a similar choice for forward jumps, at their own risk, by using a S (for short) or N (for near) prefix before the mnemonic or before the operand, similar to how GoAsm uses D (dword) and B (byte), etc. Granted, in the 32-bit world it doesn't take long to rack up 128 bytes of code between jumps, but I do try to keep my functions efficient and I make use of 'unique' symbols as a form of commenting. This especially because it may be months/years before I see the source code again, and my verbose documentation habit has been a great lifesaver.

I found a broken link in the documentation for GoLink, under Acknowledgements. The link to Anthony Williams' homepage no longer works; it returns a generic server page. A Google search found him (possibly) at http://alink.sourceforge.net, which seems to be under construction and some pages date back to the year 2000.

I like what you've done with GoAsm and agree with many of the design decisions you made. I was considering writing my own assembler once again, but don't like re-inventing the wheel, and I don't particularly care for the unnecessarily complex file formats that exist these days. I'd have to study all that overhead before I could actually do the easy part: coding the assembler itself. I've used Masm since the 8086 was the top-end processor so I have a lot of history with it, but I don't like some of the things it does. Consequently I've downloaded GoAsm, GoLink, and GoRC to give them a try. I'm running WinXP Pro SP2 so I'll stick with OllyDbg for debugging purposes. Though I'm not in a hurry to jump into the 64-bit wagon, I'll take your suggestions to heart and write code that allows for an easy transition.

Thank you for your research and hard work.

1rDirEctoALgran0

Quote
I suggest allowing the user a similar choice for forward jumps, at their own risk, by using a S (for short) or N (for near) prefix before the mnemonic or before the operand, similar to how GoAsm uses D (dword) and B (byte), etc.

I am agree with that.
But there is no need to create a new syntax, GoAsm has this possibility :

JZ >> Fin ; long form : 4 byte displacement.
NOP
Fin: RET

or

JZ > Fin ; short form : 1 byte displacement.
NOP
Fin: RET

Yes but this second syntax is forced to be assembled like the first syntax.
I think it is possible to implement it but only Jeremy can reply to that.  :eek


Best regards.

jorgon

Hi Wistrik

Welcome to the "Go" tools and welcome to the forum, wow the Commodore 64 takes me back a bit!

QuoteThe question, which you've probably been asked before but not here as far as my search has revealed, is why did you choose single-pass assembly over two-pass?

There has been quite a bit of discussion whether one or two passes is better, but I've never been asked directly (on the forum) why I chose one-pass as far as I recall.  My reasoning is based on the premise that most of the source code will directly use mnemonics and data declarations, as opposed to using macros.  Using two passes would have given the assembler an opportunity to expand the macros on the first pass and then assemble the result on the second pass.  But in order to do this, the assembler would need to look at each word to see if it was in fact a mnemonic or data declaration.  Well if it has to do that, it might as well go on to assemble the source, rather than do that on a second pass.  As for forward references, since the assembler needs to make a table of all code and data labels anyway (to put in the object file to permit the linker to link to those labels from other object files) it is a fairly simple matter to keep a record of all the times that unresolved labels are used, for later resolution.  This was also made easier by using strict syntax for label references, for example requiring a label reference to use ADDR, OFFSET or square brackets.  That was a good idea anyway since it helps to make the source code more understandable.  Restricted scope code labels and re-usable code labels could all be dealt with in the same way.  It is true that the resolution of macros, defines, equates and stuff in brackets may be more intricate in a single-pass assembler but I think GoAsm has dealt with these well.




QuoteThe idea for a suggestion came after I read that you always encode forward jumps to unique symbols as absolute, while giving the user a choice of relative or absolute encodings on backward jumps. I suggest allowing the user a similar choice for forward jumps, at their own risk, by using a S (for short) or N (for near) prefix before the mnemonic or before the operand, similar to how GoAsm uses D (dword) and B (byte), etc.

In answering this question please forgive me if I give a rather full descriptive answer.  This is to make it clear to all GoAsm users, not just to a very experienced assembler programmer like you.

1. Using a "unique code label" merely to label somewhere for the code to jump to within a procedure will not produce the most efficient code.  A unique code label should only really be used to label a code place which might be jumped to or called from another procedure (or from another object file).  This is because GoAsm takes the opportunity to abolish the need for EXTRN by marking all unique code labels as "global".  Such unique code labels find their way into the object file, and also into the symbol list if you make a debug version of your application.

2. So for example you would mostly use a unique code label in this way:-

CALCULATE:
.
.   code goes here
.
RET


3. In the above example, CALCULATE is a unique code label marking the beginning of the procedure.  Your code would probably use this by using the syntax CALL CALCULATE.  There is no short form for calls in 32-bit assembly so nothing can be done to achieve a shorter form.  In the unlikely event that you would want to use JMP CALCULATE instead, the chances are that this would be from more than 127/128 bytes away.  Even if this is not the case, as 1rDirEctoALgran0 points out, the conditional form would assemble short, but really that is not the real answer to this.

4. The real answer to this is that instead of using unique code labels for such jumps, you should use locally scoped re-usable labels or unscoped re-usable labels.  This is why these two additional types of code labels are provided by GoAsm.

5. So for example, this would provide the most compact code (using a locally scoped re-usable label called .fin):-

CALCULATE:
CMP EAX,1
JZ >.fin
.
.   code goes here
.
.fin
RET


6. Here is another example (this time using an unscoped re-usable label called L3)

CALCULATE:
CMP EAX,1
JZ >L3
.
.   code goes here
.
L3:
RET


7. Using these re-usable code label forms within the procedure, instead of unique labels, permits you to code short or long as you require.

I hope this helps to explain this particular design decision and thanks for the report of the broken link.

Incidentally, there will be a new GoAsm version soon, which introduces MACRO..ENDM to help with multi-line macros.  At present multi-line macros require the use of the continuation character and this will not longer be the case.  I am aware that this has not been popular with some users.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)