Signed word and byte arithmetic - negative numbers
I got bored with always having to write special case code to deal with negative numbers so have developed a set of subroutines to multiply, divide, MOD, and bintoascii for signed bytes and signed words. Addition and subtraction of course work without any special code. It is interesting that the picaxe interpreter is perfectly happy to allow statements such as w1 = -1234 and correctly implements them.
The code uses a trivial signed version of sertxd for test purposes. Equivalent cut-and-paste routines will also be needed for serout and hserout.
The routine to do bintoascii, which also strips leading zeroes, could also be used and is more general for example to support direct coupled LCD displays
The code should be self-documenting and only bits may be needed in any given program. I have tested reasonably thoroughly but let me have any bugs, questions or comments.
I got bored with always having to write special case code to deal with negative numbers so have developed a set of subroutines to multiply, divide, MOD, and bintoascii for signed bytes and signed words. Addition and subtraction of course work without any special code. It is interesting that the picaxe interpreter is perfectly happy to allow statements such as w1 = -1234 and correctly implements them.
The code uses a trivial signed version of sertxd for test purposes. Equivalent cut-and-paste routines will also be needed for serout and hserout.
The routine to do bintoascii, which also strips leading zeroes, could also be used and is more general for example to support direct coupled LCD displays
The code should be self-documenting and only bits may be needed in any given program. I have tested reasonably thoroughly but let me have any bugs, questions or comments.
Code:
'
' signed arithmetic
'
' NB add and subtract can be used as normal
' the distinction between + and - is made at the output formatting stage
'
symbol sign =bit0
symbol i = b1
symbol word1 = w1 '-32768 to 32767
symbol byte1 = b2 '-128 to 127
symbol byte2 = b3
symbol word2 = w2
symbol byte3 = b4
symbol byte4 = b5
symbol bytearray = 6 'space for using bintoascii, reserve 7 bytes b6-b12
'
symbol positive=0
symbol negative=1
'
' test signed word multiply
'
word1=125
word2= -45 ' This is valid syntax even though picaxe doesn't support negative integers
gosub multsignedword
gosub sertxdsignedword
sertxd(13,10)
'
' test signed word divide
'
word1=-4000
word2=-22
gosub divsignedword
gosub sertxdsignedword
sertxd(13,10)
'
' test signed byte multiply
'
byte1=-10
byte2=-5
gosub multsignedbyte
gosub sertxdsignedbyte
sertxd(13,10)
'
' test signed byte divide
'
byte1=-100
byte2=4
gosub divsignedbyte
gosub sertxdsignedbyte
sertxd(13,10)
'
' test signed word modulus
'
word1=-55
word2=360
gosub modsignedword
gosub sertxdsignedword
'
' test signed byte modulus
'
byte1=-4
byte2=12
gosub modsignedbyte
gosub sertxdsignedbyte
sertxd(13,10)
'
' test signed byte bintoascii
'
byte1=-32
gosub signedbytetoascii
bptr=bytearray
i=@bptrinc
do while i<>0
sertxd(i)
i=@bptrinc
loop
'
' test signed word bintoascii
'
word1=-1234
gosub signedwordtoascii
bptr=bytearray
i=@bptrinc
do while i<>0
sertxd(i)
i=@bptrinc
loop
do
loop
'Proc sertxdsignedword(word1 As Word)
'
sertxdsignedword:
If word1 >= $8000 Then
word1 = -word1
sertxd( "-", #word1)
Else
sertxd (#word1)
Endif
return
'
'Proc sertxdsignedbyte(byte3 As byte)
'
sertxdsignedbyte:
If byte1 >= $80 Then
byte1 = -byte1
sertxd ("-", #byte1)
Else
sertxd (#byte1)
Endif
return
'
'Function multsignedword(word1 As Word, word2 As Word) As Word
'multiply word1 by word2 and return the result in word1
'
multsignedword:
sign = positive
If word1 >= $8000 Then
sign = Not sign
word1 = -word1
Endif
If word2 >= $8000 Then
sign = Not sign
word2 = -word2
Endif
word1 = word1 * word2
If sign = negative Then
word1 = -word1
Endif
return
'
'Function divsignedword(word1 As Word, word2 As Word) As Word
'divide word1 by word2 and return the result in word1
'
divsignedword:
sign = positive
If word1 >= $8000 Then
sign = Not sign
word1 = -word1
Endif
If word2 >= $8000 Then
sign = Not sign
word2 = -word2
Endif
word1 = word1 / word2
If sign = negative Then
word1 = -word1
Endif
return
'
'Function multsignedbyte(byte1 As byte, byte2 As byte) As byte
'multiply byte1 by byte2 and return the result in byte1
'
multsignedbyte:
sign = positive
If byte1 >= $80 Then
sign = Not sign
byte1 = -byte1
Endif
If byte2 >= $80 Then
sign = Not sign
byte2 = -byte2
Endif
byte1 = byte1 * byte2
If sign = negative Then
byte1 = -byte1
Endif
return
'
'Function divsignedbyte(byte1 As byte, byte2 As byte) As byte
'divide byte1 by byte2 and return the result in byte1
'
divsignedbyte:
sign = positive
If byte1 >= $80 Then
sign = Not sign
byte1 = -byte1
Endif
If byte2 >= $80 Then
sign = Not sign
byte2 = -byte2
Endif
byte1 = byte1 / byte2
If sign = negative Then
byte1 = -byte1
Endif
return
'
'Function modsignedbyte(byte1 As byte, byte2 As byte) As byte
'calculate the byte2 modulus of byte1 and return the result in byte1
'useful for clock arithmetic
'
modsignedbyte:
sign = positive
If byte1 >= $80 Then
sign = negative
byte1= -byte1
Endif
byte1 = byte1 // byte2
If sign = negative Then
byte1 = -byte1
Endif
If byte1 >= $80 Then
byte1 = byte1 + byte2
Endif
return
'
'Function modsignedword(word1 As Word, word2 As Word) As Word
'calculate the word2 modulus of word1 and return the result in word1
'useful for degrees arithmetic
'
modsignedword:
sign = positive
If word1 >= $8000 Then
sign = negative
word1 = -word1
Endif
word1 = word1 // word2
If sign = negative Then
word1 = -word1
Endif
If word1 >= $8000 Then
word1 = word1 + word2
Endif
return
'
'Proc signedbytetoascii
' returns a byte array starting at pointer bytearray terminated by a null
' of the number in byte1
' the number is stripped of leading zeroes
'
signedbytetoascii:
if byte1>= $80 then
byte2=$FF
else
byte2=0
endif
'
'Proc signedwordtoascii
' returns a byte array starting at pointer bytearray terminated by a null
' of the numberin word1
' the number is stripped of leading zeroes
'
signedwordtoascii:
byte3=0
sign=positive
bptr = bytearray
If word1 >= $8000 Then
sign= negative
word1 = -word1
else
endif
bintoascii word1,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc
@bptr=0 'denotes end of string with a null
bptr = bytearray
if @bptrinc="0" then ' at least one leading zero
byte3=1
if @bptrinc="0" then ' at least two leading zeros
byte3=2
if @bptrinc="0" then ' at least three leading zeros
byte3=3
if @bptrinc="0" then ' exactly four leading zeros
byte3=4
endif
endif
endif
endif
byte1=bytearray+byte3
byte2=bytearray+5
byte4=bytearray
for i= byte1 to byte2 'now move array (including trailing null) left by the number of leading zeroes
bptr=i
byte3=@bptr
bptr=byte4
@bptr=byte3
byte4=byte4+1
next i
if sign=negative then
byte1=bytearray
byte2=bytearray+5
for i= byte2 to byte1 step -1 'now move array (including trailing null) left by the number of leading zeroes
bptr=i
byte3=@bptrinc
@bptr=byte3
next i
bptr=bytearray
@bptr="-"
endif
return
Last edited: