Hello!
I want to make a calculation of a Frequency for a DDS Chip.
I've got a simple formula: Freq = 20.000.000 * FRegister / 2^32
All variables are of unsigned long. The result has to be unsigned long.
How can I make this calculation???
Has anyone an idea? I'ld need a 64Bit calculation.
If it's not possible, what's with a floating point calculation? (=> double)
How can I convert from an unsigned Long to a double and the other way round?
Thanks a lot in advance!!!
Michael
How to calculate with 32 Bit variables => 64 Bit needed
You can't do this calculation with just 32 bit numbers, as you correctly realized.
Floating point calculation won't be too helpful either - MikroC only knows single precision floats, which best case yield only around 7 significant digits. Double precision got promised a long time ago but still isn't implemented.
I have the same problem (also need to calculate the tuning word for a DDS chip, and mine has a 6 byte tuning word!), and I think I will have to write some integer routines for 12-byte-long integers myself.
Floating point calculation won't be too helpful either - MikroC only knows single precision floats, which best case yield only around 7 significant digits. Double precision got promised a long time ago but still isn't implemented.
I have the same problem (also need to calculate the tuning word for a DDS chip, and mine has a 6 byte tuning word!), and I think I will have to write some integer routines for 12-byte-long integers myself.
Hi All!
I faced similar problem some tinme ago with 8051 and bascom.
Here are the basic code i used to multiply and divide 8 bytes numbers.
It is (more or less) easy to port into C
Regards Jorge
I faced similar problem some tinme ago with 8051 and bascom.
Here are the basic code i used to multiply and divide 8 bytes numbers.
It is (more or less) easy to port into C
Regards Jorge
Code: Select all
'*************************************
' variables declare in the subroutines
'*************************************
Dim Rot(8) As Byte
Dim Restado(8) As Byte
Dim Restando(8) As Byte
Dim Res(8) As Byte
Dim Denominador(8) As Byte
Dim Numerador(8) As Byte
Dim Divisor(8) As Byte
Dim Resto(8) As Byte
Dim Cont1 As Byte
Dim Cont2 As Byte
Dim Aux1 As Byte
Dim Aux2 As Integer
Dim Aux3 As Integer
Dim Aux4 As Long
Dim Aux5 As Long
'*************************************
' general variables
'*************************************
Dim Carry As Byte
Dim Zero As Byte
Dim Kn As Byte
Dim Kw As Byte
Dim Index As Byte
Declare Sub Leftshift()
Declare Sub Subtract()
Declare Sub Divide()
Declare Sub Multiply()
Denominador(1) = &H16
Denominador(2) = &H25
Denominador(3) = &H02
Denominador(4) = &H01
Denominador(5) = 0
Denominador(6) = 0
Denominador(7) = 0
Denominador(8) = 0
Numerador(1) = &H18
Numerador(2) = &H18
Numerador(3) = &H18
Numerador(4) = &H18
Numerador(5) = 0
Numerador(6) = 0
Numerador(7) = 0
Numerador(8) = 0
Carry = 1
Call Multiply()
End
'****************************************************
' Subroutine to Multiply Numerador and Denominador
' the result is in Divisor in 64 bits aritmethics
'****************************************************
Sub Multiply()
Aux4 = 0
For Cont1 = 1 To 8
For Cont2 = Cont1 To 1 Step -1
Aux1 = Cont1 + 1
Aux1 = Aux1 - Cont2
Aux5 = Denominador(cont2)
Aux5 = Aux5 * Numerador(aux1)
Aux4 = Aux4 + Aux5
Next Cont2
Divisor(cont1) = Low(aux4)
Shift Aux4 , Right , 8
Next Cont1
End Sub
'****************************************************
' Subroutine to Divide Numerador over Denominador and
' the result is in Divisor and Resto in 64 bits
' aritmethics
'****************************************************
Sub Divide()
Kw = 64
Carry = 0
'error check
'calculate kn number of significant bits in Numerador
Resto(3) = 1
For Cont1 = 1 To 8
For Aux1 = 0 To 7
Resto(1) = 1
Shift Resto(1) , Left , Aux1
Resto(2) = Numerador(cont1) And Resto(1)
If Resto(2) <> 0 Then
Kn = Resto(3)
End If
Incr Resto(3)
Next Aux 1
Next Cont1
'in kn there is the significant bits
'left justify the Numerador
For Cont1 = 1 To 8
Rot(cont1) = Numerador(cont1)
Next Cont1
Resto(1) = Kw - Kn
For Cont2 = 1 To Resto(1)
Call Leftshift()
Next Cont2
For Cont1 = 1 To 8
Numerador(cont1) = Rot(cont1)
Next Cont1
'clear Resto() and Divisor()
For Cont1 = 1 To 8
Divisor(cont1) = 0
Resto(cont1) = 0
Next Cont1
Index = Kn
While Index > 0
'decrement index
Decr Index
'rotate Numerador thru carry
For Cont1 = 1 To 8
Rot(cont1) = Numerador(cont1)
Next Cont1
Call Leftshift()
For Cont1 = 1 To 8
Numerador(cont1) = Rot(cont1)
Next Cont1
'rotate Resto thru carry
For Cont1 = 1 To 8
Rot(cont1) = Resto(cont1)
Next Cont1
Call Leftshift()
For Cont1 = 1 To 8
Resto(cont1) = Rot(cont1)
Next Cont1
'Subtract Denominador() from Resto() and put in res()
For Cont1 = 1 To 8
Restado(cont1) = Resto(cont1)
Restando(cont1) = Denominador(cont1)
Next Cont1
Call Subtract()
'complement carry
If Carry = 0 Then
Carry = 1
Else
Carry = 0
End If
'If carry = 1 then Resto = res
If Carry = 1 Then
For Cont1 = 1 To 8
Resto(cont1) = Res(cont1)
Next Cont1
End If
'rotate divisor thru carry
For Cont1 = 1 To 8
Rot(cont1) = Divisor(cont1)
Next Cont1
Call Leftshift()
For Cont1 = 1 To 8
Divisor(cont1) = Rot(cont1)
Next Cont1
Wend
End Sub
'****************************************************
' Subroutine to subtract restando from restado in
' 64 bits with zero if both are equal and carry 1 if
' the result Res is negative
'****************************************************
Sub Subtract()
Zero = 1
Aux1 = 0
For Cont1 = 8 To 1 Step -1
If Zero = 1 Then
If Restado(cont1) <> Restando(cont1) Then
Zero = 0
If Restado(cont1) > Restando(cont1) Then
Carry = 0
Else
Carry = 1
End If
End If
End If
Next Cont1
If Zero = 0 Then
If Carry = 1 Then
For Cont1 = 1 To 8
Swap Restado(cont1) , Restando(cont1)
Next Cont1
End If
For Cont1 = 1 To 8
Aux2 = Restando(cont1) + Aux1
If Restado(cont1) < Aux2 Then
Aux3 = 256 - Aux2
Res(cont1) = Restado(cont1) + Aux3
Aux1 = 1
Else
Res(cont1) = Restado(cont1) - Aux2
Aux1 = 0
End If
Next Cont 1
Else
For Cont1 = 1 To 8
Res(cont1) = 0
Next Cont 1
Carry = 0
End If
End Sub
'****************************************************
' Subroutine to left shift thru Carry the 64 bits Rot
' carry should be 0 or 1
'****************************************************
Sub Leftshift()
For Cont1 = 1 To 8
If Rot(cont1) > 127 Then
Aux1 = 1
Else
Aux1 = 0
End If
Shift Rot(cont1) , Left , 1
Rot(cont1) = Rot(cont1) + Carry
Carry = Aux1
Next Cont1
End Sub
Hi,
thanks for the code! I did this years ago but my code would be difficult to port, writing it from scratch would have been easier.
When I get to successfully port your code to MikroC I will post it here.
One short question to your code, there are some variables defined as basic types (int and long, i.e. I assume 2-byte and 4-byte integers). Will those need to change if I go from 8-byte calculations to 12-byte calculations? Or is all that is needed to basically replace all 8s in the code with 12s (loop limits, array sizes)?
Thanks,
Wolfgang
thanks for the code! I did this years ago but my code would be difficult to port, writing it from scratch would have been easier.
When I get to successfully port your code to MikroC I will post it here.
One short question to your code, there are some variables defined as basic types (int and long, i.e. I assume 2-byte and 4-byte integers). Will those need to change if I go from 8-byte calculations to 12-byte calculations? Or is all that is needed to basically replace all 8s in the code with 12s (loop limits, array sizes)?
Thanks,
Wolfgang
I converted the routines to MikroC and spent some time optimizing them for speed and memory. Runs now about 3x as fast as the converted original. I also cleaned up the code - all variables are local and the functions do not modify their input values, only the result values.
Still some things to do - the array indices are 1-based, which wastes a byte per value, need to make them zero based. Also, I need to make the routines usable for larger (>4 byte) numbers.
I plan to add functions to convert the numbers to/from decimal text strings, and implement an "add" function.
Anyway, as promised here is the converted code - hope it is useful!
Wolfgang
Still some things to do - the array indices are 1-based, which wastes a byte per value, need to make them zero based. Also, I need to make the routines usable for larger (>4 byte) numbers.
I plan to add functions to convert the numbers to/from decimal text strings, and implement an "add" function.
Anyway, as promised here is the converted code - hope it is useful!
Wolfgang
Code: Select all
#include <built_in.h>
//'*************************************
//' variables declare in the subroutines
//'*************************************
char val1[9];
char val2[9];
char val3[9];
char val4[9];
char rem[9];
//'*************************************
//' function prototypes
//'*************************************
void multiply(char* value1, char* value2, char* result);
void divide(char* value1, char* value2, char* result, char* remainder);
void subtract(char* value1, char* value2, char* result, char* carry);
void leftshift(char* value, char* carry);
void add(char* value1, char* value2, char* result);
void convert_dec_to_bin(char* dec_val, char* bin_val);
void convert_bin_to_dec(char* bin_val, char* dec_val);
//'****************************************************
//' calculates "value1 * value2" and stores result in "result"
//'****************************************************
void multiply(char* value1, char* value2, char* result)
{
char i, j;
unsigned long aux4;
aux4 = 0;
for (i = 1; i <= 8; i++)
{
for (j = i; j >= 1; j--)
{
aux4 = aux4 + value1[j] * value2[i + 1 - j];
}
result[i] = Lo(aux4);
aux4 = aux4 >> 8;
}
}
//'****************************************************
//' Calculates "value1 / value2"
//' stores result in "result" and remainder in "remainder"
//'****************************************************
void divide(char* value1, char* value2, char* result, char* remainder)
{
char i;
char aux1;
char kn;
char kw;
char carry;
char res[9];
char value1_copy[9];
kw = 64;
carry = 0;
// calculate kn number of significant bits in value1
remainder[3] = 1;
memcpy (value1_copy, value1, 9);
for (i = 1; i <= 8; i++)
for (aux1 = 0; aux1 <= 7; aux1++)
{
remainder[1] = 1 << aux1;
remainder[2] = value1_copy[i] & remainder[1];
if (remainder[2])
kn = remainder[3];
++(remainder[3]);
}
// in kn there is the significant bits
// left justify the value1_copy
remainder[1] = kw - kn;
for (i = 1; i <= remainder[1]; i++)
leftshift(value1_copy, &carry);
memset (result, 0, 9);
memset (remainder, 0, 9);
i = kn;
while (i--)
{
leftshift(value1_copy, &carry);
leftshift(remainder, &carry);
subtract (remainder, value2, res, &carry);
carry = carry ? 0 : 1;
if (carry)
memcpy (remainder, res, 9);
leftshift(result, &carry);
} // end while
}
//'****************************************************
//' calculates "value1 - value2", stores result in "result"
//' "carry" is 1 if result is negative
//'****************************************************
void subtract(char* value1, char* value2, char* result, char* carry)
{
char i;
char dummy;
char aux1;
char zero;
unsigned int aux2;
char value1_copy[9];
char value2_copy[9];
zero = 1;
aux1 = 0;
memcpy (value1_copy, value1, 9);
memcpy (value2_copy, value2, 9);
for (i = 8; i >= 1; i--)
{
if (zero)
{
if (value1_copy[i] != value2_copy[i])
{
zero = 0;
*carry = (value1_copy[i] > value2_copy[i]) ? 0 : 1;
}
}
}
if (!zero)
{
if (*carry)
for (i = 1; i <= 8; i++)
{
dummy = value1_copy[i];
value1_copy[i] = value2_copy[i];
value2_copy[i] = dummy;
}
for (i = 1; i <= 8; i++)
{
aux2 = value2_copy[i] + aux1;
if (value1_copy[i] < aux2)
{
result[i] = value1_copy[i] + (256 - aux2);
aux1 = 1;
}
else
{
result[i] = value1_copy[i] - aux2;
aux1 = 0;
}
}
}
else
{
for (i = 1; i <= 8; i++)
result[i] = 0;
*carry = 0;
}
}
//'****************************************************
//' Subroutine to left shift value with carry bit
//'****************************************************
void leftshift(char* value, char* carry)
{
char i;
char aux1;
for (i = 1; i <= 8; i++)
{
aux1 = (value[i] > 127) ? 1 : 0;
value[i] = (value[i] << 1) + (*carry);
*carry = aux1;
}
}
void main (void)
{
char i;
for (i = 1; i <= 8; i++)
val3[i] = 0;
val1[1] = 0x16;
val1[2] = 0x25;
val1[3] = 0x02;
val1[4] = 0x88;
val1[5] = 0;
val1[6] = 0;
val1[7] = 0;
val1[8] = 0;
val2[1] = 0x44;
val2[2] = 0x55;
val2[3] = 0x66;
val2[4] = 0x77;
val2[5] = 0;
val2[6] = 0;
val2[7] = 0;
val2[8] = 0;
// carry = 1;
multiply(val1, val2, val3);
divide(val3, val2, val4, rem); // should yield val1
divide(val3, val1, val4, rem); // should yield val2
}
Ok, I ended up rewriting the routines from scratch. The new routines work with numbers of arbitrary length (almost - since I restrict counters to char and signed char, the limit is 127 bytes, but that won't be an issue given the restricted memory space on a PIC :-) Just change the constant definition for the length. The array indexes are zero based so no RAM space gets wasted.
I did not yet have time to test the routines comprehensively, but I did do a number of spot checks. Feedback and bug reports are highly appreciated. I still need to implement conversion routines to and from text strings.
Performance is almost 10x faster than the routines posted above. My simulator says a division of two 8-byte numbers takes 20 msec or less (the larger the divisor, the faster; dividing by 1 is the worst case). Multiplication of two 8-byte numbers is around 2 msec. Addition and subtraction is around 0.1msec. All those numbers are on a PIC16F887; an 18F series PIC should be quite a bit faster because of its built-in hardware multiplier.
Note that the routines do no error checking whatsoever, so you need to make sure you don't get overflow etc. But none of the routines should ever modify its input parameters (important e.g. in order to assign the result to one of the input parameters) - let me know in case that happens anywhere.
Wolfgang
Here is the code:
I did not yet have time to test the routines comprehensively, but I did do a number of spot checks. Feedback and bug reports are highly appreciated. I still need to implement conversion routines to and from text strings.
Performance is almost 10x faster than the routines posted above. My simulator says a division of two 8-byte numbers takes 20 msec or less (the larger the divisor, the faster; dividing by 1 is the worst case). Multiplication of two 8-byte numbers is around 2 msec. Addition and subtraction is around 0.1msec. All those numbers are on a PIC16F887; an 18F series PIC should be quite a bit faster because of its built-in hardware multiplier.
Note that the routines do no error checking whatsoever, so you need to make sure you don't get overflow etc. But none of the routines should ever modify its input parameters (important e.g. in order to assign the result to one of the input parameters) - let me know in case that happens anywhere.
Wolfgang
Here is the code:
Code: Select all
// APIM - Arbitrary Precision Integer Math
//
// Language: MikroC, for Microchip PIC
//
// arithmetic functions for positive integers of (almost) arbitrary length
// algorithms should work for up numbers consisting of up to 127 bytes
// note that no error checking is done (e.g. for overflow)
#include <built_in.h>
#define APIM_LENGTH 8 // size of numbers in bytes
// values are stored as array of char, LSB first, i.e.
// myvar[0] holds LSB, and myvar[APIM_LENGTH-1] holds MSB
void apim_add (char* oper1, char* oper2, char* result);
char apim_sub (char* oper1, char* oper2, char* result);
void apim_mult (char* oper1, char* oper2, char* result);
void apim_div (char* oper1, char* oper2, char* result, char* remainder);
void apim_inc (char* oper1);
signed char apim_compare(char* oper1, char* oper2);
void apim_shift_left_by_1 (char* oper);
void apim_shift_left_by_8N (char* oper, char n);
void apim_shift_left (char* oper, unsigned int shift_distance);
void apim_shift_right_by_1 (char* oper);
/* not implemented yet
void apim_print_hex (char* val_bin, char* val_string);
void apim_print_dec (char* val_bin, char* val_string);
void apim_scan (char* val_string, char* val_bin);
*/
// calculates (oper1 + oper2)
void apim_add (char* oper1, char* oper2, char* result)
{
char i;
char carry;
char oper2_copy;
for (i = 0, carry = 0; i < APIM_LENGTH; i++)
{
oper2_copy = oper2[i]; // make a copy in case result and oper2 point to the same memory location
carry = ((result[i] = oper1[i] + oper2_copy + carry) < oper2_copy) ? 1 : 0;
}
}
// calculates (oper1 - oper2)
// returns 0 if result is positive, 1 if result is negative (negative result is unusable = incorrect)
char apim_sub (char* oper1, char* oper2, char* result)
{
char i;
char carry;
char oper1_copy, oper2_copy;
for (i = 0, carry = 0; i < APIM_LENGTH; i++)
{
oper1_copy = oper1[i]; // make a copy in case result and oper1 point to the same memory location
oper2_copy = oper2[i]; // make a copy in case result and oper2 point to the same memory location
result[i] = oper1_copy - oper2_copy - carry;
carry = (oper1_copy >= (oper2_copy + carry)) ? 0 : 1;
}
return carry;
}
// calculates (oper1 * oper2)
void apim_mult (char* oper1, char* oper2, char* result)
{
char i, j;
char partial_prod[APIM_LENGTH];
unsigned int byte_prod;
char carry;
memset (result, 0, APIM_LENGTH);
for (i = 0; i < APIM_LENGTH; i++)
{
for (j = 0; j < APIM_LENGTH; j++)
{
byte_prod = oper1[j] * oper2[i] + carry;
carry = hi (byte_prod);
partial_prod[j] = lo (byte_prod);
}
apim_shift_left_by_8N (partial_prod, i);
apim_add (result, partial_prod, result); // IMPORTANT: don't exchange result and partial_prod (will mess up apim_add)
}
}
// calculates (oper1 / oper2)
void apim_div (char* oper1, char* oper2, char* result, char* remainder)
{
char i, shift_counter;
char oper2_copy[APIM_LENGTH];
shift_counter = 0;
memcpy (oper2_copy, oper2, APIM_LENGTH); // never modify input parameters!
while (oper2_copy[APIM_LENGTH-1] == 0) // this will become an eternal loop if (oper2 == 0) (division by zero)
{
apim_shift_left_by_8N (oper2_copy, 1);
shift_counter = shift_counter + 8;
}
while ((oper2_copy[APIM_LENGTH-1] & 0b10000000) == 0)
{
apim_shift_left_by_1 (oper2_copy);
shift_counter++;
}
memcpy (remainder, oper1, APIM_LENGTH);
memset (result, 0, APIM_LENGTH); // do after memcpy above, in case result and oper1 point to the same location
for (i = 0; i <= shift_counter; i++)
{
apim_shift_left_by_1 (result);
if (apim_compare (remainder, oper2_copy) >= 0)
{
apim_inc (result);
apim_sub (remainder, oper2_copy, remainder);
}
apim_shift_right_by_1 (oper2_copy);
}
}
// left-shifts oper by an arbitrary amount of bits
void apim_shift_left (char* oper, unsigned int n)
{
char i;
apim_shift_left_by_8N (oper, n >> 3);
for (i = (n & 7); i > 0; i--)
{
apim_shift_left_by_1 (oper);
}
}
// left-shifts oper in steps of full bytes (8 bits)
void apim_shift_left_by_8N (char* oper, char n)
{
memmove (oper + n, oper, APIM_LENGTH - n);
memset (oper, 0, n);
}
// left-shifts oper by one bit
void apim_shift_left_by_1 (char* oper)
{
unsigned int i;
char carry, carry_new;
for (i = 0, carry = 0; i < APIM_LENGTH; i++)
{
carry_new = ((oper[i]) & 0b10000000) ? 1 : 0;
oper[i] = (oper[i] << 1) + carry;
carry = carry_new;
}
}
// right-shifts oper by one bit
void apim_shift_right_by_1 (char* oper)
{
signed int i;
char carry, carry_new;
for (i = APIM_LENGTH - 1, carry = 0; i >= 0; i--)
{
carry_new = (oper[i] & 0b00000001) ? 0b10000000 : 0;
oper[i] = (oper[i] >> 1) + carry;
carry = carry_new;
}
}
// compares two numbers
// returns: 0 = numbers are equal, 1 = oper1 is larger, -1 = oper1 is smaller
signed char apim_compare(char* oper1, char* oper2)
{
signed char i;
i = APIM_LENGTH - 1;
while ((oper1[i] == oper2[i]) && (i >= 0)) i--;
if (i < 0)
{
return 0; // numbers are equal
}
else if (oper1 [i] > oper2 [i])
{
return 1; // oper1 is larger
}
else
{
return -1; // oper1 is smaller
}
}
// increments oper1 by 1
void apim_inc (char* oper1) // increments oper1 by 1
{
char i;
char carry;
unsigned int dummy;
dummy = 1;
for (i = 0; i < APIM_LENGTH; i++)
{
dummy = dummy + oper1[i];
oper1[i] = lo(dummy);
dummy = hi(dummy);
}
}
char my_carry;
void main()
{
char val1[APIM_LENGTH] = {0x19,0x28,0x37,0x46,0x00,0x00,0x00,0x00};
char val2[APIM_LENGTH] = {0xff,0x11,0xee,0x66,0x00,0x00,0x00,0x00};
char res[APIM_LENGTH] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char resdiv[APIM_LENGTH] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char rem[APIM_LENGTH] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char one[APIM_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char onetofour[APIM_LENGTH] = {0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00};
apim_mult (val1, val2, res);
apim_div (res, val1, resdiv, rem); // should yield val2
apim_div (res, val2, resdiv, rem); // should yield val1
apim_div (res, one, resdiv, rem); // should yield res
apim_inc (res);
apim_div (res, val2, resdiv, rem); // should yield val1 and rem=1
apim_add (res, onetofour, res);
apim_div (res, val2, resdiv, rem); // should yield val1 and rem=04 03 02 02
my_carry = apim_sub (val1, val2, res);
my_carry = apim_sub (val2, val1, res);
apim_mult (val1, val2, res);
apim_mult (val2, val1, res);
apim_shift_left (val1,13);
apim_shift_left_by_1 (val1);
apim_shift_left_by_1 (val1);
apim_shift_left_by_1 (val1); // should yield original val1 shifted by 2 bytes
}
Hi sir.
w r t the post under "How to calculate with 32 Bit variables => 64 Bit needed"
i was not able to find the logic behind the add_apim function.
According to ur logic
If for eg: LENGTH=4
03FFFF08 +
01555555
will yield 0455545D rather than 0555545D
It can be corrected by knowing the carry flag in the STATUS REGISTER using Assembly...
Also let me kno if there is any way to acccess the CARRY flag using MikroC...
With Regards
Luttappy
w r t the post under "How to calculate with 32 Bit variables => 64 Bit needed"
i was not able to find the logic behind the add_apim function.
According to ur logic
If for eg: LENGTH=4
03FFFF08 +
01555555
will yield 0455545D rather than 0555545D
It can be corrected by knowing the carry flag in the STATUS REGISTER using Assembly...
Also let me kno if there is any way to acccess the CARRY flag using MikroC...
With Regards
Luttappy
Hi luttappy,
thanks for alerting me to this behavior! - it is indeed a bug in my code that happens whenever operand 2's byte is 0xff and carry is 1. I fixed the code, below is the corrected apim_add function. I checked and your example now produces the expected result.
Wolfgang
thanks for alerting me to this behavior! - it is indeed a bug in my code that happens whenever operand 2's byte is 0xff and carry is 1. I fixed the code, below is the corrected apim_add function. I checked and your example now produces the expected result.
Wolfgang
Code: Select all
// calculates (oper1 + oper2)
void apim_add (char* oper1, char* oper2, char* result)
{
char i;
char carry;
char oper2_copy;
unsigned int res;
for (i = 0, carry = 0; i < APIM_LENGTH; i++)
{
oper2_copy = oper2[i]; // make a copy in case result and oper2 point to the same memory location
res = oper1[i] + oper2_copy + carry;
result[i] = lo(res);
carry = hi(res);
}
}