ASSEMBLER STANDARDS

Started by BigDumbDinosaur, February 12, 2008, 11:42 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

BigDumbDinosaur

MOS TECHNOLOGY ASSEMBLER SYNTAX STANDARDS

Scattered about the Internet landscape are a number of homegrown 6502/65C02 assemblers free for the downloading.  Unfortunately, many of them don't conform to the original MOS Technology standard developed with the 6502 microprocessor (MPU), which drives us old-time 6502 programmers to drink (we have to blame something for our bad habits).  Variances or outright errors are typically found in instruction mnemonic representation, number radices, operand representation, label/symbol representation, comment delimiters, whitespace rules or assembler pseudo-ops.

For this who are reading this and are contemplating the scratch-development of a 6502 assembler, perhaps the following might be of interest to you.

Mnemonics and Operands
MOS Technology defined a complete set of mnemonics to describe every legal instruction that the MPU can execute, and also defined how to represent the operand with any instruction that can operate on either memory or an MPU register.  For example:

        ASL FLAG        ;Memory is the operand.

        ASL A           ;The MPU accumulator is the operand.

        ASL             ;WRONG!  Any questions?

Any instruction that can operate on memory or an MPU register MUST be followed by an operand to avoid ambiguity.

Number Radices
A radix (plural radices) is a symbol for the base representation of a number.  In almost all assembly language programs, the programmer may freely mix binary, octal, decimal and hexadecimal. 

The correct MOS Technology radices for representing the decimal number 165 would be as follows:

        %10100101       Base 2 or bitwise binary.

        @245            Base 8 or octal.

        165             Base 10 or decimal.

        $A5             Base 16 or hexadecimal.

The MOS Technology standard designated base 10 as the assembler default, which is nearly universal.  However, the C-128's machine language monitor uses hexadecimal as the default base (e.g., LDA #A5 is actually LDA #$A5) and symbolizes decimal numbers with a plus sign (e.g., +165 = $A5 = @245 = %10100101).  The other MOS Technology radices are supported as described above.

Operand Representation
The operand to any MPU instruction or assembler directive (see labels and symbols below) must be in a format that clearly delineates between different addressing modes.  Also, the operand must be in a form that the assembler can evaluate in an unambiguous fashion.  Examples of proper operands are as follows:

        165             165, an eight bit value.

        $3FFF           16383, a 16 bit value.

        165+21          186.

        5+4*2/3         6.

        'A              65, the ASCII value for the uppercase letter A.

        *               The program counter (assembly address).

        *=$2000         Sets the program counter to decimal location 8192.

        *=*+10          Advances the program counter ten locations.

Assignments in all cases are evaluated from left to right with no algebraic precedence.

The assembler should also support the entry of character strings and other data into a static data storage area, which will be discussed below.

Label and Symbol Notation
A label refers to a memory location within a program and is automatically assigned the value of the program counter when assembled.  A symbol (symbolic constant), on the other hand, refers to the explicit assignment of a value by program code.  The difference between a label and a symbol, aside from the manner in which the assignment is made, is that some assemblers allow the value of a symbol to be changed later in the program (reassigned).  On the other hand, a label cannot be changed, and an attempt to do so will cause assembly to halt with an error.

The MOS Technology standard for label and symbol naming states that the name must begin with an alphabetic character, may be followed by up to five alphanumeric characters, and may not be any MPU instruction mnemonic, such as CLC or LDA.  A single character label or symbol cannot be A, X or Y, as those are reserved for representing the MPU registers—the use of single character names is not recommended.  Labels and symbols are not supposed to be case-sensitive, which in practice is seldom observed anymore.  Although I will be using uppercase examples below, I never use uppercase names in any assembly language programs that I develop, as it is too easy to get mixed up.

The size limitation of six characters was due to the modest capabilities of the systems in use at the time of the 6502's development, and is an unnecessary restriction in modern implementations.  Contemporary assemblers (such as the HCD65 C-128 assembler) generally permit much longer names and also allow the use of the underscore character as part of the name.  Hence a symbol such as THE_SIZE_OF_AN_INVENTORY_RECORD is acceptable (although ridiculous).  This could also be done as TheSizeOfAnInventoryRecord, as is often found in Windows software development (and also ridiculous), as a standards-compliant assembler would ignore case.

Some label and symbol examples:

        S_CMMAS   =721            ;customer record master record size

