6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 6:30 am

All times are UTC




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: comparing 16 bit numbers
PostPosted: Sun May 17, 2020 10:15 pm 
Offline

Joined: Sat Mar 11, 2017 1:56 am
Posts: 276
Location: Lynden, WA
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:


Top
 Profile  
Reply with quote  
PostPosted: Sun May 17, 2020 11:40 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
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:
;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!


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 12:11 am 
Offline

Joined: Sat Mar 11, 2017 1:56 am
Posts: 276
Location: Lynden, WA
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.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 12:23 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
I just happen to be working on code like that right now...

Code:
        lda     I+1
        cmp     J+1
        bne     Decide
        lda     I
        cmp     J
Decide  blo     Lower


blo is an alias for bcc.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 12:59 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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:
  LDA x+1
  CMP y+1
  BNE :+
  LDA x+0
  CMP y+0
: BCC lower
  BNE higher
  BEQ same


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 1:48 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 387
Location: Minnesota
The approaches described so far all work fine, but if you're more concerned about small size than fastest average execution:

Code:
         lda addr0
         cmp addr1
         lda addr0+1
         sbc addr1+1
         bcc  addr1IsBigger
         bne addr0IsBigger
         ; else equal...


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 6:02 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
There's an article by Bruce Clark:
Beyond 8-bit Unsigned Comparisons by Bruce Clark


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 6:47 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1398
Location: Scotland
Might be worth noting that some assemblers have aliases either built-in or via macros for the branch instructions, so:

Code:
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/


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 7:03 am 
Offline

Joined: Tue Feb 24, 2015 11:07 pm
Posts: 81
drogon wrote:
BLT -> BCC ; Branch if Less Than

Every single time I see "BLT" I think of Bacon, Lettuce and Tomato.


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 7:49 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
"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."


Top
 Profile  
Reply with quote  
PostPosted: Mon May 18, 2020 3:14 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1926
Location: Sacramento, CA, USA
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)


Top
 Profile  
Reply with quote  
PostPosted: Tue May 25, 2021 4:11 pm 
Offline

Joined: Tue May 25, 2021 4:09 pm
Posts: 1
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.

Top
 Profile  
Reply with quote  
PostPosted: Tue May 25, 2021 4:21 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
(welcome, watermelon. I think you meant to link to this AVR application note)


Top
 Profile  
Reply with quote  
PostPosted: Tue May 25, 2021 6:51 pm 
Offline
User avatar

Joined: Sun Nov 01, 2020 10:36 am
Posts: 35
Location: Tatooine
teamtempest wrote:
The approaches described so far all work fine, but if you're more concerned about small size than fastest average execution:

Code:
         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:
         lda addr0
         cmp addr1
         lda addr0+1
         sbc addr1+1
         bcc  addr1IsBigger
         ;addr0IsGreaterOrEqual


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 27, 2022 7:47 pm 
Offline
User avatar

Joined: Tue Apr 03, 2018 2:10 pm
Posts: 125
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:
; 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

_________________
I like it when things smoke.
BlogZolatron 64 project


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 16 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: