So I could just add a dedicated variable (or even use one of the existing 'scratchpad' variables) and just do away with PSHA / PULA?
You don't even need to do that. The way it is written, you can get the value into A with
LDX f2binary ; address of binary to convert
LDAA $01,X
because X was decremented. I would prefer to decrement X at the end of the loop so it is LDAA $00,X but that's cosmetic.
It appears the code is generic, convert X bits of binary to Y bytes of BCD. You say X is either 8 or 24 and Y is either 2 or 4, makes sense.
It also does not destroy the binary (which my code does).
Working on it.
But the whole code is pretty whack. Why do binary/BCD conversion 1 bit at a time (with a loop) instead of 4 bits at a time?
Do you have an algorithm that does that?
I now have a somewhat bastard child of my code and the OP code. It runs in the HVRSoftware emulator, make sure to put a break at Line 52 or it will just keep going. An oddity, the emulator did not return a Z flag on line 45 when the mask bit got shifted out. I thought it should. So I used BCC instead of BNE (the mask bit gets shifted into C). And I had to emulate DAA.
I couldn't figure out which way the input and output bytes were ordered or addressed, so I made both big endian. That makes it easy to see the result in the emulator 7654321
bra main
binVal .byte $74,$CB,$B1 ; big endian
f2binary .rmb 2
xyz .rmb 8
decVal .rmb 8
f2BCD .rmb 2
f2bytes .byte 4
f2bits .byte 24
f2bitpos .rmb 1
main LDX #binVal
STX f2binary
LDX #decVal
STX f2BCD
bin2BCD LDX f2BCD ; address of output ? couldn't figure what this DEX, INX adjustment of f2BCD was doing
LDAB f2bytes ; number of bytes to output
LDAA #$00
func021 STAA $00,X ; clear output to zero
DEX
DECB
BNE func021
INX
STX f2BCD
func022 LDAA #$80 ; mask for
STAA f2bitpos ; bit position in binary byte
func023 LDX f2binary ; address of byte in binary to convert
LDAA $00,X
LDX f2BCD ; set up for loop
LDAB f2bytes
ANDA f2bitpos ; a bit of A = 1?
ADDA #$FF ; will set carry if A has any bit set
func024 LDAA $00,X ; double the BCD and add in any carry
ADCA $00,X
bsr EmDAA ; and decimal adjust it
STAA $00,X
DEX ; *** or INX if little endian
DECB ; adjusted all output bytes
BNE func024 ; no, next byte
func025 DEC f2bits ; more binary bits to process?
BEQ func028 ; no
LSR f2bitpos ; yes, adjust the mask
BCC func023 ; mask still has a bit
LDX f2binary ; no bits, move to the next binary byte
INX ; *** or DEX if little endian
STX f2binary
BRA func022 ; and repeat
func028 RTS
; emulate the DAA instruction
EmDAA pshb
tab
tpa
anda #$20 ; isolate half carry
bcs EmCy
bne EmCnHy ; C clear H set
; C clear H clear
tba
anda #$0F
cmpa #$0A
bcs xxx
EmCnHy addb #$06
bcs Em60
xxx cmpb #$A0
bcs EmXCn
Em60 addb #$60
EmXCy tba
pulb
sec
rts
EmXCn tba
pulb
clc
rts
; C set
EmCy bne EmCyHy ; C set H set
tba
anda #$0F
cmpa #$0A
bcs Em60
EmCyHy addb #$06
bra Em60
.end