views:

83

answers:

5

It's been a while since my assembly class in college (20 years to be exact).

When someone gives you a number, say 19444, and says that X is bits 15 through 8 and Y are bits 7 through 0... how do I calculate values of X and Y?

I promise this is not homework, just a software guy unwisely trying to do some firmware programming.

+8  A: 

First of all convert the input number to hexadecimal:

19444 => 0x4BF4

Hex is convenient because every 4 binary bits are one hex digit. Hence, every 2 hex digits are 8 bits, or a byte. Now assuming traditional little-endian notation (look it up!), bits 7 downto 0 are the low byte, bits 15 downto 8 are the high byte:

   [7:0] => 0xF4
   [15:8] => 0x4B
Eli Bendersky
+1 for explaining things.
Kobi
Endianness is irrelevant (unless you're accessing individual bytes using pointer or union magic - which may be happening if this stuff is coming from a serial line etc.).
Artelius
@Artelius: I beg to differ. With some interpretations of endinaness, [7:0] (or rather [0:7]) would be the high byte. It is **very** relevant
Eli Bendersky
@Eli - can you give an example? In my experience, bits 0..7 are always the least significant byte - it's only the position of that byte in memory that varies based on endianness. If that's wrong, I'd like to know how much I need to worry about it.
Steve314
@Steve314: some processors specify their words as reg[0:31], where bits [0:7] are the high byte of the register and so on
Eli Bendersky
After doing some reading it seems Eli is right (http://en.wikipedia.org/wiki/Bit_numbering), but it seems braindead to me. IMO bits should always be numbered based on the power of 2 of their place value; this would greatly reduce complications resulting from endianness and word size.
Artelius
@Artelius: it's called "endianness" for a reason - a pun made by Johnathan Swift in his Gulliver books on the "brain-dead" debates about the end of the egg from which to start eating it. :-)
Eli Bendersky
@Eli - "Some processors" isn't an example. But from Artelius comment, I guess you're right.
Steve314
+3  A: 

Using your preferred language, you can get the least significant byte by using a bitwise AND:

Y = 19444 & 0xff

or, the more mathematical:

Y = 19444 % 256

Now, for the most significant byte you can use bit shifts (if the number is larget than two byte, apply the first stage again):

X = 19444 >> 8
Kobi
+1  A: 

Also, mind the byte order (wheter the most significant byte comes first).

Not in this case. *Bit* numbering might be relevant though.
Paul R
Byte order is not relevant here as there has been no mention of memory addresses.
Artelius
+1  A: 

When given bit positions (like "15 through 8"), by convention bit 0 is the least significant bit of the binary number. If you're dealing with a 16-bit number, then bit 15 is the most significant bit.

One hexadecimal digit corresponds to 4 binary digits. So hex FF is 11111111 in binary. Bitwise AND is often used to "mask out" a certain collection of bits.

Nearly all processors provide some form of bitwise shifting. For example, shifting 1010001 right by 4 bits gives you 101.

Combining all this, in C you would typically do something like this:

unsigned short int num;
unsigned char x, y;

num = 19444;

y = num & 0xff; //use bitwise AND to get 8 least-sig bits
x = num >> 8;   //right-shift by 8 bits to get 8 most-sig bits
Artelius
+3  A: 

(The following assumes C notation). In general, to access the value in bits N through M, where N is the smaller value and the bits are numbered from 0, use:

(value >> N) & (1U << (M - N + 1)) - 1;

So for bits 0..7, use:

(value >> 0) & (1U << 8) - 1

and for bits 8..15, use:

(value >> 8) & (1U << 8) - 1

Note that for the case where "N through M" is the entire width of the type, you can't use the shift as written.

caf