6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Jun 22, 2024 10:43 am

All times are UTC




Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Fri May 03, 2013 3:22 pm 
Offline

Joined: Thu Feb 28, 2013 6:34 am
Posts: 16
Location: San Francisco, California
Hi there,

For context, I'm trying to write an s-c compatible assembler that can be used on any platform.

I'm curious as to how people generally implement possibly zero-page instructions with forward references: you can't tell immediately whether the instruction will be two or three bytes long, and changing it later will shift everything around (potentially changing other possibly-zero-page instructions).

I can think of a couple of ways to solve the problem (multiple passes, or remembering what needs to be fixed and iteratively adjusting), but I was wondering if there's a usual, clean approach or normal compromise.

Thanks,

Zellyn


Top
 Profile  
Reply with quote  
PostPosted: Fri May 03, 2013 3:28 pm 
Offline

Joined: Thu Feb 28, 2013 6:34 am
Posts: 16
Location: San Francisco, California
Aah. Failure to search. :-)

viewtopic.php?t=1639


Top
 Profile  
Reply with quote  
PostPosted: Fri May 03, 2013 7:07 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8460
Location: Southern California
I'll mention this since it's hardly mentioned on the linked topic. The easy solution to the usual case is just to always define the variables before using them. In the case of ZP variables, doing them all at once eliminates a lot of ORG directives anyway. If non-ZP variables are to go into the same memory space as the code, ie, the code is in RAM, there's no problem defining those further down the source code, but it should still be before the first reference to them.

_________________
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: Tue May 14, 2013 7:01 pm 
Offline

Joined: Sat Mar 27, 2010 7:50 pm
Posts: 149
Location: Chexbres, VD, Switzerland
I think that assuming zero page, and then extending if required is a nice solution. However, some instructions are zeropage only which is a problem.

ldx $foobar,Y and ldy $foobar,Y comes in mind, but I'm sure they are others.
If you were to have to extend them, it would be impossible without using some extra register (A in this case).


Top
 Profile  
Reply with quote  
PostPosted: Tue May 14, 2013 7:44 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8460
Location: Southern California
Quote:
I think that assuming zero page, and then extending if required is a nice solution.

That would depend on the system. In small ones, you could get most, or all, of the variables in ZP; but in cases where there's a pre-installed OS that uses up most of ZP for system variables, they leave you with almost none. Even if most of ZP is avialable, it may still not be anywhere near enough if you have large arrays.

_________________
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: Tue May 21, 2013 3:10 pm 
Offline

Joined: Sat Mar 27, 2010 7:50 pm
Posts: 149
Location: Chexbres, VD, Switzerland
Did I ever said it was required to put everything in ZP ?!?

I just mean, in the assembler point of view, to resolve instruction like

lda label

you don't know if label is ZP or not, so it is elegant to assume ZP, and expand the instruction to 3 bytes if label is outside of ZP as a second step.

The problem would be for instructions like

ldx label,Y

which will fail if label is not in ZP.

As far I know, ldx zp,Y and ldy zp,X would be the only problematic instructions (for indirect loads, it's obvious the pointer has to be in ZP).


Top
 Profile  
Reply with quote  
PostPosted: Tue May 21, 2013 6:17 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8228
Location: Midwestern USA
Bregalad wrote:
I just mean, in the assembler point of view, to resolve instruction like

lda label

you don't know if label is ZP or not, so it is elegant to assume ZP, and expand the instruction to 3 bytes if label is outside of ZP as a second step.

However, if a yet-to-be-resolved location is assumed to be zero page and is later determined to be absolute, a phase error will occur during the second assembly pass. You'd have to implement a three-pass assembler, in which pass two would correct erroneous ZP references to absolute ones, and pass three would actually assemble the code. That is a lot of hoop-jumping just to compensate for a sloppy programmer's bad habits, I say

Quote:
The problem would be for instructions like

ldx label,Y

which will fail if label is not in ZP. As far I know, ldx zp,Y and ldy zp,X would be the only problematic instructions (for indirect loads, it's obvious the pointer has to be in ZP).

This sort of problem was solved in the 1950s with the development of the two-pass assembler and proper coding techniques. Any assembly language programmer worthy of the name will define all constants and static memory locations—ZP ones, in particular—before any code that refers to them, which results in automatic disambiguation during pass one. Scattering definitions all over the place is in my opinion, the mark of a dysfunctional program—and a disorganized programmer. Excepting rare and well-rationalized cases, no professional would do such a thing.

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


Top
 Profile  
Reply with quote  
PostPosted: Tue May 21, 2013 8:00 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8460
Location: Southern California
Hopefully the assembler would do as many passes as necessary to eliminate the phase errors, with of course the option to stop it if the continuously updated progress report on the screen makes it clear that it's going to take way too long or never finish at all. I had one of those "rare and well-rationalized cases" (as BDD put it) once where it took many passes to eliminate all the phase errors. It was ok though because it still took only 10-15 seconds to finish IIRC. That was about 1990 and I can't remember what the situation was, but I know was not about 8- versus 16-bit addressing. I seem to vaguely remember it had something to do with conditional assembly in macros.

_________________
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: Wed May 22, 2013 9:15 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
... or provide a way to force a zero page or absolute address in the instruction like the WDC assembler does and make the programmer explicitly fix up problems with unresolved labels without doing extra passes.

LDA <LABEL ; Generate a zero-page
LDA |LABEL ; Generate an absolute

_________________
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  
PostPosted: Fri May 24, 2013 1:00 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 672
Is there any real reason to avoid extra passes though? Better to have the computer do more work than make the human add and maintain completely redundant information.

That said, forcing absolute addressing to a $00xx address is required sometimes, but then that's not redundant information.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Fri May 24, 2013 6:38 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8228
Location: Midwestern USA
White Flame wrote:
Is there any real reason to avoid extra passes though?

Probably not with modern hardware. When I assemble the POC V1 BIOS in the Kowalski simulator, it takes at most about three seconds to run through over 11,000 lines of code. If an extra pass can assist in optimizing code, there's certainly no reason to not do it. However...

Quote:
Better to have the computer do more work than make the human add and maintain completely redundant information.

I agree that the programmer shouldn't have to over-extend himself when the computer can do the grunt work. Where I draw the line is in using sloppy habits because the computer (more specifically, the assembler, since we're discussing how to handle ZP addressing) works fast and doesn't complain. Part of good programming practice is organizing the source code so it can be studied and maintained by someone other than the original author. That becomes difficult when the "Commodore 64 BASIC programmer mentality" gets into the picture.

Quote:
That said, forcing absolute addressing to a $00xx address is required sometimes, but then that's not redundant information.

That is usually resolvable on an instruction by instruction basis, e.g., LDA $0021 -> LDA $21 versus JMP $21 -> JMP $0021. The assembler in my POC M/L monitor always assumes direct page addressing when an eight bit is entered for instructions that can use DP addressing.

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


Top
 Profile  
Reply with quote  
PostPosted: Fri May 24, 2013 12:14 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 672
It'll pretty much always boil down to declaring a variable in one place and then using it by name elsewhere, which is hard to make sloppy. Adding a "good practice" constraint about where in order that must happen can sometimes get more messy than allowing it to reside in the organization the programmer chooses, as compile-time decisions and included files can introduce some complex dependencies.

In that last bit, I was specifically meaning where you'd want LDA $21 to be compiled as AD 00 21, instead of A5 21. It's a legitimate zero page address, but you'd want to override the assembler's optimization decision in a few cases: Need to blow an extra cycle for alignment, selfmod it later to other non-zp addresses, use indexing to reach past $00ff, etc. That is legitimate additional intent to communicate to the assembler.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Sat May 25, 2013 12:39 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8228
Location: Midwestern USA
White Flame wrote:
It'll pretty much always boil down to declaring a variable in one place and then using it by name elsewhere, which is hard to make sloppy. Adding a "good practice" constraint about where in order that must happen can sometimes get more messy than allowing it to reside in the organization the programmer chooses, as compile-time decisions and included files can introduce some complex dependencies.

Try using that line of thinking in C. I'm sure that you know you have to declare variables before any part of your program refers to them, and you also have to be mindful of their scope. Prototypes must also be declared before any reference is made to the associated functions. Good practice makes it prudent to declare all variables and prototypes as early in the code as possible, even if INCLUDEs are involved (which they are in all but the most trivial projects). It's all about something called code discipline, the lack of which is common in amateur circles (hence the wisecrack about Commodore 64 BASIC programmers).

In years past when I worked for others as a software developer, a consistently sloppy programmer usually ended up looking for a new job because s/he was writing code that would be difficult to maintain. All professional software development houses have coding standards that programmers are expected to follow, except in (as I said earlier) rare and well-rationalized cases. Someone with a cavalier attitude about program structure (as you seem to intimate) would not have been hired at some of the places where I worked. :)

Quote:
In that last bit, I was specifically meaning where you'd want LDA $21 to be compiled as AD 00 21, instead of A5 21.

As soon as you said "to be compiled as" the rest of your message got lost. Pardon my pedantry. but one does not compile assembly language programs.

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


Top
 Profile  
Reply with quote  
PostPosted: Sat May 25, 2013 4:18 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 672
I'm not talking about cavalier code structure. I'm talking about designed code structure that hits the limits of assumptions that the tools and environment enforce. Attempting to get good code reusability, enabling flexible feature configuration, and optimizing to those selected features using lots of assembly-time directives to configure itself, is where I've hit issues with this the most.

As one small example, inside AcheronVM, instructions are defined as 1-liner macro declarations at the point of instruction implementation. This is the easiest way to be able to add and remove instructions, and is optimal in the "don't repeat yourself" organizational/maintenance sense. The jump tables, opcode allocations, and even generating the include files defining VM instruction -> byte macros, are all done at assembly time, respecting differing types of instruction allocations and alignment concerns. However, even with ca65's great support I still have to hop out into writing external helper programs to do things that should (intuitively) be expressable with the currently available directives; it's ordering and resolving constraints on those directives that limits what you can do with them.


BigDumbDinosaur wrote:
As soon as you said "to be compiled as" the rest of your message got lost. Pardon my pedantry. but one does not compile assembly language programs.

Assembly is a strict subset of compilation (the transformation of code from one form to another), so the use of "compiled" is still technically correct. ;-) (I've got a lot of Lisp on the brain, which regularly and substantially blurs the line.)

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Sat May 25, 2013 9:32 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10832
Location: England
Quote:
Pardon my pedantry
Pedantry not pardoned! As soon as anyone says "as soon as you said..." my heart sinks. Are we trying to have a friendly discussion here, or aiming to score points off one another? Do we have so little interest in the 6502 that we're not prepared to put the effort in to understand what someone is saying? Which in this case is blindingly obvious. Yes, some people say "compiled" when they mean "assembled" - and it hurts no-one. Yes, in an ideal world we'd all use the same words in the same sense, but in this world almost all of us get by without blowing a fuse. This isn't a military academy.
Cheers
Ed


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 17 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: