Jump to content
IGNORED

Wasting a Cycle Not Working


Just Jeff

Recommended Posts

I'm trying to waste 1 cycle here for an in-kernel RESM1 by changing a zero page store to an absolute:

	;sta RESM1						; 3		Change to 4 cycle store
	sta $1300						; 4		Wasting a cycle to delay missile 1

What am I doing wrong? Leaving the store out entirely has the same effect as the absolute store, so I think the memory address might be wrong.

Link to comment
Share on other sites

I didn't bother to look up the correct address for RESM1, so I might have given the wrong one. But what I meant was that if the zero-page address were $nn, then the absolute address would be written in assembly as $00nn, not $nn00-- even though it would be expressed in Little Endian order in the actual machine code.

  • Like 1
Link to comment
Share on other sites

Try sta.w resm1. $0013 = $13 so it probably still assembles as ZP without explicitly saying otherwise with .w

 

My personal feeling is that that's a problem with the assembler, because to my mind it should treat a 4-character hex address as absolute, even if the high byte is $00.

  • Like 1
Link to comment
Share on other sites

 

My personal feeling is that that's a problem with the assembler, because to my mind it should treat a 4-character hex address as absolute, even if the high byte is $00.

Yeah its a little counter-intuitive. We were, after all, writing the 6502 code properly at that point.

Link to comment
Share on other sites

Thank you... What is this doing? I've never seen that syntax.

The assembler would add the value of the RESM1 symbol ($13) to $100 giving an effective address of $0113, forcing the assembler to emit the absolute version of whichever instruction you're using, while exploiting the mirroring of the TIA's address space in the VCS so that the same register is hit in either case.

  • Like 1
Link to comment
Share on other sites

My personal feeling is that that's a problem with the assembler, because to my mind it should treat a 4-character hex address as absolute, even if the high byte is $00.

To the assembler, what it finds after the opcode is a string(text) value that needs to be evaluated into an integer value so it can be used. This occurs even if it is just a "simple number" to us humans because to the assembler everything in the source code is text while it needs to work with binary values. Once evaluated, the assembler has no idea if there were leading zeros or not because $0001, $01, and even just 1 all evaluate to the exact same 32-bit binary value of 1 (and yes, internally dasm uses 32 bit values).

 

For the vast majority of 6502 code you're not worried about cycle exact instructions. I wasn't when I coded on my VIC-20, 64, or 128, until I needed to use custom UART routines to support faster modems.

 

The software routines in the C64 Kernal arent good for much more than 1200 bps any faster and it cant keep up, characters get dropped, and chaos ensues. Some terminal programs for the C64 included their own optimized serial port emulation routines, and could get into the 2400 or 4800 bps range.

Since 6502 systems often have limited resources (like the 4K cartridge limit of the 2600) the usual expectation is the assembler will optimize for space, and every time it uses Zero Page addressing instead of Absolute it saves a precious byte.

 

Knowing that sometimes you do need cycle exact routines, the assemblers include a way for you to override the analysis. In dasm these are known as Force Extensions:

 

EXTENSIONS:

    FORCE extensions are used to force an addressing mode.  In some cases,
    you can optimize the assembly to take fewer passes by telling it the
    addressing mode.  Force extensions are also used with DS,DC, and DV
    to determine the element size.  NOT ALL EXTENSIONS APPLY TO ALL
    PROCESSORS!

	example:    lda.z   charlie

	i   -implied
	ind -indirect word
	0   -implied
	0x  -implied indexing (0,x)
	0y  -implied indexing (0,y)
	b   -byte address
	bx  -byte address indexed x
	by  -byte address indexed y
	w   -word address
	wx  -word address indexed x
	wy  -word address indexed y
	l   -longword (4 bytes) (DS/DC/DV)
	r   -relative
	u   -uninitialized (SEG)

	First character equivalent substitutions:

	b z d	    (byte, zeropage, direct)
	w e a	    (word, extended, absolute)

So if your code is of the rare case of needed cycle specific times, you force it. Kernel routines for the 2600 are a rare case.

  • Like 2
Link to comment
Share on other sites

I understand what you're saying, but I still think that a computer program-- and an assembler is a computer program-- can be programmed to be "intelligent" enough to recognize that "$0013" is a 4-"digit" hex address, and as such it should be able to interpret it as a 2-byte address even though the high byte is 0.

 

Now, if the person using the assembler prefers it to default to one behavior or another-- such as automatically assuming that "$0013" is to be treated as a 2-byte address, or automatically simplifying it to a 1-byte zero-page address-- then a command line switch or .INI file parameter or whatever could be added for that purpose.

 

Having to append extra characters to an opcode seems like a kludge. I'm familiar with that method, even if I haven't written or assembled any 6502 code in several years now, and I understand that it can be useful for forcing the assembler to use a particular address mode-- but in this particular case it seems like it shouldn't be necessary in the first place, because you aren't using it to force the assembler to use a different address mode than otherwise written, you're using it to force the assembler to use the address mode as written.

  • Like 1
Link to comment
Share on other sites

I agree with SpiceWare. The assembler should not care about how you write a value. $0013 is a zero page address. Maybe I like to write all my addresses as words, or, I don't know, $000000000013. I think the way DASM handles this makes perfect sense logically.

 

Spice makes a good point about rare cases, DASM is not exclusively an Atari 2600 compiler. The fact that wasting a cycle on purpose is a common thing in Atari 2600 (kernel) programming, doesn't mean it's a logic thing to assume for any non Atari 2600 exclusive compiler.

Edited by MLdB
  • Like 2
Link to comment
Share on other sites

I think this is a case where the principle of least astonishment pushes you in different directions, depending on the context of your thinking.

 

If you're thinking from a language semantic perspective, when you use "$0013" you might expect dasm to infer that you want the word version of the opcode. If you're thinking about how dasm works with symbol resolution, you'd expect dasm to store the symbol internally with leading zeros and sort out for itself if the zp or word version of the opcode should be used - a kludge would be needed to do otherwise.

 

Being a kludge isn't an argument against it, though. There does already exist a dasm kludge along the same lines. A specified ".w" modifier will be silently changed into a ".wx" or ".wy" modifier, if indexing is discovered after the operand.

 

But I think for the case we're discussing, a kludge isn't warranted. A ".w" modifier with an indexed operand is a clear contradiction. I think a "$0013" operand resulting in a ZP opcode isn't contradictory, even if it might be counter-suggestive to some.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...