Phát hiện tràn với C18


7

Tôi đang thực hiện một máy tính trong một vi điều khiển được điều khiển qua cổng nối tiếp. Ví dụ, tôi sẽ gửi 1234*5678=và nó sẽ trả lời 7006652\r\n. Tôi đã viết mã cho điều này bằng trình biên dịch C18.

Khi tôi gửi 123456*789123=, tôi nhận được trả lời 2932688576, không chính xác. Câu trả lời đúng sẽ có 97421969088, nhưng điều đó tràn ra unsigned long.

Tôi không muốn tăng giới hạn tràn, nhưng muốn có cách kiểm tra xem có bị tràn không. Trong ASM, điều đó có thể thực hiện được bằng cách kiểm tra bit có liên quan trong thanh ghi STATUS, tuy nhiên, với C, bit này sẽ bị xóa trước khi tôi có thể đọc nó, phải không?

Cách tốt nhất sẽ là một giải pháp chung để xem có xảy ra tràn không.

pic  c  software  c18 

Một cách rõ ràng là sử dụng Ada, ví dụ Gnat với các kiểm tra tràn được bật. Thật không may, mặc dù điều đó sẽ hoạt động với AVR hoặc MSP430 hoặc ARM, tôi không biết trình biên dịch phù hợp cho PIC.
Brian Drumond

Tôi cảm thấy điều này có thể giống như một câu hỏi stackoverflow.com, và chắc chắn, một tìm kiếm đã đưa tôi đến đó. Tôi đã kết luận, sau một số bài đọc, rằng không có câu trả lời đơn giản cho điều này (dù sao cũng sử dụng C).
gbarry

@gbarry bạn có thể cho tôi một liên kết đến câu hỏi SO liên quan không?

1
Tôi đã tìm kiếm trên "thuật toán kiểm tra tràn" và nhận được điều này: stackoverflow.com/questions/2713972 Và nhận xét đầu tiên là một liên kết đến một câu hỏi tương tự ... stackoverflow.com/questions/199333
gbarry

Câu trả lời:


3

Có thể có các thủ thuật liên quan đến thanh ghi STATUS nhưng mã chung (chưa được kiểm tra) sau đây là điều tôi nghĩ đến để kiểm tra số lượng bit cần thiết để đại diện cho mỗi đầu vào bằng cách thực hiện các thao tác dịch chuyển bit phải lặp lại cho đến khi giá trị trống.

Sau đó, bằng cách cộng hai kết quả lại với nhau, bạn sẽ có thể tìm ra nếu đầu ra sẽ tràn 32 bit.

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);

2

Chỉ cần để kết quả bên trong rộng bằng tổng chiều rộng của toán hạng, sau đó kiểm tra xem kết quả không cao hơn mức cho phép bên ngoài. Nếu PIC18 có hệ số nhân phần cứng, thì điều này không thực sự tốn kém về mặt tính toán và hoàn toàn chính xác, không giống như phương pháp xác định tổng vị trí của chữ số khác không quan trọng nhất của toán hạng.

Xem pg 174 của tài liệu trong http://ptgmedia.pearsoncmg.com/images/0321335724/samplech CHƯƠNG / seacord_ch05.pdf


PIC18 có hệ số nhân phần cứng 8 bit, do đó nhân với số lớn hơn là "hợp lý" nhanh.
gbarry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.