comparing 16 bit numbers

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

comparing 16 bit numbers

Post 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. :roll:
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: comparing 16 bit numbers

Post by BigDumbDinosaur »

Dan Moos wrote:
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. :roll:
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
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: comparing 16 bit numbers

Post 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.
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: comparing 16 bit numbers

Post 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.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: comparing 16 bit numbers

Post 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
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Re: comparing 16 bit numbers

Post 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...
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: comparing 16 bit numbers

Post by BigEd »

There's an article by Bruce Clark:
Beyond 8-bit Unsigned Comparisons by Bruce Clark
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: comparing 16 bit numbers

Post 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
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
unclouded
Posts: 81
Joined: 24 Feb 2015

Re: comparing 16 bit numbers

Post by unclouded »

drogon wrote:
BLT -> BCC ; Branch if Less Than
Every single time I see "BLT" I think of Bacon, Lettuce and Tomato.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: comparing 16 bit numbers

Post 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."
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: comparing 16 bit numbers

Post 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".
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
watermelon
Posts: 1
Joined: 25 May 2021

Re: comparing 16 bit numbers

Post 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.
Last edited by watermelon on Tue May 25, 2021 10:29 pm, edited 1 time in total.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: comparing 16 bit numbers

Post by BigEd »

(welcome, watermelon. I think you meant to link to this AVR application note)
User avatar
BB8
Posts: 57
Joined: 01 Nov 2020
Location: Tatooine

Re: comparing 16 bit numbers

Post by BB8 »

teamtempest wrote:
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
User avatar
speculatrix
Posts: 151
Joined: 03 Apr 2018
Contact:

Re: comparing 16 bit numbers

Post 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
It either works or catches fire. Either way is fun.
Zolatron 64 project (on Medium)
Post Reply