Detección de desbordamiento con C18

Estoy implementando una calculadora en un microcontrolador que se controla a través del puerto serie. Por ejemplo, enviaría 1234*5678=y respondería con 7006652\r\n. He escrito el código para esto usando el compilador C18.

Cuando envío 123456*789123=, recibo la respuesta 2932688576, que es incorrecta. La respuesta correcta hubiera sido 97421969088, pero eso desborda un unsigned long.

No quiero aumentar el límite de desbordamiento, pero me gustaría tener una forma de verificar si ha habido un desbordamiento. En ASM, eso sería posible al verificar el bit relevante en el registro de ESTADO, sin embargo, con C, este bit se borraría antes de que pudiera leerlo, ¿no es así?

Lo mejor sería una solución general para ver si se ha producido un desbordamiento.

Una forma obvia sería usar Ada, por ejemplo, Gnat con las comprobaciones de desbordamiento activadas. Desafortunadamente, aunque eso debería funcionar con AVR o MSP430 o ARM, no conozco un compilador adecuado para PIC.
Sentí que esto podría ser más como una pregunta de stackoverflow.com y, efectivamente, una búsqueda me llevó directamente allí. Concluí, después de leer un poco, que no hay una respuesta simple para esto (usando C, de todos modos).
@gbarry, ¿puede darme un enlace a la pregunta SO relevante?
Busqué en "desbordamiento de verificación de algoritmo" y obtuve esto: stackoverflow.com/questions/2713972 Y el primer comentario fue un enlace a una pregunta similar... stackoverflow.com/questions/199333

Respuestas (2)

Puede haber trucos con respecto al registro de ESTADO, pero el siguiente código genérico (no probado) es algo en lo que pensé para verificar la cantidad de bits necesarios para representar cada entrada al realizar operaciones repetidas de desplazamiento de bits a la derecha hasta que el valor esté vacío.

Luego, al sumar los dos resultados, debería poder determinar si la salida se desbordará en 32 bits.

unsigned long a = 123456;
unsigned long b = 789123;

int calc_bit_size(unsigned long v)
{
    int bit_count = 0;
    while (v > 0)
    {
        bit_count++;
        v >>= 1;
    }
    return bit_count;
}

if (calc_bit_size(a) + calc_bit_size(b) > 32)
   printf("Overflow!")
else
   printf("%lu", a * b);

Simplemente deje que el resultado interno sea tan ancho como la suma del ancho de los operandos, y luego verifique que el resultado no sea más alto que lo permitido externamente. Si el PIC18 tiene un multiplicador de hardware, esto no es realmente costoso desde el punto de vista computacional y es completamente preciso, a diferencia del método para determinar la suma de la posición del dígito distinto de cero más significativo de los operandos.

Consulte la página 174 del documento en http://ptgmedia.pearsoncmg.com/images/0321335724/samplechapter/seacord_ch05.pdf

PIC18 tiene un multiplicador de hardware de 8 bits, por lo que las multiplicaciones en números más grandes son "razonablemente" rápidas.