Mini fun quiz: return a boolean in Z

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Mini fun quiz: return a boolean in Z

Post by BigEd »

It's not unusual for a routine to return a byte-sized value in A and a bit-sized value in C.

Suppose you also wanted to return a second bit-sized value, in Z - how would you tackle that?

Extra points for using fewer resources to do it.

For spoiler control, so you don't have to peek at previous responses if you don't want to, I'm going to put a lot of blank lines in - there's nothing more to see.

























nothing to see here






















-eot-
yzoer
Posts: 79
Joined: 11 Nov 2002
Location: Seattle

Re: Mini fun quiz: return a boolean in Z

Post by yzoer »

Doesn't 'bit' perform a logical and between the accumulator and an address? IIRC it leaves the carry intact?

[Edit: It doesn't change the accumulator. So you could do something else here? I.e. ASL/BIT $nnnn]
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Mini fun quiz: return a boolean in Z

Post by BigEd »

Ah, yes, BIT is well-made for that sort of thing. I was thinking of INC or DEC. But you do need a memory location to work with. Maybe that's fine... I was thinking of somehow using stack space. But it all gets rather tangled.
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: Mini fun quiz: return a boolean in Z

Post by White Flame »

BIT could constrain which value you're holding in .A, so I don't think that would be great. If you wanted to return zero in .A and the Z flag unset, that'd be quite difficult to do with just BIT.

I was thinking you'd set up a RAM byte with %000000ZC (with Z inverted), load up .A with your return value, then LSR that byte to set up C and Z.

Alternatively, if you wanted to use the stack instead of a scratch ZP location, push a flag byte to the stack, set up .A, then PLP and RTS. This way might be a few cycles faster, without a read-modify-write instruction involved, but the flags byte also might take a bit more setup than the LSR method.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Mini fun quiz: return a boolean in Z

Post by BigEd »

Ah, PLP, that's a good thought. I'd been thinking about indirecting into the stack, but then you need to use or preserve X, and it's all too much.
User avatar
GaBuZoMeu
Posts: 660
Joined: 01 Mar 2017
Location: North-Germany

Re: Mini fun quiz: return a boolean in Z

Post by GaBuZoMeu »

With a 65802 or 65816 the SEP or REP should work (allthough not tested).

If you use the V Flag instead of Z you may set/clear V before reaching the end of the subroutine where you wish to return with a valid A and C.

The easiest way to return with an additional flag IMHO is using the D flag.


my 2 cents
User avatar
MichaelM
Posts: 761
Joined: 23 Apr 2012
Location: Huntsville, AL

Re: Mini fun quiz: return a boolean in Z

Post by MichaelM »

I vote for White Flame's LSR scheme. :)
Michael A.
CurtisP
Posts: 79
Joined: 10 Feb 2011

Re: Mini fun quiz: return a boolean in Z

Post by CurtisP »

PHA/PLA don't affect the status register at all flag, so maybe something like this:

Code: Select all

;code to calculate byte value
PHA
;code to set C
;code to set Z
PLA
for example

Code: Select all

LDA VALUE  ;Byte to Return
PLA
LDA CARRY  ;Set Carry if Not Zero
CLC
ADC #255
LDA ZERO   ;Set Z if Zero
PHA
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: Mini fun quiz: return a boolean in Z

Post by White Flame »

PHA doesn't affect flags, but PLA does set N and Z to match the newly loaded accumulator value, as with any other load instruction. I also think your example might have PHA/PLA reversed, unless you're doing something even more clever.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Mini fun quiz: return a boolean in Z

Post by Chromatix »

The D flag is easy to set and clear, but hard to test (requires PHP, PLA, BIT#) and interferes with arithmetic if the caller forgets to clear it. The V flag is easy to test but harder to set (though easy to clear) because there's no SEV (unless you're on a 65816). N and Z are easy to test, but are interfered with by almost every ALU operation.

In practice, 6502 software does use the V flag for this purpose since it's corrupted by relatively few instructions - only ADC. SBC, BIT (not #), RTI and PLP. You can set it reliably using LDA #&40, ADC #&40, which also sets N, and clears C and Z. Similar two-instruction sequences (substitute #&80 or #&C0 in the LDA) can leave N and Z in different states, though it's not possible to set both N and Z simultaneously this way. Only BIT is capable of altering Z independently of N, besides directly loading the status register. To preserve N and Z while loading A with the return value, you'll need PHP, PLP.

C, V, N and Z can be set simultaneously in arbitrary combinations using LDA#, PHA, ..., PLP. On CMOS chips you can also build these flags using the index registers. On the 65816 you can set and clear the flags explicitly using SEP/REP.
Post Reply