Skip to main content

I have come up with following version that seems to be working correctly for few test cases I have defined.

First we need a helper function that prints hex value given binary data:

void hexdump(unsigned char *data, int len)
{
    int c = 0;
    while (c < len)
    {
        cout << hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[c++]);
    }
    printf("\n");
}

Now lets define the actual function that takes block.bits and converts it to 256 bit value in memory:

bool convert_bits(uint32_t bits, uint64_t* value, int val_len = 4)
{
    assert(val_len == 4);
    assert(value != NULL);

    if (val_len != 4 || value == NULL)
    {
        return false;
    }

    // if bits =  0x1b0404cb, hex target = 0x0404cb * 2**(8*(0x1b - 3)) 
    uint32_t x = 8 * ((bits >> 24) - 3); // number of zero bits on right
    uint64_t val = bits & 0x00FFFFFF;

    // Number of maximum bits required for val is 24.
    assert(x <= (256 - 24));
    if (x > (256 - 24))
    {
        return false;
    }   

    int startq = (3 - int(x / 64));
    int endq = (3 - int((x + 24) / 64));

    int shift = ((3 + endq) * 64 - x);
    if (startq != endq)
    {
        shift = 64 - shift;
    }

    value[startq] = htobe64(val << shift);
    value[endq] = htobe64(val >> shift);

    return true;
}

Now lets test the above function:

int main()
{
    uint64_t num[4] = { 0, 0, 0, 0 };
    if(convert_bits(0x1b0404cb, num))
    {
        hexdump((unsigned char *)num, sizeof(uint64_t) * 4);
    }
    return 0;
}

This prints: 00000000000404cb000000000000000000000000000000000000000000000000