uint32_t comparison

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

uint32_t comparison

Post by barnacle »

I'm trying to compare two 4-byte words: one at a fixed location (lba) and one at a variable location pointed to by [Y:A]. All I need to know is whether one is greater than the other; equality is nice to have since I can delete another routine. Both variables are unsigned values.

The need to increment and test Y demolishes any previously calculated flags, which is a shame, but I think this ought to work (I may have the C flag upside down). There's a lot of flags being pushed and pulled...

Code: Select all

;-----------------------------------------------------------------------
; u32_cmp
; compare four-byte words in lba and [Y:A]
; returns the carry set if [Y:A] < lba
u32_cmp:
	sta u32_ptr
	sty u32_ptr+1
	ldy #0
	php
u32_c_1:
	plp
	lda lba,y
	cmp (u32_ptr),y
	php
	iny
	cpy #4
	bne u32_c_1
	plp
	rts
Thoughts?

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: uint32_t comparison

Post by barnacle »

Ooops, let's try this; it needs the subtraction for the higher order bytes:

Code: Select all

u32_cmp:
	sta u32_ptr
	sty u32_ptr+1
	ldy #0
	lda lba,y
	cmp (u32_ptr),y
	php
u32_c_1:
	iny
	plp
	lda lba,y
	sbc (u32_ptr),y
	php
	cpy #3
	bne u32_c_1
	plp
	rts
Neil
leepivonka
Posts: 167
Joined: 15 Apr 2016

Re: uint32_t comparison

Post by leepivonka »

Maybe like:

Code: Select all

u32_cmp: ; compare lba with (YA) as uint32, return P.C & P.Z
   sta temp1	; save ptr to arg
   sty temp1+1
   ldy #$ff	; start at most-significant byte
@1: iny		; step to next byte
   cpy #4
   beq @9	; if done, return z=1, c=1
   lda lba,y	; compare
   cmp (temp1),y
   beq @1
@9: rts
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: uint32_t comparison

Post by barnacle »

Ah, thank you; that's a little tidier than mine. I'll have a play.

Neil
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: uint32_t comparison

Post by BigDumbDinosaur »

barnacle wrote:
I'm trying to compare two 4-byte words...There's a lot of flags being pushed and pulled...
No need to to make it complicated.  :D  Something like this might work for you, assuming the “4-byte words” aka “double words” are in little-endian order:

Code: Select all

u32_cmp  =*                    ;compare LBA to variable
;
;	————————————————————————————————————————————————————
;	This function compares the current 32-bit LBA to a
;	32-bit variable whose address is pased in .A (LSB) &
;	.Y (MSB).  The LBA & variable are assumed to be in
;	little-endian format.  Returns are as follows:
;
;	SR ——> c   z   Result
;	——————————————————————————————
;	       x   1   LBA == variable
;	       0   0   LBA <  variable
;	       1   0   LBA >  variable
;	——————————————————————————————
;
;	Invocation example:
;
;	    lda #<variable
;	    ldy #>variable
;	    jsr u32_cmp
;	    beq isequal
;	    bcc lbalower
;	    bcs lbahigher
;	————————————————————————————————————————————————————
;
         sta u32_ptr           ;variable pointer LSB
         sty u32_ptr+1         ;variable pointer MSB
         ldy #4-1              ;index...
;
;			——————————————————————————
;			We are working MSB to LSB.
;			——————————————————————————
;
u32_c_1  =*                    ;main loop
         lda lba,y
         cmp (u32_ptr),y
         bcc u32_c_2           ;LBA < variable
;
         bne u32_c_2           ;LBA > variable
;
         dey
         bpl u_32_c_1          ;keep checking
;
         iny                   ;LBA == variable
;
u32_c_2  =*
         rts
Last edited by BigDumbDinosaur on Sat Feb 07, 2026 9:41 am, edited 1 time in total.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: uint32_t comparison

Post by barnacle »

My assembler makes yours a byte longer than Leepivonka's, BDD, but it's more understandable to me :mrgreen: and I think it might provide more functionality - not sure about that yet.

Thanks, both!

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: uint32_t comparison

Post by barnacle »

And here's the results from BDD's method; just what I need.

Code: Select all

NeoDOS32 v0.0276
Free cluster count: 0001E5EC
Next free cluster: 0000007D
Press any key to boot:
Test 32-bit compare
lba is < tmpq1 Z = 0 S = 1 C = 0
lba is = tmpq1 Z = 1 S = 0 C = 1
lba is > tmpq1 Z = 0 S = 0 C = 1
finished test - any key
This means I can replace an existing equality test as well.

