Page 1 of 2
comparing 16 bit numbers
Posted: Sun May 17, 2020 10:15 pm
by Dan Moos
On a vanilla 65c02, what is the best way to compare 2 16 bit numbers? Specifically trying to check which of two addresses are larger.
Do i just do a normal subtraction, and watch the carry/zero flags, or is there a slicker way?
I mostly ask because whenever I do something, I invariably later see a method that is both better, and embarrassingly obvious.

Re: comparing 16 bit numbers
Posted: Sun May 17, 2020 11:40 pm
by BigDumbDinosaur
On a vanilla 65c02, what is the best way to compare 2 16 bit numbers? Specifically trying to check which of two addresses are larger.
Do i just do a normal subtraction, and watch the carry/zero flags, or is there a slicker way?
I mostly ask because whenever I do something, I invariably later see a method that is both better, and embarrassingly obvious.

Here's how I would do it:
Code: Select all
;16-bit number comparison...
;
lda #>x ;MSB of 1st number
cmp #>y ;MSB of 2nd number
bcc islower ;X < Y
;
bne ishigher ;X > Y
;
lda #<x ;LSB of 1st number
cmp #<y ;LSB of 2nd number
bcc islower ;X < Y
;
beq issame ;X = Y
;
bne ishigher ;X > Y
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 12:11 am
by Dan Moos
Thanks.
The branch instructions, especially in these cases still tie my brain in a knot. I know what they do, I know how they work , ect. But I still sorta "lose the ball" sometimes.
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 12:23 am
by BillG
I just happen to be working on code like that right now...
Code: Select all
lda I+1
cmp J+1
bne Decide
lda I
cmp J
Decide blo Lower
blo is an alias for bcc.
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 12:59 am
by Chromatix
The general pattern of multi-byte compares is:
1: Compare the most-significant bytes first, using either the signed or unsigned comparison rule as appropriate. If they are unequal, they determine the overall result.
2: Otherwise, continue to less significant bytes in turn, until you find a pair that is unequal or you run out of bytes. These comparisons should always use the
unsigned comparison rule, even on signed values.
3: If you run out of bytes before finding any that differ, the overall result is that the values are equal.
For comparing multi-byte unsigned values, I prefer the following construction:
Code: Select all
LDA x+1
CMP y+1
BNE :+
LDA x+0
CMP y+0
: BCC lower
BNE higher
BEQ same
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 1:48 am
by teamtempest
The approaches described so far all work fine, but if you're more concerned about small size than fastest average execution:
Code: Select all
lda addr0
cmp addr1
lda addr0+1
sbc addr1+1
bcc addr1IsBigger
bne addr0IsBigger
; else equal...
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 6:02 am
by BigEd
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 6:47 am
by drogon
Might be worth noting that some assemblers have aliases either built-in or via macros for the branch instructions, so:
Code: Select all
BLT -> BCC ; Branch if Less Than
BGE -> BCS ; Branch if Greater than Equal
Or just do what I did for a while and write them on a post-it on the side of my screen..
-Gordon
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 7:03 am
by unclouded
BLT -> BCC ; Branch if Less Than
Every single time I see "BLT" I think of Bacon, Lettuce and Tomato.
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 7:49 am
by Chromatix
"Yeah, my BLT drive just went AWOL, and I've got this big project due tomorrow for Mr. Kawasaki, and if I don't have it in he's going to make me commit harakiri - you know these new Japanese management techniques."
Re: comparing 16 bit numbers
Posted: Mon May 18, 2020 3:14 pm
by barrym95838
Motorola's convention is to use BLO for unsigned and BLT for signed, so BillG has it right, by at least one definition of "right".
Re: comparing 16 bit numbers
Posted: Tue May 25, 2021 4:11 pm
by watermelon
The AVR202 [1] explains the implementation of 16-bit arithmetic in the Assembler language of the 8-bit AVR microcontroller: Simple subroutines extendable to 32 bits or any data word length. Code density and processing speed are comparable with 16-bit microcontrollers. There is a running example code. According to the following algorithm, the operation is performed: The least significant bytes of the words are added. Then the high bytes of the terms are added, taking into account the carry. There are so many numbers in my life, just recently I was haunted by the number 111, I just saw it everywhere! Then I read about its meaning at
https://www.zodiacsigns-horoscope.com/a ... 1-meaning/, and now I give even more importance to numbers.
Re: comparing 16 bit numbers
Posted: Tue May 25, 2021 4:21 pm
by BigEd
(welcome, watermelon. I think you meant to link to
this AVR application note)
Re: comparing 16 bit numbers
Posted: Tue May 25, 2021 6:51 pm
by BB8
The approaches described so far all work fine, but if you're more concerned about small size than fastest average execution:
Code: Select all
lda addr0
cmp addr1
lda addr0+1
sbc addr1+1
bcc addr1IsBigger
bne addr0IsBigger
; else equal...
The "; else equal..." part is wrong.
Let's take the two values $6502 and $6501 (so, in little endian: 02 65 01 65). The first compare will be 02-01, which will give a set Carry flag (and an unset Zero flag). The second operation will take the Carry and subtract 65 from 65. This will produce a set Zero flag (and a set Carry flag). The Zero flag will reflect only the equality of the high bytes.
The "bne addr0IsBigger" is technically correct, but what flows through could still be Greater [or Equal].
When you use SBC to do a multibyte compare, you have to check the equality separately.
Code: Select all
lda addr0
cmp addr1
lda addr0+1
sbc addr1+1
bcc addr1IsBigger
;addr0IsGreaterOrEqual
Re: comparing 16 bit numbers
Posted: Sun Feb 27, 2022 7:47 pm
by speculatrix
I've read the above and the tutorial, but would appreciate a sanity check on a general-purpose routine for comparing 32-bit numbers. Does this made sense?
Code: Select all
; Compare two 32-bit values
NUMA = $4000 ; LSB for NUMA. Other bytes in NUMA+1, NUMA+2, NUMA+3
NUMB = $4004 ; like above
.compare_32bit
lda NUMA+3
cmp NUMB+3
bcc less_than ; NUMA < NUMB
bne more_than ; if NUMA+3 <> NUMB+3 then NUMA > NUMB
lda NUMA+2
cmp NUMB+2
bcc less_than
bne more_than
lda NUMA+1
cmp NUMB+1
bcc less_than
bne more_than
lda NUMA
cmp NUMB
bcc less_than
bne more_than
.equal
; stuff
.less_than
; stuff
.more_than
; stuff
rts