6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 5:27 pm

All times are UTC




Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Sun Nov 22, 2009 9:09 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
In the topic "Dead CBM PET 3016 help !!" under "General discussions," BigDumbDinosaur wrote:
Quote:
Hence my work on a custom assembler.

What do you have in mind?

One thing I would really like that I have not seen in an assembler so far is to go beyond assembler variables (like EQUates that can be reassigned as many times as you want, which is nothing new), and also have assembler arrays and the ability to use a variable as a pointer into an array. What I would like to do with them is to make one or more stacks in the assembler so I can make assembly program structures in macros, without having to make sure assembler variables used by one structure don't step on those used by other ones that are nested. Being able to write in assembly with nested program structure macros would sure take the confusion out of a lot of pieces of code that are normally written as a pile of spaghetti with gobs of branches to labels. I translated one of Bruce Clark's memory-block-moving routines at http://6502.org/source/general/memory_move.html below. I know it's not the best example, but it should give the idea:
Code:
        ┌───────────────────╖
        │  Regular version  ║
        ╘═══════════════════╝


; Move memory down
;
; FROM = source start address
;   TO = destination start address
; SIZE = number of bytes to move
;
MOVEDOWN LDY #0
         LDX SIZEH
         BEQ MD2
MD1      LDA (FROM),Y ; move a page at a time
         STA (TO),Y
         INY
         BNE MD1
         INC FROM+1
         INC TO+1
         DEX
         BNE MD1
MD2      LDX SIZEL
         BEQ MD4
MD3      LDA (FROM),Y ; move the remaining bytes
         STA (TO),Y
         INY
         DEX
         BNE MD3
MD4      RTS




        ┌──────────────────────╖
        │  Structured version  ║
        ╘══════════════════════╝


MOVEDOWN:
   LDY #0

   LDX SIZEH               ; Get the high byte of the size of block to move.
   IF_NEQ                  ; Do this 1st part if there's at least one full page to move.
      BEGIN                ; Do this loop once for each full page to move.
         BEGIN             ; Do this loop once for each byte in the page.
            LDA (FROM),Y
            STA (TO),Y
            INY
         UNTIL_EQ          ; UNTIL_EQ assembles the BNE up to the BEGIN four lines up.
         INC FROM+1        ; Increment the high byte of the source
         INC TO+1          ; and destination addresses, and
         DEX               ; decrement the number of full pages left to do.
      UNTIL_EQ             ; UNTIL_EQ assembles the BNE up to the corresponding BEGIN.
   END_IF                  ; END_IF puts the branch distance in the BEQ assembled by the
                           ; IF_NEQ above, whose operand's addr was on the assembler stack.

   LDX SIZEL               ; After all full pages have been moved, see if there's part of
   IF_NEQ                  ; one left to do.  If there is, do the following.
      BEGIN                ; Do this loop once for each byte left.
         LDA (FROM),Y
         STA (TO),Y        ; After transferring each byte,
         INY               ; increment the index,
         DEX               ; and decrement the number of bytes left to do.
      UNTIL_EQ             ; UNTIL_EQ assembles the BNE up to the BEGIN 5 lines up.
   END_IF                  ; END_IF puts the branch distance in the BEQ assembled
                           ; by the IF_NEQ above, so a branch taken goes to the RTS below.
   RTS

The two versions lay down exactly the same machine code. [Edit, years later:] I implemented structure macros and documented them at http://wilsonminesco.com/StructureMacros/index.html , adding also FOR...NEXT loops which are more suitable than the BEGIN...UNTIL structures above as they set up the applicable index register and do the incrementing or decrementing and the comparison in a more integrated way:
Code:
MOVEDOWN:
   LDY  #0

   LDX  SIZEH                   ; Get the high byte of the size of block to move.
   IF_NOT_ZERO                  ; Do this 1st part if there's at least one full page to move.
      FOR_X   X_REG, DOWN_TO, 0 ; Do this loop once for each full page to move.  Start w/ current X contents.
         FOR_Y  Y_REG, UP_TO, 0 ; Do this loop once for each byte in the page.   Start w/ current Y contents.
            LDA  (FROM),Y
            STA  (TO),Y
         NEXT_Y                 ; NEXT_Y assembles the BNE up to the LDA (FROM),Y two lines up.
         INC  FROM+1            ; Increment the high byte of the source and
         INC  TO+1              ; destination addresses.  In next line, decr the number of full pages left to do.
      NEXT_X                    ; NEXT_X does the DEX, and assembles a BNE up to the first line after FOR_X above.
   END_IF                       ; END_IF puts the branch distance in the BEQ assembled by the
                                ; IF_NOT_ZERO above, whose operand's addr was on the macro stack.

   LDX  SIZEL                   ; After all full pages have been moved, see if there's _part_
   IF_NOT_ZERO                  ; of one left to do.  If there is, do the following.
      FOR_X   X_REG, DOWN_TO, 0 ; Do this loop once for each byte left.
         LDA  (FROM),Y
         STA  (TO),Y            ; After transferring each byte,
         INY                    ; increment the index.  In next line, decr the number of bytes left to do.
      NEXT_X                    ; NEXT_Y does the DEX, then assembles the BNE up to the first line after FOR_X above.
   END_IF                       ; END_IF puts the branch distance in the BEQ assembled
                                ; by the IF_NOT_ZERO above, so a branch taken goes to the RTS below.
   RTS
 ;----------------
The resulting machine code laid down remains the same.
[End edit]


The IF_NEQ (ie, "if not equal," meaning "if the Z flag is not set") macro assembled the BEQ instruction but with an invalid operand because it doesn't know yet how far down it will have to branch. Then it puts the address of that operand on the stack we formed in the assembler, so that the END_IF macro can fill it in. The same kind of thing will happen with IF...ELSE...END_IF, BEGIN...WHILE...REPEAT, FOR...NEXT (or DO...[LEAVE]...LOOP), CASE...CASE_OF...END_OF...END_CASE, and any other structure you might want.

Since it's a stack, any number of program structures can be nested without interfering with each other. No labels necessary. The macros will also use the stack to pass structure-security values for error-checking. This will alert you to occurrences of, for example, pairing a NEXT with a CASE because you accidentally left something out and had an incomplete structure.

A CASE structure might look like this:
Code:
   CASE A
      CASE_OF $0A
         actions    ; ┐ Do this stuff only
         actions    ; │ if accum was equal
         actions    ; ┘ to $0A (linefeed char)
      END_OF

      CASE_OF $0D
         actions    ; ┐ Do this stuff only
         actions    ; │ if accum was equal
         actions    ; ┘ to $0D (CR char)
      END_OF

      CASE_OF $08
         actions    ; ┐ Do this stuff only
         actions    ; │ if accum was equal
         actions    ; ┘ to $08 (backspace char)
      END_OF

      actions       ; code to execute
      actions       ; for all other cases

   END_CASE


(Substitute appropriate assembly code for "actions.") CASE_OF $0A assembles CMP #$0A, BNE __ , with the BNE operand invalid until the corresponding END_OF fills it in, making the BNE go down to the next part, CMP #$0D, BNE... The END_OFs also lay down an instruction to jump down to the code following END_CASE, and the operands get filled in by the END_CASE macro, without requiring a second pass. After all three particular tests are done (ie, testing for $0A, $0D, and $08), any bytes that did not get caught by those tests will get handled in the code between the last END_OF and the END_CASE. Regardless of what the accumulator contents were initially, after each case is handled, execution normally resumes immediately after END_CASE.

These macros of course are not part of the assembler, but merely show what can be done if the assembler supports assembler arrays so the use can make stacks and form the structure macros. Actually what I showed above is nowhere near exhaustive as far as listing what could be done with them goes. This stuff really is just some Forth internal stuff, which is why I might sound like I've done it before. I have.


The C32 assembler I use from Universal Cross-Assemblers only has one bug that I know of and can think of at the moment: A comma in a quoted string used as a macro parameter will get treated as the delimiter leading to the next macro parameter, even though it's before the double quote that marks the end of the string.