The above creates the symbol S_CMMAS, representing the size of a customer master record, and assigns the value 721 to it.  Following this assignment, any other instruction in the program can (and should) use S_CMMAS when referring to the size of a customer master record, instead of using the hard coded number 721.  It is bad practice to bury "magic numbers" like 721 in code.  Always symbolically represent them in a separate "include" file, where changes can be quickly and easily made if needed.

        A_NUL     =0              ;ASCII <NUL>
        A_LF      =10             ;ASCII <LF>
        A_CR      =13             ;ASCII <CR>

The above creates the symbolic constants A_NUL (ASCII null), A_LF (ASCII linefeed) and A_CR (ASCII carriage return) with the values 0, 10 and 13, respectively.  Again, it is bad practice to hard code such values into programs.

        OPCMMAS *=*+S_CMMAS     ;customer master record image

The above code assigns the location in memory where a customer record will be buffered and reserves S_CMMAS bytes for storage, where S_CMMAS was previously defined as 721.  The expression *=*+S_CMMAS advances the program counter S_CMMAS bytes.  The rest of the program can refer to the record image location with OPCMMAS, such as in the following example:

        LDX #<OPCMMAS
        LDY #>OPCMMAS
        JSR PUTREC

The above example illustrates the MOS Technology standard notation for taking the least significant byte (LSB, represented by <) and most significant byte (MSB, represented by >) of the 16 bit value of OPCMMAS, which we defined in the previous example, and passing the address to a function for processing.

COMMENTS and CODE LINE STRUCTURE
All programs should be sufficiently commented to allow a third party to read and understand what the program is supposed to accomplish.  Uncommented code is a sign of laziness and (in my opinion) programmer ignorance, especially when complex routines are involved.  Nobody's memory is that good that s/he can write a program this year and expect several years hence to recall all the details of what was supposed to happen.

The MOS Technology standard for comments require that they begin with a semicolon (;).  Any text following the semicolon up to the end of the line will be ignored by the assembler, although it will usually be regurgitated in a printed listing as the assembler runs.  Here's a simple example, which also illustrates how a fully formed line of code should appear:

PUTREC  STX IMGPTR              ;store image pointer LSB
        STY IMGPTR+1            ;store image pointer MSB

Note that a fully formed code line (the STX IMGPTR line above) consists of four fields: label, instruction, operand and comment.  The MOS Technology standard requires that the label always start at the left end of the line, followed by whitespace, followed by the instruction mnemonic, followed by whitespace, followed by the operand (if required), followed by whitespace again, followed by the comment, if any.

Whitespace is defined as at least one blank (ASCII 32) or horizontal tab (ASCII 9) character that is not bounded by quotes.  If no label is to be used (e.g., the STY IMGPTR+1 line above), whitespace should start the line as shown above.  Incidentally, MOS Technology never stated how the assembler should behave when it encounters a blank line or one consisting only of whitespace characters.  The logical thing to do would be to discard the line without complaining about it, or add a semicolon to its beginning so it appears on a printed listing as a blank comment line.

PSEUDO-OPS
A pseudo-op (pseudo-operation) is an instruction to which the assembler itself responds, as opposed to one that is assembled into code.  The distinguishing characteristic of a pseudo-op is that it always starts with a period (.).  The standard pseudo-ops required by MOS Technology are:

        .BYTE           Assembles one eight bit value

        .DBYTE          Assembles one big-endian 16 bit value.

        .END            Terminates assembly, even if not at end-of-file.

        .TEXT           Assembles a null-terminated character string.

        .WORD           Assembles one little-endian 16 bit value.

As with symbols and labels, pseudo-ops are not supposed to be case-sensitive.  Here are some
syntactically correct examples:

        FLAG    .byte $00

The label FLAG is defined at the current address in the program counter and zero is assembled into that location.

        INPBFR  =$0200
        IPBADR  .WORD INPBFR

The symbol INPBFR refers to a fixed location in memory (an input buffer, in this case, at decimal 512 in RAM).  The label IPBADR is set to the current address in the program counter and the little-endian address of the input buffer INPBFR is assembled at that location.

        DSPTCH  .DBYTE DPADD-1,DPSUB-1,DPMUL-1,DBDIV-1

The above assembles a comma-delimited table of big-endian addresses at location DSPTCH, each address being one location before the actual location to which it refers.  If the following are true:

        DPADD   =$2000
        DPSUB   =$2140
        DPMUL   =$22FF
        DPDIV   =$2368

and the program counter is $1000 when assembly of the table occurs, RAM will appear as follows:

        >1000 1F FF 21 3F 22 FE 23 67

