manipulating bit fields in c noah mendelsohn tufts university email:...

29
Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: [email protected] Web: http://www.cs.tufts.edu/~noah COMP 40: Machine Structure and Assembly Language Programming (Spring 2014)

Upload: susan-lakeman

Post on 02-Apr-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

Manipulating Bit Fields in C

Noah MendelsohnTufts UniversityEmail: [email protected]: http://www.cs.tufts.edu/~noah

COMP 40: Machine Structure and

Assembly Language Programming (Spring 2014)

Page 2: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Goals for this presentation

Learn to use C language to pack and extract bit fields

Also: learn exact width C integer types

2

Page 3: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Warning:

Because it makes the examples easier to understand, some of the code in these slides uses

the syntax:

0b11001001

for literals. This is a GNU extension to the C language that is not allowed in COMP 40 code. You

may use hex literals like this:

0xC9

as they are standard.

Page 4: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Exact Width Integer Types

Page 5: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Why exact width integer types?

The problem: C integer types aren’t fixed size– Size of char, int, long, etc. depends on platform and compiler

– Sometimes we need to get a known size

The solution: stdint.h defines fixed size integers– int32_t: 32 bit signed integer– uint32_t: 32 bit unsigned integer– int16_t: 16 bit signed integer– uint64_t: 64 bit unsigned integer– Etc.

When writing bit packing code, you need to know or account for the size of the integers you’re manipulating

5

Page 6: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Why Bother with Bit Fields?

Page 7: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Why use bit fields?

Save space:– Storing 10 million values each ranging from 0-10

– If each is a 32 bit int: 40 megabytes

– If each is a 4 bit int: 5 megabytes

Manipulate standard file formats and network packets

7

Page 8: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

32 bits

V HDLN SVC TYPE LENGTH

ID FLGS FRAG OFFSET

TTL PROTOCOL HDR CHECKSUM

SOURCE ADDRESS

DESTINATION ADDRESS

OPTIONS

THE TCP OR UDP DATA (VARIABLE LEN)

Example: Internet Protocol Packet

8

How can we extract this 8 bit protocol number from the 32 bit field?

Page 9: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Extracting Bit Fields

Page 10: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Extracting a bit field

10

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0; *

* Note that extra spaces have been used in these boolean literals to make them, easier to read. Such spaces are not allowed in code (and, as previously noted, the 0b1001 syntax is a GNU extension not allowed in COMP 40 submissions anyway).

Page 11: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Extracting a bit field

11

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0;

“and” together i and mask

(i & mask) == 0b 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0;

Create mask to select bits we need

Page 12: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Extracting a bit field

12

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0;

“and” together i and mask?

(i & mask) == 0b 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0;

… and shift to finish the job

(i & mask) >> 5 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

Page 13: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Be careful with signed shifts

13

uint16_t u = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1;

In this example, masking leaves on high order bit

(u &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;(i &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

Page 14: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Be careful with signed shifts

14

uint16_t u = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1;

In this example, masking leaves on high order bit

(u &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;(i &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

Unsigned is correctSigned has unwanted leading 1’s

Page 15: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Be careful with signed shifts

15

uint16_t u = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1;

In this example, masking leaves on high order bit

u &= mask: 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1;i &= mask == 0b 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1;

Huh? Turns out that right shifting of a signed integer is implementation define…but

why?

C wants these operations to be super-efficient, and on some hardware there’s no

efficient signed shift.

On our systems, the sign will propagate and you may count on that in your

homework submissions.

Page 16: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

How can we choose the bits to extract at runtime?

16

unsigned short i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;int width = 3; int offset = 5;

/* mask is now 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 */

mask = mask >> (16 - width) << (offset);

This time we’ll have to compute the mask

unsigned short mask = ~0;

/* mask is now 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */

(i & mask) >> offset == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

Now, finish the job as before

Page 17: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

We can adapt to integer size at runtime

17

unsigned short i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;int width = 3; int offset = 5;

/* mask is now 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 */

mask = mask >> (number_of_bits - width) << (offset);

This time we’ll have to compute the mask

unsigned short mask = ~0;

/* mask is now 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */

(i & mask) >> offset == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

Now, finish the job as before

const number_of_bits = sizeof(unsigned short) * 8;

Page 18: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Setting Bit Fields

Page 19: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Putting new value in a bit field

20

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

Page 20: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Putting new value in a bit field

21

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask…

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

Important: we have zeros where new value is going

Page 21: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Putting new value in a bit field

22

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask…

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

… shift the new value and use “or” to combine

(i | (new_value << 5)) == 0b 1 0 0 1 1 1 0 0 0 1 0 0 1 1 1 0;

Page 22: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Flag Bits

Page 23: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Very common idiom – single bit flags

24

/* Flag definitions */const uint16_t HI_PRIORITY = 0x8000;const uint16_t SECURE = 0x4000;const uint16_t ARCHIVED = 0x2000;…const uint16_t BEAUTIFUL = 0x0002;const uint16_t SPECTACULAR = 0x0001;

One bit each

Page 24: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Very common idiom – single bit flags

25

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

Can use binary instead of hex, but hard to count the

zeros!

Page 25: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Initializing flags

26

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

Use | to combine bits

uint16_t myflags = SECURE | BEAUTIFUL; /* secure and beautiful */

Page 26: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Testing flags

27

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

Test flags with & remember C treats

anything != 0 as true!

if (myflags & BEAUTIFUL) {…}; /* if beautiful */

Page 27: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Testing flags

28

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

Testing multiple flags on

if ((myflags & (BEAUTIFUL | SECURE)) == (BEAUTIFUL | SECURE)) {…}; /* if beautiful and secure */

Page 28: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Turning flags on

29

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

Us | to turn on additional flags

myflags |= ARCHIVED; /* now it’s archived too */

Page 29: Manipulating Bit Fields in C Noah Mendelsohn Tufts University Email: noah@cs.tufts.edunoah@cs.tufts.edu Web: noah COMP 40: Machine

© 2010 Noah Mendelsohn

Turning flags off

30

/* Flag definitions */const uint16_t HI_PRIORITY = 0b1000000000000000;const uint16_t SECURE = 0b0100000000000000;const uint16_t ARCHIVED = 0b0010000000000000;…const uint16_t BEAUTIFUL = 0b0000000000000010;const uint16_t SPECTACULAR = 0b0000000000000001;

To turn off, & with all the other flags!

myflags &= ~BEAUTIFUL; /* but not beautiful anymore */