I sure liked the ANSI [Edit: that should say IBM437] graphics characters used by DOS (which I still use in my assembly). They're very useful for drawing diagrams and tables and framing titles in your code. My programmer's text editor that runs under DOS makes it very easy to draw these, almost like it was CAD. I just found out these characters can be had in GUIs also, but probably not in text files that only have 8 bits per character. I drew the shadowed boxes around the titles in the code above this way, but you can do far more with them. That's mostly a function of the text editor of course, but the assembler has to be able to tolerate the special characters without trouble.

I would like to have more freedom in naming labels than most assemblers give. This might require separating arithmetic and logical operators with spaces around them so you could for example have a routine called Read_A/D (read analog-to-digital converter). Without the spaces around the slash, the assembler would not try to actually divide the non-existent "Read_A" by "D". Also, using special characters allows you to have for example ±½°, 100Ω, φ2, or µF.

[Edit, Oct 2014:] I should have added that I don't want labels to be required to start in column 1 (nor do I want them to require their own line). If you can start labels of only local significance in column 2 for example, they will not show up in a text editor's condensed display. This makes it easier to find things, because the condensed display is not cluttered with those. Additionally, I don't want assembler directives (or anything else for the matter) to be required to start with a dot. When things start in the same column for vertical alignment for visual factoring, it looks messy when some lines start with a dot. It makes it look like you tried to align them and were just really sloppy. I want the option to have case sensitivity.


Somewhere I wrote a wish list for an assembler, but I can't find it at the moment, so I'll probably have more ideas trickling in. I'm thinking more seriously again about starting to make my next computer, using the '816, and then I should have enough memory to run an assembler that is much more suited for large projects than what I have on the current workbench computer. Ideally it would no longer be dependent on the PC for development. The assembler I have in ROM in my current workbench computer is minimal and is really only for assembling primitives for Forth, runtimes, subroutines, ISRs, etc., but not a whole application. It does however allow putting more than one instruction on a line, which I like. You can for example do:
Code:
LDA_ZP,X  0    CMP_ZP,X  4    BNE 1$
LDA_ZP,X  1    CMP_ZP,X  5    BNE 1$
LDA_ZP,X  2    CMP_ZP,X  6    BEQ 1$
LDA_ZP,X  3    CMP_ZP,X  7    BEQ 1$

LDA(ZP)    IP                    PHA  INY
LDA(ZP),Y  IP    STA_ZP  IP+1    PLA
                 STA_ZP  IP
INX  INX    JMP POP3

(This is a slight modification of a portion of actual working code.) To straight-line it would take 23 lines.

I know BigDumbDinosaur was probably talking about making an assembler just for his own use, but I thought it would be a good idea to discuss desirable assembler features anyway. BDD, if you do make your assembler available to others, I trust it will be for Linux, even if you do a separate Windoze version.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 22, 2009 10:39 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Hi Garth,

GARTHWILSON wrote:
In the topic "Dead CBM PET 3016 help !!" under "General discussions," BigDumbDinosaur wrote:
Quote:
Hence my work on a custom assembler.

What do you have in mind?
...
What I would like to do with them is to make one or more stacks in the assembler so I can make assembly program structures in macros, without having to make sure assembler variables used by one structure don't step on those used by other ones that are nested.


That was the reason that I implemented ".(" and ".)" block pseudo
opcodes in xa. Labels/variable defined inside a block are invisible to code outside the block (I do have special label definition syntax to break out of the block though).

Quote:
Being able to write in assembly with nested program structure macros would sure take the confusion out of a lot of pieces of code that are normally written as a pile of spaghetti with gobs of branches to labels. I translated one of Bruce Clark's memory-block-moving routines at http://6502.org/source/general/memory_move.html below. I know it's not the best example, but it should give the idea:


But with the macros you loose the ability to hand-optimize code when you need it.

Multiple instructions in one line in xa work by separating them with ":".
I did that to be able to parse old C64 based assembler source that actually looked like:

Code:
10 *=$c000
20 LDA #$00:STA $DC00


Helped a lot for the reuse of that code although not for readability :-)

André


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 12:14 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
My portable assembler has structured code generation very similar to Garth's example. For example
Code:
LockVIA:
        REPEAT
         DEC VIA_LOCK
         IF EQ
          RTS
         ENDIF
         INC VIA_LOCK
         OS_YIELD
        FOREVER