A typical use for the above table would be as follows:

        LDX #INDEX              ;table index
        LDA DSPTCH,X            ;routine-1 MSB
        PHA                     ;setting up a return address
        LDA DSPTCH+1,X          ;routine-1 LSB
        PHA
        RTS                     ;goto routine

The above is an example of the 6502 machine code equivalent of an ON GOTO statement in BASIC.  By the way, this unorthodox technique works because RTS, in pulling the "return address" from the stack, will increment it before loading it into the MPU's program counter.  Hence the MPU will go to the selected routine's real address, not the address minus one. 

        TITLE   .TEXT 'C-128 80 Column Display Manager'

The above assembles the null-terminated character string C-128 80 Column Display Manager and stores the string starting at memory location TITLE, which will be whatever the program counter happens to be when the code is encountered.  An alternate way of accomplishing the above would be:

        TITLE   .BYTE 'C-128 80 Column Display Manager',A_CR,A_LF,A_NUL

which allows characters that can't be entered from the keyboard to be included in the string.  Each character bounded by the single quites ('') is assembled with its ASCII value into memory.  Values defined by symbols (e.g., A_CR) are assembled in the order shown.  Commas are used to delimit values, as the entire series of bytes is treated as a single operand by the assembler.  Note the use of the symbolic representation for the carriage return, linefeed and null characters, rather than hard-coded numbers.

Incidentally, to get a single quote into the string you would code as follows:

        TITLE   .BYTE 'BigDumbDinosaur''s Software',A_CR,A_LF,A_NUL

Note the BigDumbDinosaur''s construct, which will assemble as BigDumbDinosaur's.

In addition to the above pseudo-ops, others may be supported to control assembly.  This would include macro-instructions (macros were not part of the original MOS Technology-supplied assembler), listing controls, conditional assembly, and so forth.  The implementation of any of these features would depend on the inclination of the assembler's developer.

The Commodore MADS assembler package only looked at the first, second and third characters of pseudo-ops, which meant that the pseudo-ops .WORD and .WOR were functionally identical.  This, of course, was not in keeping with the MOS Technology standard.
x86?  We ain't got no x86.  We don't need no stinking x86!

hannenz

#1
hey - thanks for this one. this is quite informative.
though, i think - form having written an assembler myself and knowing the demands of a ml programmer towards an assembler - i think some things are not covered yet by this standard and some things should just be handled differently:

1.) the < and > operators for designating low and high byte values of an operand. they are still handled way differently in many assemblers and i didn't find something towards this in the standard. Here someone should clear things up once and forever, on which part of an expression or even whole Pseudo-Directve Line the operands should apply to.
The most frightening thing i ever saw was Power-Assembler who interprets a sequence of expressions in a Psueod-Opcode-INstruction beginning with a < or > operand assigning it to the WHOLE line, like:


  .byte <$400,$500,$600,$700

would assemble to a list of Low bytes only and then on the other hand Power-Assembler wants lines like:

lda <$17

which will assemble to lda IMMEDIATE with $17, even suppressing the addressmode (#) 'modifier' of the instruction, which is the most off-standard i've ever seen.

In my eyes (and that's how I implemented it in my assember) the < and > are unary operators with highest precedence. period. that leads to the next issue, operators, expressions and precedences:

2.) according to the standard, expressions are evaluated from left to right with no precedences. I think this is something like the 6-char-label/ symbol restriction, that should be extinguished. As I did it, I can say, that implementing integer expression evaluation WITH precedences and parenthesis is not too hard to do and doesn't affect assembly times too much and significantly increases readability and clearness of the code. Look at those this line:


lda #<(VIDEORAM + LINE * LINEWIDTH) / (MAX - COLUMN)

which you wouldn't be able to express without parenthesis which seem not to be allowed in the standard.

3.) Why designate single character constants with only one single quote instead of

lda #'a

vs.

lda #'a'

using a closing quote makes the code more readable especially when used in expressions. My assembler allows both notations but i prefer using closing quotes.

4.) The old

ASL A vs. ASL

battle...
i don't understand the standard's argumentation here when speaking of ambigousity. In fact it IS ambigous to write

ASL A

since A could be a symbol as well - ok, the standard simply forbids A, X and Y as symbols but THAT is a workaround in my eyes and NOT a "straight forward" approach...
what's wrong with


ASL


no operand: Register is addressed
has operand: memory is addressed.
there is no ambigouity in this - not in my eyes.
If MOS would be consistent in its argumentation it would have been necessary to design instructions like