Okay for me to use the code in the FAT32 stuff?

Neil
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Re: uint32_t comparison

Post by teamtempest »

Quote:
No need to to make it complicated.
I agree. It took me a second to understand that final INY, but only a second. Very straightforward and quite handy.
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: uint32_t comparison

Post by BigDumbDinosaur »

barnacle wrote:
And here's the results from BDD's method; just what I need.

Code: Select all

NeoDOS32 v0.0276
Free cluster count: 0001E5EC
Next free cluster: 0000007D
Press any key to boot:
Test 32-bit compare
lba is < tmpq1 Z = 0 S = 1 C = 0
lba is = tmpq1 Z = 1 S = 0 C = 1
lba is > tmpq1 Z = 0 S = 0 C = 1
finished test - any key

This means I can replace an existing equality test as well.
What are the S = 1 and S = 0 referring to?
Quote:
Okay for me to use the code in the FAT32 stuff?
Are you asking for permission to use my routine?  Of course you may.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: uint32_t comparison

Post by BigDumbDinosaur »

barnacle wrote:
My assembler makes yours a byte longer than Leepivonka's, BDD, but it's more understandable to me :mrgreen: and I think it might provide more functionality - not sure about that yet.
Having “slept on it,” as well having consumed sufficient quantities of coffee :mrgreen:, I came up with a slightly shorter rendition:

Code: Select all

u32_cmp  =*                    ;compare LBA to variable
;
;	————————————————————————————————————————————————————
;	This function compares the current 32-bit LBA to a
;	32-bit variable whose address is pased in .A (LSB) &
;	.Y (MSB).  The LBA & variable are assumed to be in
;	little-endian format.  Returns are as follows:
;
;	SR ——> c   z   Result
;	——————————————————————————————
;	       x   1   LBA == variable
;	       0   0   LBA <  variable
;	       1   0   LBA >  variable
;	——————————————————————————————
;
;	Invocation example:
;
;	    lda #<variable
;	    ldy #>variable
;	    jsr u32_cmp
;	    beq isequal
;	    bcc lbalower
;	    bcs lbahigher
;	————————————————————————————————————————————————————
;
         sta u32_ptr           ;variable pointer LSB
         sty u32_ptr+1         ;variable pointer MSB
         ldy #4-1              ;index...
;
;			——————————————————————————
;			We are working MSB to LSB.
;			——————————————————————————
;
u32_c_1  =*                    ;main loop
         lda lba,y
         cmp (u32_ptr),y
         bne u32_c_2           ;LBA != variable
;
;			——————————————————————————————————————————
;			If LBA < variable, c = 0, z = 0.
;			If LBA > variable, c = 1, z is don't care.
;			——————————————————————————————————————————
;
         dey
         bpl u_32_c_1          ;keep checking
;
         iny                   ;LBA == variable
;
u32_c_2  =*
         rts

Bon appetite!
x86?  We ain't got no x86.  We don't NEED no stinking x86!
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: uint32_t comparison

Post by barnacle »

The flags tested were zero, sign, and carry. Just included for completeness since it's the inverse of the carry. The canonical name is probably 'N' in 6502 land. :mrgreen:

Thanks for the permission. Credit in the source code!

The new code is interesting, but it's handy to have the equality test as well.

Neil

edit: wait, what does the last routine return for equality? Z set?
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: uint32_t comparison

Post by BigDumbDinosaur »

barnacle wrote:
The flags tested were zero, sign, and carry.  Just included for completeness since it's the inverse of the carry.  The canonical name is probably 'N' in 6502 land. :mrgreen:
Yes, canonical for the negative bit in SR is ‘n’.

In a binary comparison context, the state of n is not only irrelevant, it may/could/might/probably-will be treacherous.  In comparisons, c and z are your friends; n is a sNake in the grass :D, since it reflects the internal sign effect caused by the subtraction that CMP, CPX and CPY carry out.  It is possible with certain values to produce a comparison in which carry is clear (register_value < memory_value) and the internal subtraction does not result in a carry into the sign bit.

Quote:
Thanks for the permission. Credit in the source code!
Yer welcome.
Quote:
The new code is interesting, but it's handy to have the equality test as well...edit: wait, what does the last routine return for equality?  Z set?
Same results as the previous routine, as described in the comments.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply