Qaimaq
Qaimaq

Reputation: 147

Am I wrong with these shiftings?

I have a 14 bits address with leading zeros and I want to divide it into page number and offset. I was trying to solve it with shifting the address but my offset is getting wrong value, however the page number shows up correctly. Can you point where I am wrong here?

Page numbers bits are [2:5] Offset bits are [6:15]

struct Mem
{
 unsigned int address = 0x0000;
 unsigned int pageNum = 0x0;
 unsigned int pageOff = 0x000;
}

int main()
{
 Mem box;

 box.address = 0x0ad0;
 box.pageNum = (box.address << 2) >> 12;
 box.pageOff = (box.address << 6) >> 6;

return 0;
}

Upvotes: 0

Views: 83

Answers (1)

Gillespie
Gillespie

Reputation: 6561

Shifting left to clear out digits is a dangerous game, in my opinion, because if you happen to be using int instead of unsigned int, you might get a sign extend you didn't intend. I recommend shifting and masking:

If your address looks like this:

X X P P P P O O O O O O O O O O

Where P is page numbers and O is offsets then you would do:

box.pageNum = (box.address >> 10) & 0xf; // 0xf is 1111 in binary, so it only keeps the right 4 binary digits
box.pageOff = box.address & 0x3ff; // 0x3ff is 1111111111 in binary, so it only keeps the right 10 digits

However, as Remy pointed out you could just use bit fields (https://en.cppreference.com/w/c/language/bit_field) like:

struct Address
{
    unsigned int offset : 10;
    unsigned int page_num : 4;
}

...

Address a;
a.page_num; // assign it directly
a.offset; // assign it directly

Upvotes: 3

Related Questions