INC X

instead of

INX

since X is a MPU register as well.

With the other approach you don't have to limitate the programmer in symbol usage. Why not having a symbol called A, why are one-character-symbols not recommended?? what's wrong with'em? if i design some bitmap plotting routine, for example, it would totally make sense to call one symbol 'X' and another 'Y ' to hold values for coordinates. That is descriptive... and should not be limited by the assembler.

Well, ok. These are my 2 cents about this standard and i sure don't want to "fight" it in any way (sorry, don't know how to express in english) but that is for me a very exciting issue, since i dealt with exact those considerations when i designed my own assembler, not too long ago. I didn't know about the MOS standard at that time - maybe i would have adapted it (would have saved me a lot of work - but would have made the assembler far less powerful!!!)
but now i am lucky not having done so...;)
but what IS right, is that there SHOULD be a standard since implementations of different assemblers are varying too much. But then, I think from a modern point of view the MOS standard should be modified regarding the issues i stated above. that's my opinion and i know you will have another, but that's what life makes interesting, isn't it...;) - i think as an example the syntax of ca65 very good and reasonable, and that is in fact what i orientated at, with the assembler i have written.

if you are curoius, here is the docs to my assembler: http://people.freenet.de/hannenz/as.html
where you can read implementation detail. i would appreciate if you would tell me what you think about it.



EDIT: I am not at home at the moment and just noticed, that there is something wrong with my homepage, the link above doesn't exist forr unknown reasons, as do many others on my site, which shouldn't be so - i'll have to look at that this evening, sorry.

BigDumbDinosaur

#2
Quote from: hannenz on February 12, 2008, 10:15 PM
i think some things are not covered yet by this standard and some things should just be handled differently:

1.) the < and > operators for designating low and high byte values of an operand. they are still handled way differently in many assemblers and i didn't find something towards this in the standard.

Quote
        LDX #<OPCMMAS
        LDY #>OPCMMAS
        JSR PUTREC

The above example illustrates the MOS Technology standard notation for taking the least significant byte (LSB, represented by <) and most significant byte (MSB, represented by >) of the 16 bit value of OPCMMAS, which we defined in the previous example, and passing the address to a function for processing.


Carefully re-read the article.  :)  I excerpted the part you may have missed.  Also, re-read the part about strict left-right evaluation with no algebraic precedence for computed addresses, etc..

As for the ASL A vs. ASL argument you are trying to perpetuate, the MOS Technology standard was written in 1975 (I have a copy of it in my ancient computing archives).  The fact that the first manufacturer of the 6502 defined the assembly language syntax is what makes it the standard.  Your notion that an instruction like ASL doesn't need an operand unless it is working on memory is wrong, wrong, WRONG!  MOS Technology wrote the standard, not you or me.  How about if we all read from the same book on this, eh?
x86?  We ain't got no x86.  We don't need no stinking x86!

hydrophilic

The standard is "ASL A" however there is no ambiguity to write "ASL" since without a memory operand it must refer to the Accumulator; no other register is permitted.

Most assemblers take the practical approach which is to permit both.  This allows old code to be assembled while allowing new, less noisy code.  The only possible problem is if you allow A to be a variable.  Don't allow that.  Other one-letter variable names should be permitted; registers/flags like B, C, D, I, N, P, S, V, and Z can never be used as an operand so there is no ambiguity.  X and Y registers can never be the first operand and the second operand never allows a variable so, again, there would be no ambiguity to allow X and Y as variables.

In my opinion, as long as the code is not ambiguous, the assembler should shut up and produce code.

The lack of operator precedance is something that should also be abandoned.  An assembler directive to permit the old behavior would be sufficient.

BigDumbDinosaur

Quote from: hydrophilic on February 13, 2008, 11:16 AM
The standard is "ASL A" however there is no ambiguity to write "ASL" since without a memory operand it must refer to the Accumulator; no other register is permitted.

Except that to do so is inconsistent syntax, and violates the standard.  You're sounding a lot like a Microsoft programmer, where, if they could, they'd throw away all the standards.

ASL can work on the accumulator or memory, either of constitutes an operand.  MOS Technology's requirement that ASL or similar accumulator/memory instructions have an operand, whether memory or accumulator, simply follows the standard for other instructions that require an operand.  For example, BIT (in the NMOS part) works only on zero page or absolute memory, and therefore requires an operand (e.g., BIT $12 or BIT $1234).  ASL with no operand doesn't make sense, since it is able to work on memory, as well as the accumulator, the latter being an operand!  Until recently, I never saw an assembler that didn't expect an operand after any instruction that works on accumulator/memory.

