Signed and Unsigned 8/16 bit arithmetic.

**The AVR instruction set supports signed arithmetic like adding,subtracting and comparing 8 bit (byte) signed numbers but has no support for 16 bit (word) signed numbers.Since the scope of Acorn kernel is assembler and assembler only, i have summarized the basic macro definitions that will help programmers do complex signed and unsigned numbers based algorithms in AVR assembler.**

**Signed number representation - two's complement.**

**We all know that in mathematics, the negative signed number is represented by prefixing them with a ‘−’ sign. However the AVR assembler numbers are represented by a sequence of ‘1’ and ‘0’ without extra symbols and any notion of a sign.Here the 2-complement method of sign number representation is discussed.The negative number(“-” sign) is represented by setting the most significant bit to 1 in byte/word number representation.Thus the byte 1011 0000 which is 176 in the unsigned arithmetic, becomes -80 in signed arithmetic.Converting unsigned number to its signed representation and vice versa goes through 2 basic steps:**

**Initial value:01010000(2)=0x50(16)=80(10) 80 **

- Flip all bits

Flipping all bits yields

10101111(2)=0xAF(16)=175(10)

- Add 1 ignoring overflow

**10101111+00000001-------------10110000(2)=0xB0(16)=176(10) - 80**

**The two's complement of zero is zero: inverting gives all ones, and adding one changes the ones back to zeros (since the overflow is ignored). Furthermore, the two's complement of the most negative number representable (e.g. a one as the most-significant bit and all other bits zero) is itself. Hence, there appears to be an 'extra' negative number.**

**It should be noted that although the two's-complement representation of a non-negative number is represented by its ordinary binary representation, the range of numbers represented is not the same as with unsigned binary numbers. For example, an 8-bit unsigned number can represent the values 0 to 255(11111111). However a two's complement 8-bit number can only represent positive bytes from 0 to 127(01111111), because the rest of the bit combinations with the most significant bit as '1' represent the negative bytes-1 to -128. The following rule summerizes the signed number range that could be represented by N bits.Using N bits, all integers from −(2N−1) to 2N−1 − 1 can be represented.**

**Arithmetic Overflow.**

**What happens however if we try to calculate numbers and the result falls outside the designated N bits range [(2N−1) ; 2N−1 − 1]?Such condition is called arithmetic overflow and the AVR CPU architecture has got something to help programmers with this condition:V - Two’s Complement Overflow Flag in SREG status register. Let us observe its behaviour with an example.**

**11110111{2} =0xF7{16}=247{10}= -9 +10001000{2} =0x88{16} =136{10}=-120 It is obvious that the result -129 falls outside the 8 bits signed range [-128;127] so lets see how AVR CPU will react to this condition.In AVR assembler code this will beldi r16,-9ldi r17,-120add r16,r17The SREG status register right after the addition will be **

**where V - two's complement overflow flag is set.Same example with positive numbers00001001{2} =0x09=9{10}= 9 +01111000{2} =0x78{16} =120=120 The result 129 falls outside the 8 bits signed range [-128;127].In AVR assembler code this will beldi r16,9ldi r17,120add r16,r17The SREG status register right after the addition will be **

**where V - two's complement overflow flag is set.It is up to the programmer to investigate such conditions and properly handle arithmetic overflows.**

**Signed 1 byte/8 bits Arithmetic.**

**As already mentioned AVR instruction set supports signed arithmetic on a single byte length number.Let us see some basic examples.**

- adding combining positive and negative bytes

** ldi axl,-127 ldi axh,1loop: add axl,axh brvs overflow ;overflow -> handle it!rjmp loopoverflow : ldi axl,-127 ldi axh,1 rjmp loop**

- subtracting combining positive and negative bytes

** ldi axl,-127 ldi axh,-1loop: sub axl,axh brvs overflow ;overflow -> handle it!rjmp loopoverflow : ldi axl,-127 ldi axh,-1 rjmp loop **

** **

**Signed 2 bytes/16 bits Arithmetic.**

