16+
Вторник
20 ноября
Вход |Карта сайта | |Upload |codebook | PARTS

 О смысле всего сущего 0xFF

 Средства и методы разработки

 Мобильная и беспроводная связь

 Блошиный рынок Объявления

caxapa

Микроконтроллеры ARM 

AVR PIC MSP PLD,FPGA,DSP 

Кибернетика Технологии 

Схемы, платы, компоненты 

Микроконтроллеры

 
   Новая тема Правила Регистрация Поиск »» Архив
Вернуться в конференциюТопик полностью
fk0  (06.09.2018 11:07, просмотров: 1687)
I need to print signed 64-bit numbers in decimal form. Program runs in freestanding environment (no C library available, libgcc may be unavailable too, or may not work correctly). So I can't use printf(3) function. 
I'am trying to write function, which will be able to convert number from binary form (int64_t) to ascii. Simple solution is to divide number by 10, and use remainder as next digit (from left to right, iteratively). Unfortunately, processor doesn't have 64 bit division, and I can't rely on libgcc in that (__udivdi3 function). So I invented other way to perform binary->decimal conversion, by using binary coded decimal (BCD) numbers. First I convert binary number to BCD form (bit by bit, need 64 iterations, and need to sum BCD numbers), then convert BCD to ASCII. See source code below, I hope, somebody suggests me some improvements...
/*static*/ void _print_dec(intmax_t num)
{
    char *p;
    char buf[24 /* > log10(2^64) */];
    uint_fast8_t r;
    uint64_t n = num < 0 ? -num : +num;

    uint_fast16_t result_h = 0, digit_h = 0;
    uint64_t result = 0, digit = 1;
    while (n != 0)
    {
        /* sum bcd numbers: r = a + b, where r should be L-value  */
        #define BCD_ADD(type, r, a, b) do { \
            type t1 = a + (type)(0x6666666666666666 & ((type)-1 >> 4)), t2 = t1 ^ b; \
            t1 += b, t2 = ~(t1 ^ t2) & (type)0x1111111111111110; r = t1 - (t2>>2 | t2>>3); \
        } while (0);

        /* this macro computes rh:rl = ah:al + bh:bl (sum of compound BCD number), rh:rl should be L-value */
        #define BCD_ADD_COMPOUND(type_h, type, rh, rl, ah, al, bh, bl) do { \
            uint_fast8_t c = 0; \
            type t1 = al, t2 = bl; \
            BCD_ADD(type, rl, al, bl); \
            c = rl >> (sizeof(type)*CHAR_BIT-4); \
            BCD_ADD(type_h, rh, ah, bh); \
            if (c >= 10 || (rl < t1 && rl < t2)) { \
                rl = (rl & ((type)-1 >> 4)) | ((c - 10ULL) << (sizeof(type)*CHAR_BIT-4)); \
                BCD_ADD(type_h, rh, rh, 1); \
            } \
        } while (0)

        if (n & 1)
            BCD_ADD_COMPOUND(uint_fast16_t, uint64_t, result_h, result, result_h, result, digit_h, digit);

        BCD_ADD_COMPOUND(uint_fast16_t, uint64_t, digit_h, digit, digit_h, digit, digit_h, digit);
        n >>= 1;
    }

    p = &buf[sizeof(buf) - 1];
    *p = 0;
    do {
        r = result & 0x0f;
        *--p = r + '0';
        result = (result >> 4) | ((uint64_t)(result_h & 0x0f) << (sizeof(uint64_t)*CHAR_BIT-4));
        result_h = result_h >> 4;

    } while (result_h != 0 || result != 0);

    if (num < 0) *--p = '-';
    print_cstr(p);
}

[ZX]
Главная | Карта сайта | О проекте | Проекты | Файлообменник | Регистрация | Вебмастер | RSS
Лето 7527 от сотворения мира. При использовании материалов сайта ссылка на caxapу обязательна.
MMI © MMXVIII