generates this for a 6502 (it would use BRA on a 65C02)
Code:
00FE5B                    : LockVIA:        REPEAT
00FE5B  C6F8              :                  DEC VIA_LOCK
00FE5D  D001              :                  IF EQ
00FE5F  60                :                   RTS
                                             ENDIF
00FE60  E6F8              :                  INC VIA_LOCK
                                             OS_YIELD
00FE62  0001              +                 BRK #$01
00FE64  4C5BFE            :                 FOREVER

OS_YIELD is a macro that generates a BRK. I allow BRK and COP instructions to have an optional immediate byte as an argument.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 2:55 pm 
Offline

Joined: Fri Jun 27, 2003 8:12 am
Posts: 618
Location: Meadowbrook
Would love a hardware simulrtion where you can assign the hardware and use virtual LEDs to represent what goes on. 65C22 in my hardware and 374s and a display. As is, am debugging using the memory dump stepping which works but can be a pain.

_________________
"My biggest dream in life? Building black plywood Habitrails"


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 3:57 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
I find the best assembler to use is Forth. Like Garth, I too have similarly structured, hand-written assembler in Forth and it works fantastically well. Since my (still unfinished, regrettably) Forth compiles to subroutine calls for the most part, mixing high-level Forth and low-level assembly poses no performance hit.

The only difficulty with using Forth, if you can call it that, is it takes greater effort to configure Forth for static compilation (e.g., source file in, object file out, and that's that). It can be done, but Forth prefers being the linker and loader and execution environment too.

But, that's perfectly fine with me. The only time I ever need static compilation is when I'm targeting a processor of a different architecture (e.g., an ATmega processor, for example).


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 3:58 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
I'm encountering the following errors while posting:

Code:
Ran into problems sending Mail. Response: 535 5.7.8 Error: authentication failed

DEBUG MODE

Line : 132
File : smtp.php


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 8:44 pm 
Offline
Site Admin
User avatar

Joined: Fri Aug 30, 2002 1:08 am
Posts: 281
Location: Northern California
kc5tja wrote:
I'm encountering the following errors while posting

We recently moved to a new server and the old server was shut down for good yesterday. This appears to be the last remnant from the old server and should be fixed now.

Regards,
Mike

_________________
- Mike Naberezny (mike@naberezny.com) http://6502.org


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 9:29 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
garthwilson wrote:
I know BigDumbDinosaur was probably talking about making an assembler just for his own use, but I thought it would be a good idea to discuss desirable assembler features anyway. BDD, if you do make your assembler available to others, I trust it will be for Linux, even if you do a separate Windoze version.

The assembler that I am developing will run under the 3GL T-code engine of the Throughbred Dictionary-IV environment (a high-powered, multiuser Business BASIC package). It would be portable in the sense that any Dictionary-IV installation could run it, which covers all UNIX-like operating systems, as well as Window$. However, I seriously doubt the average hobbyist will be eager to cough up the 1500 or so bucks required to get Thoroughbred just so they can run an assembler. :D

I'm using Thoroughbred for this project because it is available to me on my UNIX development box. Hence the only cost involved will be my time and patience (I have nearly infinite amounts of the latter, but much less of the former). I would not undertake this project at all if good, native-mode '816 assemblers that don't need work or are unnecessarily expensive (e.g, WDC's ProSDK) were available.

As for high level language constructs, macros will be as high level as I will get. To me, an assembler is a low-level development environment and adding language structures is creeping featurism, as well as a fine way to introduce complex bugs. If I need a higher level environment I turn to ANSI C, which does a much better job than any assembler of insulating the programmer from the uncouthness of the MPU's instruction set and the underlying hardware. Languages like C were developed precisely for that reason.

BTW, I never put multiple M/L instructions on one line. It's too easy to overlook something when trying to figure out why a program misbehaves.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 22, 2009 9:43 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
fachat wrote:
That was the reason that I implemented ".(" and ".)" block pseudo
opcodes in xa. Labels/variable defined inside a block are invisible to code outside the block (I do have special label definition syntax to break out of the block though).

In the old Commodore Dev-Pak assembler, local symbols could be declared by using the form xx$, where xx was a number (don't recall the permissible range, but it was considerable). The scope of such symbols was bound by the previous and next regular symbol, e.g.:

Code:
print  ldy #0
10$    lda (ptr),y
       beq 20$
       jsr bsout
       iny
       bne 10$
20$    rts
;
get    clc
10$   jsr getin
       ...

Here, the 10$ in the get sub doesn't collide with the same symbol in print.

Quote:
garthwilson wrote:
Being able to write in assembly with nested program structure macros would sure take the confusion out of a lot of pieces of code...


But with the macros you loose the ability to hand-optimize code when you need it.

You make a good point, André. Assembly language is all about tightness and execution speed. As soon as high level structural elements are tossed into the pot, the tightness and speed are lost and, the work to regain it becomes considerable. If the program has become so complicated that high level structure has to get into the picture, perhaps assembly language is not the right choice.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Nov 22, 2009 11:54 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
BigDumbDinosaur wrote:
I would not undertake this project at all if good, native-mode '816 assemblers that don't need work or are unnecessarily expensive (e.g, WDC's ProSDK) were available.

My assembler supports 6502, 65C02, 65816 and 65832. Its free and all you need is a Java runtime environment to run it. The same Java class zip should work on both Windows and Linux.

Might be worth trying before you start building.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 23, 2009 12:29 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
First, congratulations to BitWise for what appears to be an excellent implementation of the structures, built right into his assembler, so the user doesn't have to add any macros to get such functionality!

Quote:
Quote:
What I would like to do with them is to make one or more stacks in the assembler so I can make assembly program structures in macros, without having to make sure assembler variables used by one structure don't step on those used by other ones that are nested.

That was the reason that I implemented ".(" and ".)" block pseudo opcodes in xa. Labels/variable defined inside a block are invisible to code outside the block (I do have special label definition syntax to break out of the block though).

Without seeing it, I'm having trouble envisioning how you could use it for this. You could have variables used in the macros that begin and end a structure for example, and if that block has more structures inside it, especially more of the same kind, it seems like there would be conflicts. Macro local variables won't do the job.

Still, a good part of the discussion is to bring up what features various assemblers have.


Quote:
Quote:
being able to write in assembly with nested program structure macros would sure take the confusion out of a lot of pieces of code that are normally written as a pile of spaghetti with gobs of branches to labels. I translated one of Bruce Clark's memory-block-moving routines at http://6502.org/source/general/memory_move.html below. I know it's not the best example, but it should give the idea:

But with the macros you loose the ability to hand-optimize code when you need it.

No, macros augment—they do not replace or remove—all the older tools and resources. You can still do all the same things you did before, if you want to; it's just that now you don't have to.

If you need something something slightly different, you can always expand it out with the small change if you need to, but usually the better thing is to just write another macro. There's nothing wrong with writing a macro to use just once. It still brings better modularity, without the penalties that a subroutine brings. But something I liked about the macro capability in the 2500AD assembler was that you could say for example, "If there is a 3rd parameter, do such-and-such, and then see if there's a 4th parameter and test it for <yada yada>..." C32, although it has conditional assembly, requires any given macro to always have the same number of parameters, making it less flexible. I suppose you could pad unused parameters with dummy parameters, but that would partly defeat the purpose.

In the assembly source for my '816 Forth, I have one macro in particular that is used many hundreds of times, to make headers. Every use of the macro saves over a dozen lines of source code (most of those lines making decisions and tracking address info for vocabulary threads, not actually laying down code) and makes it far more clear what's happening, and it's not doing anything different from what I would do without macros (except that it's not error-prone). The comma bug I mentioned in the C32 assembler unfortunately does not allow me to have a header with a name "C," or "LDA_ZP,X" (since they have commas), so those macros have to be expanded out and the ugly internals again become visible.


Quote:
As for high level language constructs, macros will be as high level as I will get. To me, an assembler is a low-level development environment and adding language structures is creeping featurism, as well as a fine way to introduce complex bugs.

Ahem—the reason for structures is to make it more manageable and produce fewer bugs in the first place. The book "Thinking Forth" by Leo Brodie, although written in the context of Forth, is really more about good habits in software design, things that you can transfer to many other languages to increase programmer productivity and code reliability and maintainability. I find myself doing those things in assembly, as much as the assembler allows.


Quote:
Assembly language is all about tightness and execution speed. As soon as high level structural elements are tossed into the pot, the tightness and speed are lost and, the work to regain it becomes considerable.

I'm talking about generating the very same object code with more-readable source code. Macros leave you in complete control and there is absolutely zero penalty in runtime speed or memory. The point is to keep all the control and performance of assembly while removing the need to keep seeing all the internal details after you have set them up. In that sense, raising the level of the language by taking maximum advantage of macros is a good thing.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 23, 2009 12:52 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
BigDumbDinosaur wrote:
I would not undertake this project at all if good, native-mode '816 assemblers that don't need work or are unnecessarily expensive (e.g, WDC's ProSDK) were available.


I've had simply stellar success with the ca65 assembler and linker combo. That's what I'm using for my Kestrel series of projects.

Quote:
ANSI C, which does a much better job than any assembler of insulating the programmer from the uncouthness of the MPU's instruction set and the underlying hardware.


Instruction set? Yes.

Underlying hardware? Hardly -- not even close. Consider the constructs *(--p) and *p++, which are PDP addressing modes. In fact, most constructs in C exist because they exist in the PDP in some capacity.

Quote:
BTW, I never put multiple M/L instructions on one line. It's too easy to overlook something when trying to figure out why a program misbehaves.


This is a matter of familiarity and coding style. Personally, I've never run into a problem with multiple statements on a line, as long as they were logically grouped.

The one instruction per line style came about because that's how you have to do it on IBM punch-cards (IBM S/360s, at least at the time, relied on which column something appeared in to indicate its purpose. Labels in column 0, mnemonics in column 8, operands in column 16, etc.). It's also why we have 8-space tabs.

Contemporary assemblers rely on LL or LR grammars, just as C does, so this limitation need no longer apply.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 23, 2009 12:59 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
GARTHWILSON wrote:
Macros leave you in complete control and there is absolutely zero penalty in runtime speed or memory.


Not necessarily. A macro may well end up expanding to 16 or more bytes or significantly high-level constructs. Liberal use of such a macro, then, can significantly impact speed and/or memory, especially if looping is implicit.

That being said, though, what is a high-level language if not essentially a macro language for your target processor? Thinking of macros as a source of incorrectness in programs is the macro library writer's problem, not yours (unless you are said writer). If you don't trust macros, you cannot trust high level languages either, for the same reasons.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 23, 2009 3:21 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
BitWise wrote:
BigDumbDinosaur wrote:
I would not undertake this project at all if good, native-mode '816 assemblers that don't need work or are unnecessarily expensive (e.g, WDC's ProSDK) were available.

My assembler supports 6502, 65C02, 65816 and 65832. Its free and all you need is a Java runtime environment to run it. The same Java class zip should work on both Windows and Linux.

Might be worth trying before you start building.

You download link appears to be broken.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 23, 2009 6:17 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
GARTHWILSON wrote:
Quote:
That was the reason that I implemented ".(" and ".)" block pseudo opcodes in xa. Labels/variable defined inside a block are invisible to code outside the block (I do have special label definition syntax to break out of the block though).

Without seeing it, I'm having trouble envisioning how you could use it for this. You could have variables used in the macros that begin and end a structure for example, and if that block has more structures inside it, especially more of the same kind, it seems like there would be conflicts. Macro local variables won't do the job.


You're right, you can define macros that contain local variables but indeed you can not define something like an "IF" macro and an "ELSE" macro that share the variables.

The way xa65 defines macros is using a cc-like preprocessor that has #IF and #ELSE - but for conditional code generation, not for generating code that executes a kind of IF or ELSE :-)

And one thing I completely forgot:

A 6502 assembler for me needs to be able to produce relocatable code in the form of an .o65 file. After all that's what my operating system needs.

André


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 23 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: