Page 1 of 1
16 bit subtraction
Posted: Tue Mar 14, 2023 7:29 pm
by xlar54
Hey guys, this is likely a noob question, but Ive seen some other 16 bit subtractions that dont seem to take into account a rollover. What I mean is:
C000: 01 FF
If I subtract $05, and the carry is set, then i know I can DEC $C001. But if its zero, I cant. So my subtraction code is no good, since im using BCS.
The most Id be adding or subtracting is less than 256, so its going to only be a single byte. Can someone show some code for this (apparently pretty simple) issue?
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 8:27 pm
by GARTHWILSON
It's not very clear what you mean here—which might be why you're having problems. Subtracting 5 from 1 or 0, either way, regardless of what the C flag was when you started, will end up with it clear (because 1-5, or 0-5, either way, had to borrow), and your BCS will be correct, to branch, or not branch, around the DEC $C001, to whatever the next lower number is, regardless of rollover, like from $FF to $FE, or 00 to $FF.
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 8:46 pm
by barnacle
Looks like you're subtracting an eight-bit value from a sixteen bit minuend, no?
Why not just subtract zero from the second byte, irrespective of the carry value? It'll all sort itself out.
Or are you desperate for space or speed?
Code: Select all
lda $c000
sbc #5
sta $c000
lda $c001 ; 4 cycles
sbc #0 ; 2 cycles
sta $c000 ; 4 cycles
lda $c000
sbc #5
sta $c000
bcs label ; 2 cycles
dec $c001 ; 6 cycles
label:
I would submit that while the first version is both smaller and faster, it more clearly shows your intent. Unless I've misunderstood you.
Neil
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 9:57 pm
by xlar54
Correct. Subtracting an 8 bit number from a 16.
Looking at your examples, i think i see my issue. Im putzing around with the carry flag, doing a SEC before the SBC, etc. Seems your code works without worrying about the carry.
Im still scratching my head though trying to understand why subtracting 0 from the second byte ($FF) results in $FE
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 10:21 pm
by xlar54
If any Commodore 128 users (or VICE) would like to see what Im working on:
https://github.com/Commodore64128/ataripac128
Movement is still a bit wrong.. its taking me some time to figure things out.
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 10:41 pm
by Dr Jefyll
Seems your code works without worrying about the carry.
That seems to be a small booboo on barnacle's part, xlar54.
(I know what kind of dodgy excuses
I make when I slip up, but in this case I'll leave Neil to deal with the matter himself!

)
Unless the programmer has reason to be sure Carry is already set, there needs to be a SEC somewhere before the first SBC.
Code: Select all
sec
lda $c000
sbc #5
sta $c000
lda $c001 ; 4 cycles
sbc #0 ; 2 cycles
sta $c000 ; 4 cycles
lda $c000
sec
sbc #5
sta $c000
bcs label ; 2 cycles
dec $c001 ; 6 cycles
label:
Im still scratching my head though trying to understand why subtracting 0 from the second byte ($FF) results in $FE
You need to review the exact definition of what the SBC instruction does, and how it enables multi-byte subtract operations. (It might be helpful to firstly review how the ADC instruction enables multi-byte addition operations.
-- Jeff
Re: 16 bit subtraction
Posted: Tue Mar 14, 2023 10:42 pm
by GARTHWILSON
I'm still scratching my head though trying to understand why subtracting 0 from the second byte ($FF) results in $FE
The carry flag being clear is the same as a borrow flag (if such a flag existed) being set; so $FF, minus 0, minus 1 for the borrow, is $FE.
Re: 16 bit subtraction
Posted: Wed Mar 15, 2023 6:12 am
by barnacle
Oh, of course the carry should be set before the start of a subtraction chain; er, er, I just didn't want to clutter up the discussion. Yes, that's it. Or a big boy did it and ran away. Um. Or cosmic rays?
Also, the line
I would submit that while the first version is both smaller and faster, it more clearly shows your intent.
should read
I would submit that the second version is both smaller and faster, the first more clearly shows your intent.
Here I go again, contributing to the total amount of wrong on the internet! Obviously I shouldn't post late at night.
(When I had to work with PIC assembly ten or a dozen years ago, I had to do multi-precision arithmetic. The PIC didn't have add-with-carry or subtract-with-borrow and as a result the carry had to be rippled through after every addition/subtraction. At the time, *every* example on the net with the sole exception of a single Microchip datasheet got that wrong...)
Though with my statement 'shows intent' I suspect that many of the code writers here would agree with this premise: optimising too early is always a bad idea. In initial code, write for clarity of intent and simplicity of logic; that way you will have more chance of remembering what it's supposed to do when you come back to it in six months, or next week. Come up with clever tricks to optimise code length or clock cycles if and only if it turns out to be necessary, or aesthetically desirable.
Neil