Quote
Most assemblers take the practical approach which is to permit both.  This allows old code to be assembled while allowing new, less noisy code.

That should be a configurable option, not a default.  What you seem to be missing is that if an assembler silently allows an instruction like ASL to exist with no operand, you have opened the door to anomalous behavior.  If the programmer accidentally forgets to provide an operand to ASL when he meant to shift memory, not the accumulator, the assembler won't know that and will generate wrong code, when it should be reporting a syntax error.  I can see that language development is not your day job.  <Grin>

Quote
The only possible problem is if you allow A to be a variable.  Don't allow that.

I stated that in my diatribe, as does MOS Technology in their standard.

Quote
Other one-letter variable names should be permitted; registers/flags like B, C, D, I, N, P, S, V, and Z can never be used as an operand so there is no ambiguity.  X and Y registers can never be the first operand and the second operand never allows a variable so, again, there would be no ambiguity to allow X and Y as variables.

I never use one letter variables, as they are mostly meaningless in a large program.  Gee, what does A mean?  Does that mean I got an A in computer science or is the first letter of a well-known word used to described obnoxious public officials?

Quote
In my opinion, as long as the code is not ambiguous, the assembler should shut up and produce code.

That attitude has caused many problems with amateur Commodore software development, and reminds me of all the problems it caused in the C world prior to the ANSI standardization.  K&R C lacked consistency in several areas that would cause different compilers to do different things with the same code, often in the way evaluation was carried out at run-time.  Almost all of those consistency issues were the result of nothing more than boneheaded, know-it-all compiler designers who didn't bother read the K&R whitebook and learn the language syntax standard.  Your thinking reminds of several such programmers I worked with back in the day.

ANSI's efforts stabilized the language and assured that everyone was getting the same results from their compilers.  We should be looking for the same in any new assemblers that might get developed for 6502 use.  The assembler should default to the MOS Technology NMOS standard (except label and symbol lengths, which should be relaxed), and options should provided that can be used to deviate from the standard IF NEEDED.  For example, the UNIX 6502 assembler I use is 100 percent MOS Technology compliant (except label name length, which can be up to 32).  Command line options can tell it to assemble 65C02 or 65C816 instructions, as well as change the manner in which expressions are evaluated or relax syntactical standards (the latter which I never use).  If no such options are used, it acts exactly like a MOS Technology compliant NMOS assember (except very fast: it can assemble about 6000-8000 lines of code per second).

Since the C64 and C-128 have NMOS MPUs, I can run the assembler by merely typing mosasm -xl <list> <source> <object> and it assembles an executable binary <object> from <source> with the assembly listing in <list> (the -x option means to prepend a little-endian load address to the object file, which makes it Commodore compatible).  If all I want to do is check the source for syntax, missing references, etc., I just omit the object file name, and all I get is a listing that I can examine for errors.  No matter what, I get the right results every time because the assembler isn't making assumptions about what I'm trying to do.  Of course, that doesn't mean the finished program will actually work... =D

Quote
The lack of operator precedance is something that should also be abandoned.  An assembler directive to permit the old behavior would be sufficient.

Au contraire!  An assembler directive/option to permit NEW behavior should be provided.  Why would you assume that the new behavior should be the default?  If I did that with my code, everything would be wrong!  I don't want anything to do with an assembler like that.
x86?  We ain't got no x86.  We don't need no stinking x86!

hydrophilic

Quote from: BigDumbDinosaurAu contraire!  An assembler directive/option to permit NEW behavior should be provided.

Sounds good to me.  I think you did a nice job telling us about the original standards, but I wonder if an agreement can be reached on missing features.  Macros immediately comes to mind, but I don't want to start on that now.

Uninitialized memory is a big concern. For example, if I am assembling code to $1800 and I want to reference variables in zero page or for page 3 for example, I have to, accroding to the MOS standards, do something like

sqtop   = $300
sqleft  = sqtop+1
sqbot   = sqleft+2
sqright = sqbot+1

Its not immediately clear how many bytes each variable uses, and much worse, if you need to reorder your variables for any reason, you have to change the equates.  This is highly error prone!

A better method some assemblers allow is like

.bss $300
sqtop   .dsb 1
sqleft  .dsb 2
sqbot   .dsb 1
sqright .dsb 2

This makes it immediatly obvious how much memory each variable requires and you can reorder them without changing their definition.  I like the approach but often such assemblers limit you to 3 or 4 such memory segments: program text, program variables, and unitialized variables (hopefully two of these, zero page and not).

I think the best approach would be to allow an unlimited number of named memory spaces.  Like

.seg basic $4000
.seg bitmap $2000
.seg vectors $300
.seg matrices $1800
.seg io $d000
.seg kernal $e000
.seg cartridge $8000

That being an example of definitions without any variables declared.

Another thing not in the standards that is often essential is an alignment directive.  Even if an assembler allows .ALIGN, most force you to use some arbitrary set of multiples like 2, 4, 8 or 256.  Drives me mad, mad, mad!

I think an align directive should take the form
.ALIGN multiple, offset
where multiple can be any positive number, and offset can be any positive number less than multiple.

Some examples assuming the current PC is $1021:
.align $10 ;next code/variable at $1030
.align $20 ;next code/variable at $1040
.align $20,7 ;next code/variable at $1047
.align $27 ;next code/variable at $1026 ($27*$6A)

I think this is possible with the MOS standard if use
* = (*+multiple-1)/multiple*multiple+offset
Of course this is not very clear and requires parenthesis.  You could use a temp variable instead of parenthesis but that makes it even worse.

Code relocation is another important thing that could use some standards but I'll save that for another time.

hannenz

@BDD: i got your point now. really.
but for one thing: i still claim, that ASL A is inconsistent syntax, since it is INX and not INC X as an example but let's not start a war about this one... i understand that the standard is needed to get same results for same code, and so i take it as it is.
oh and what about parenthesis now? are they allowed to change evaluation precedence or not??

@hydropholic: what you are talking about isn't a matter of the MOS standard, since the standard allows extensions by use of Pseudo-Opcodes, so any kind of implementation of an .ALIGN pseudo or .BSS/.DSEG call-it-what-you-want can be done without violating the standard, if i got it right now. same is for Macros (which are Pseudo's in fact).
When it comes to relocation, you might want to have a look at the object files, Power-C and its assemblers produces: relocatable object files (containing meta-data) which are linked in a seperate stage (similar to c65/ ca65/ ld65). if you want more info on these, just tell me...


BigDumbDinosaur

Quote from: hannenz on February 15, 2008, 08:57 AM
@BDD: i got your point now. really.
but for one thing: i still claim, that ASL A is inconsistent syntax, since it is INX and not INC X as an example but let's not start a war about this one... i understand that the standard is needed to get same results for same code, and so i take it as it is.

C'mon, man!!! Think about it!!!  INX (INY) operate on registers only, which means they CANNOT take operands.  Damn!  If you don't like the MOS Technology assembler standard look up Chuck Peddle and complain to him.  He wrote most of it.

Quote
oh and what about parenthesis now? are they allowed to change evaluation precedence or not??

As I said above, if an assembler is going to be able to alter evaluation precedence, that should be an option that you TURN ON.  It should not be a default because it will result in anomalous assembly of any program where computed addresses or constants were written to not be algebraically evaluated (that describes all of my programs, BTW).  The general idea is to add non-standard behavior IF WANTED, but don't make it the default.

You need to study software design theory, my friend, as you are trying to make the same errors that many others have made.  As I said, I wouldn't want anything to do with an assembler that ASSUMES that it knows what I want.
x86?  We ain't got no x86.  We don't need no stinking x86!

hannenz

#8
couldn't we calm down to some more relaxed level of conversation?! i am really interested in learning more about this issue and as I said: i got your point now and i understand now that what you are pointing out are serious considerations not thought about by many assembler designers - and  in fact considerations i didn't have in mind by now, too. I don't want to argue with you (nor with "chuck peddle"), i want to learn from you.

you didn't answer my question if parenthesis are allowed or not according to the standard and i couldn't find anything about that in the original post, so please be so kind and give me a simple 'yes' or 'no' (i assume 'no', since they are not mentioned at all in your original post).

the more i think about it the more i admit i agree with you. i even think about rewriting my assembler in being 100% MOS compliant and adding switches/ options for the extra features...

( P.S.: would you agree with me that in the first place the 6502 designers would have better designated one mnemonic INC/ DEC for both: register and memory address modes as we have it with ASL/ ROR ? )

P.P.S.:
what about whitespace within an operand expression such as:


lda somelabel + 17


and what about lines containing only a label, as e.g. my coding style is:

   ldx #0
loop
  txa
  ...
  bne loop
  rts


i assume that MOS standard would complain about both, right ?