Odpověď na názor

Odpovídáte na názor k článku Specifika instrukční sady mikroprocesorů Intel 8086/8088 (2). Názory mohou přidávat pouze registrovaní uživatelé. Nově přidané názory se na webu objeví až po schválení redakcí.

  • 19. 9. 2024 22:29

    radioing

    Jj, vypocty na 8bitech byly peklo. V drevnich dobach jsme se ucili zaklady DSP (zde P = processing) na pripravcich s 8051...
    Pred 20 lety jsem presel na ARMy a tam treba na slabych Cortexech s jednocyklovou nasobickou, ale casove drahym delenim konci rychla konverze utoa treba takto:

    uint8_t * bin2dec(uint32_t u, uint8_t * dest)
    {
        uint8_t * d = dest;
        uint64_t r;
    
        if (u < 100UL) {
            /* 1 & 2 digits */
            ECHO2DECDIGCOND(d, u)
            goto lm0;
    
        } else if (u < 1000000UL) {
    
            if (u < 10000UL) {
                /* 3 & 4 digits */
                /* (100..9999) * (2^32 / 100) -> 2^32 / 100 = 42,949,672.96 -> 42,949,673 */
                r = (uint64_t)u * 42949673UL;
                u = (uint32_t)(r >> 32U);
                ECHO2DECDIGCOND(d, u)
                d += 2UL;
                goto lm2;
            } else {
                /* 5 & 6 digits */
                /* 10000..999999 * (2^32 / 10000) -> 2^32 / 10000 = 429,496.7296 -> 429,497 */
                r = (uint64_t)u * 429497UL;
                u = (uint32_t)(r >> 32U);
                ECHO2DECDIGCOND(d, u)
                d += 4UL;
                goto lm4;
            }
    
        } else {
    
            if (u < 100000000UL) {
                /* 7 & 8 digits */
                /* 1000000..99999999 * (2^32 / 1000000) -> 2^32 / 1000000 = 4,294.967296 -> 4,294 */
                /* The multiplication precision is not sufficient */
                /* 1000000..99999999 * (2^(32 + 16) / 1000000) -> 2^(32 + 16) / 1000000 = 281,474,976.710656 -> 281,474,977 */
                r = ((uint64_t)u * 281474977UL) >> 16U;
                u = (uint32_t)(r >> 32U);
                ECHO2DECDIGCOND(d, u)
                d += 6UL;
                goto lm6;
            } else if (u <= 1160773632UL) {
                // 9 & 9+1/2 digits
                /* 100000000..4294967295 * (2^32 / 100000000) -> 2^32 / 100000000 = 42.94967296 -> 43 */
                /* The multiplication precision is not sufficient */
                /* 100000000..1160872980 * (2^(32 + 25) / 100000000) -> 2^(32 + 25) / 100000000 = 1,441,151,880.75855872 -> 1,441,151,882 ! */
                // -> it works up to 1160872980 only!
                // For immediate comparison -> 1,160,773,632 <-> 0x45300000 11-bit value
                r = ((uint64_t)u * 1441151882UL) >> 25U;
                u = (uint32_t)(r >> 32U);
                ECHO2DECDIGCOND(d, u)
                goto lm8;
            } else {
                /* 10 digits */
                /* 100000000..4294967295 * (2^32 / 100000000) -> 2^32 / 100000000 = 42.94967296 -> 43 */
                /* The multiplication precision is not sufficient */
                /* 100000000..4294967295 * (2^(32 + 25) / 100000000) -> 2^(32 + 25) / 100000000 = 1,441,151,880.75855872 -> 1,441,151,881 */
                r = (uint64_t)u * 1441151881UL;
                u = (uint32_t)(r >> 57U);
                ECHO2DECDIGCOND(d, u)
                /* Fix back to 32-bit fraction */
                r >>= 25U;
                goto lm8;
            }
        }
        lm8:
            r = (r & 0xFFFFFFFFUL) * 100UL;
            u = (uint32_t)(r >> 32U);
            ECHO2DECDIG(d - 8UL, u)
            d += 8UL;
        lm6:
            r = (r & 0xFFFFFFFFUL) * 100UL;
            u = (uint32_t)(r >> 32U);
            ECHO2DECDIG(d - 6UL, u)
        lm4:
            r = (r & 0xFFFFFFFFUL) * 100UL;
            u = (uint32_t)(r >> 32U);
            ECHO2DECDIG(d - 4UL, u)
        lm2:
            r = (r & 0xFFFFFFFFUL) * 100UL;
            u = (uint32_t)(r >> 32U);
            ECHO2DECDIG(d - 2UL, u)
        lm0:
    
        *d = 0U;
        return d;
    }

    To ECHO... makro neni nic jineho nez sahnuti do 200bajtove tabulky dvojic znaku. Cilem bylo zvolit takove multiplikativni konstanty, aby byly potreba 32bitove posuny, tj. zadne, takze to uint64_t je vicemene takova berlicka pro C.