It is currently Tue Sep 18, 2018 5:52 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 7:37 pm 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 314
Look, I'm not really looking to do anything fancy, it's just that I can't figure out how to do 16-bit signed addition/subtraction. I know the whole spiel about two's complement, however I'm lost in the details on how to extend 8-bit signed math to 16-bit land...

Could someone please help me? I'm specifically looking for examples of 16 bit signed add/subtract routines for the 6502, along with how 16-bit signed numbers are usually represented. I've searched in a lot of places so far and this is driving me nuts.

_________________
This is a block of text that can be added to posts you make. There is a 255 character limit.


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 7:39 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6799
Location: Canada
This is the document I continually turn to for reference on this:
http://www.6502.org/tutorials/compare_beyond.html

It covers signed stuff, but also >=16-bit stuff too.

Though, just for addition and subtraction the signed operations are identical to the unsigned ones. CLC ADC or SEC SBC work the same for signed as unsigned, the only difference is when comparing things you have to look at different flags. (Signed comparison is where you have to look at that overflow flag, for example.)


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 7:54 pm 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 314
rainwarrior wrote:
This is the document I continually turn to for reference on this:
http://www.6502.org/tutorials/compare_beyond.html

It covers signed stuff, but also >=16-bit stuff too.

Though, just for addition and subtraction the signed operations are identical to the unsigned ones. CLC ADC or SEC SBC work the same for signed as unsigned, the only difference is when comparing things you have to look at different flags. (Signed comparison is where you have to look at that overflow flag, for example.)


I looked at that document.

I'm going to have to ask to be spoonfed, really. I've been trying for the past two days to properly add together a fixed number with a 16 bit signed offset with no success, and that's all because of the damn overflow/carry flags.

I mean, where IS the sign? On both bytes? If you add two values and it goes past the -127 +127 range the V flag gets set, but on a 16 bit signed number isn't the whole least significant byte used, and the V flag is for improper 7th bit/sign manipulation? How can you use the V flag to add/subtract anything into the MSB of the 16-bit number? I really, really need to see example code.

_________________
This is a block of text that can be added to posts you make. There is a 255 character limit.


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 7:59 pm 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 358
The sign is the high bit on the high byte. The V flag is not used at all for doing simple adds and subtracts, but instead it's used when doing comparisons (16 bit CMP).

Adding two signed 16 bit numbers:

Code:
clc
lda foo+0
adc bar+0
sta result+0
lda foo+1
adc bar+1
sta result+1


For subtraction, replace adc with sbc.

One thing that might be confusing you is adding a signed 8 bit number to a signed 16 bit number. In that case, you have to first "sign extend" the 8 bit number to be 16 bits. If the 8 bit number is positive, the high byte is simply $00. If the 8 bit number is negative, the high byte is $FF.

For constants, you can use .lobyte and .hibyte:
Code:
clc
lda foo+0
adc #.lobyte(-30)
sta result+0
lda foo+1
adc #.hibyte(-30)
sta result+1


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 8:40 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6799
Location: Canada
Punch wrote:
I'm going to have to ask to be spoonfed, really. I've been trying for the past two days to properly add together a fixed number with a 16 bit signed offset with no success, and that's all because of the damn overflow/carry flags.

The overflow flag isn't part of the result of addition or subtraction, it's just information about whether an overflow has occurred when you did it. (This is important when doing a comparison though, you may need to look at it then.)

Punch wrote:
I mean, where IS the sign? On both bytes?

The sign is the highest bit. If it's an 8 bit number that's bit 7. If it's a 16 bit number that's bit 15.

When you convert an 8 bit signed number to a 16 bit signed number, you "extend the sign" by copying that high bit into every bit above it. $FE is -2 in 8-bit. $FFFE is -2 in 16-bit.

BTW, re: pubby's suggestion, you can also use < and > for .lobyte and .hibyte, if that's more succinct. (I find it easier to read.)

Punch wrote:
How can you use the V flag to add/subtract anything into the MSB of the 16-bit number? I really, really need to see example code.

V flag is only for checking for overflow (and relevant when you do comparisons). If you're doing multi-byte compares, the overflow result is only known after you've gone through the chain up to the high byte, so really only the last overflow value is relevant. (Carry on the other hand propagates through all the bytes, just like with unsigned.)


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 8:52 pm 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 314
You guys are life savers, thank you so much :mrgreen:

By the way, I also need to clip off the MSB of a signed number too for some unrelated stuff, a la what you would do with an unsigned number (just ignore the msb), and I came up with this:

Code:
;Gets lower 7 bits of signed 16 bit integer, conserves sign.
 .macro S16toS8
  .if (\# != 1)
   .fail
  .endif
   LDA \1 + 1
   BPL .plus\@
 .minus\@:
   LDA \1
   ORA #%1000_0000 ;Replace bit 7 with minus flag
               ;Negating +1 the # is unneeded since
               ;it's already two's complement.
   BRA .exit\@
 .plus\@:
   LDA \1
   AND #%0111_1111 ;That's it.
 .exit\@:
   .endm


Just copying the flag is enough to get the small 7 bit component of the whole number, right? I was playing around with the 6502 simulator on Easy 6502 and with a hex calculator and the results seemed to be correct, but I might be missing something.

_________________
This is a block of text that can be added to posts you make. There is a 255 character limit.


Top
 Profile  
 
 Post subject: Re: 6502 Signed Math
PostPosted: Fri Sep 14, 2018 9:10 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6799
Location: Canada
The usual way to truncate a signed number is the same as with unsigned. You just drop the high byte.

If the 16 bit (15+1) signed value was representable as 8 bit (7+1), the high bit of LSB is already appropriately set. (That sign extend principle above ensures this is true.)

If it was not representable, you'll get the modulo / wrapped around value just by dropping the MSB, like you would with unsigned numbers too.

You can copy the sign bit like you're suggesting, but I doubt that's a useful result. You've kept the sign the same, but the lower 7 bits are basically all bogus. I would say that if you do that the only useful bit of the result is the sign.

-129 = %1111,1111,0111,1111

Should it truncate to:

127 = %0111,1111 = wrapped 8-bit result of -128 - 1

Or:

-1 = %1111,1111 = (not sure how to justify this)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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:  
Powered by phpBB® Forum Software © phpBB Group