**Unfortunately, there is no AVR instruction set support for 2 bytes/16 bit signed arithmetic that will work right out of the box but there is an instruction infrastructure that will help us in this regard.Calculating the allowed number range using the formula above, we get the upper and lower boundary for 2 bytes signed numbers [-32 768;32 767]. There is no avr instruction which adds and subtracts 2 byte signed numbers out of the box so we will have to define these operations ourselves**

- 16 bits/2 bytes adding combining positive and negative numbers

.MACRO ADD16

add @0,@2 ;Add low bytes

adc @1,@3 ;Add high bytes with carry

.ENDMACRO

.MACRO ADDI16

subi @0,low(-@2)

sbci @1,high(-@2)

.ENDMACRO

;Example

ldi axl,low(-32 768)

ldi axh,high(-32 768)

ldi bxl,low(1)

ldi bxh,high(1)

loop:

ADD16 axl,axh,bxl,bxh

brvs overflow ;overflow -> handle it!

rjmp loop

overflow :

ldi axl,low(-32 768)

ldi axh,high(-32 768)

ldi bxl,low(1)

ldi bxh,high(1)

rjmp loop

- 16 bits/2 bytes subtracting combining positive and negative numbers

**.MACRO SUB16 sub @0,@2 ;Subtract low bytes sbc @1,@3 ;Add high byte with carry.ENDMACRO.MACRO SUBI16 subi @0,low(@2) sbci @1,high(@2).ENDMACRO ;Exampleldi axl,low(3)ldi axh,high(3) ldi bxl,low(1)ldi bxh,high(1) loop:SUB16 axl,axh,bxl,bxhbrvs overflow ;overflow -> handle it! rjmp loopoverflow :ldi axl,low(3)ldi axh,high(3) ldi bxl,low(1)ldi bxh,high(1) rjmp loop **

**There is an interesting point in the macro definition in regard to two's complement overflow flag in STATUS register. Since the addition/subtraction involves 2 consecutive instructions (add,adc/sub,sbc) that modify the two's complement overflow flag the question is what will happen when the 8 bit signed boundary is met (-128 or 127). It is clear that the first instruction will set the flag but the second one will clear it up, thus preserving the integrity of the 16 bit signed addition/subtraction.**

**Signed 1 byte/8 bits comparison.**

**Going through the instruction set one could see that there are some instructions to facilitate 8-bit signed arithmetic.BRGE - If the instruction is executed immediately after any of the instructions CP Rd,Rr CPI Rd,K SUB Rd,Rr SUBI Rd,K the branch will occur if and only if the signed binary number represented in Rd was greater than or equal to the signed binary number represented in Rr(K).BRLT - If the instruction is executed immediately after any of the instructions CP Rd,Rr CPI Rd,K SUB Rd,Rr SUBI Rd,Kthe branch will occur if and only if the signed binary number represented in Rd was less than the signed binary number represented in Rr(K). So the following code snippets are quite appropriate for 8 bit signed comparison**

ldi axl,-12

ldi axh,1

cp axl,axh

brge loop

ldi axl,-12

cpi axl,1

brge loop

ldi axh,1

cp axl,axh

brge loop

ldi axl,-12

cpi axl,1

brge loop

** **

**Signed 2 bytes/16 bits comparison.**

**As already mentioned AVR CPU has no support for 2 bytes signed number comparison therefore the following macros were devised.**

.MACRO CPI16

cpi @0,low(@3) ;Compare low byte with low immediate number’s byte

ldi @2,high(@3) ; Using a temp register!!!!!!!!

cpc @1,@2 ;Compare high byte with high immediate number’s byte

.ENDMACRO

.MACRO CP16

cp @0,@2 ;Compare low byte

cpc @1,@3 ;Compare high byte with carry from previous operation

.ENDMACRO

;Example

ldi axl,low(-30000)

ldi axh,high(-30000)

ldi bxl,low(1)

ldi bxh,high(1)

CP16 axl,axh,bxl,bxh

brge loop

ldi bxl,low(1)

ldi bxh,high(1)

CPI16 axl,axh,temp,-30000

brge loop