Last Updated: 2023-02-17 Fri 14:30

CSCI 2021 HW05: Float Layout, Unions, Debugging

CODE DISTRIBUTION: hw05-code.zip

CHANGELOG:

Fri Feb 17 02:29:42 PM CST 2023
Fixed additional broken links later in the HW.
Wed Feb 15 09:33:27 AM CST 2023
Fixed broken link to GDB tutorial in "Associated Reading"

1 Rationale

This HW introduces bit-level representations of quantities in C. It covers some basic bit operations such as bitwise AND along with shifts. It also explores the binary layout of floating point numbers which is significantly different from integers. The C union construct is used to demonstrate aspects of float layout. There are also several problems presented which are best solved using the gdb debugger and instructions are given to motivate its use.

Associated Reading / Preparation

  • Bryant and O'Hallaron: Ch 2.1-2.3 on binary representations of integers in unsigned and two's complement signed format.
  • Bryant and O'Hallaron: Ch 2.4 (skim) on binary representations of floating point numbers.
  • C References: Unions
  • CSCI 2021 Quick Guide to gdb: The GNU Debugger: Page describing how to start the debugger, a sample session using puzzlebox, an overview of the most common commands.

Grading Policy

Credit for this HW is earned by taking the associated HW Quiz which is linked under Gradescope. The quiz will ask similar questions as those that are present in the QUESTIONS.txt file and those that complete all answers in QUESTIONS.txt should have no trouble with the quiz.

Homework and Quizzes are open resource/open collaboration. You must submit your own work but you may freely discuss HW topics with other members of the class.

See the full policies in the course syllabus.

2 Codepack

The codepack for the HW contains the following files:

File Description
QUESTIONS.txt Questions to answer
collatz.c Problem 1 source showing bitwise operations
union.c Problem 2 source demonstrating unions and floating point bits
debug_scramble.c Problem 3A source to debug
debug_long.c Problem 3B source to debug

3 Bitwise Operations

Ensure that you get acquainted with C bitwise operators typically used with integers and other integral kinds. These include

  • a & b: bitwise AND
  • a | b: bitwise OR
  • a ^ b: bitwise XOR
  • ~a: bit inversion
  • a << b: left bit shift
  • a >> b: right bit shift (arithmetic shift)

4 C Unions

C unions are a relative of structs. You may wish to examine a slide towards the end of the floating point slide deck to get acquainted with the idea. Recall that structs allow multiple fields to be specified and each field gets its own memory address though all fields are group together tightly.

Unions allow several fields to be specified but place all fields at the same memory location so they overlap. This allows one to use integer operations like shifts on a memory location even if it is meant to hold a float which cannot normally be shifted.

The file union.c demonstrates this and is the discussed in Problem 2.

5 gdb The GNU Debugger

You should use a debugger to study the code in Problem 2 and gdb is the quintessential debugger associated with our compiler gcc. It is installed by default on all lab machines and is an easy install on must Linux machines.

For a quick overview of GDB, here are some resources

6 What to Understand

Ensure that you understand

  • Some details of float layout such as where the sign, exponent, and mantissa are stored
  • The idea of a union to overlay two types of variable in the same memory
  • Use of the debugger to pause program execution, print values, and determine what is happening in a running program

7 Questions

Analyze the files in the provided codepack and answer the questions given in QUESTIONS.txt.

                           _________________

                            HW 05 QUESTIONS
                           _________________


Write your answers to the questions below directly in this text file to
prepare for the associated quiz. Credit for the HW is earned by
completing the online quiz.


PROBLEM 1: C Bit Operations in Collatz
======================================

  Examine the program collatz.c which performs a similar computation to
  a HW01 code except that this version uses bitwise operations in the
  function collatz_bitwise().  Examine the locations labeled with
  comments and shown below and describe the equivalent "normal"
  arithmetic that is happening at each postion.


A
~

  ,----
  |   int neg_mask = 0x1 << 31;     // A
  |   if(n & neg_mask){             // A
  |     return -1;
  |   }
  `----


B
~

  ,----
  |     if(n & 0x1){                // B
  |       ...
  |     }
  |     else{
  |       ...
  |     }
  `----


C
~

  ,----
  |       n = ((n << 2) - n) + 1;   // C
  `----


D
~

  ,----
  |       n = n >> 1;               // D
  `----


PROBLEM 2: C Union and Float Bits
=================================

A
~

  Compile and run union.c to see what floating point value is printed by
  the lines.
  ,----
  |   flint.in = 0xC378C000;        // assign an int value
  |   printf("%.4f\n",flint.fl);    // print as a float value
  `----
  Show the float value and explain why it has a well-defined value
  despite no assignment of `flint.fl = ...;' appearing.


B
~

  The subsequent loop
  ,----
  |   flint.in = 0xC378C000;        // assign an int value
  |   ...
  |   for(int i=0; i<4; i++){       // print chars individually
  |     unsigned char c = flint.ch[i];
  |     printf("%d: %02x '%c'\n", i,c,c);
  |   }
  `----
  prints values of the bytes associated with `flint' as chars and
  hexadecimal numbers.  Show its output and explain why the hex digits
  appear in a different order from the constant flint is set to
  initially.


C
~

  The lines
  ,----
  | int mask = ~(0x80000000);
  | flint.in = flint.in & mask;
  | printf("%.4f\n",flint.fl);
  `----
  modify flint again. Show the resulting floating point output and
  describe why it has the shown value.


PROBLEM 3: GDB
==============

A debug_scramble.c
~~~~~~~~~~~~~~~~~~

  The file debug_scramble.c has a short problem which requires the
  correct number to be given as a command line argument. An array is
  filled with values and then scrambled. The command line must
  correspond to the "positive" response. Due to the array scrambling it
  is not apparent from the source code which array location contains the
  positive response.

  Use the debugger to determine the location the positive response.  For
  each of the steps below, write the commands to issue to do the items
  listed.
  1. Compile debug_scramble.c with debug symbols turned on
  2. Start gdb with the resulting program
  3. Set the arguments of the program to just 0
  4. Set a breakpoint at a line in debug_scramble.c after the scramble
     loop
  5. Run the program
  6. Print out the array after stopping at the breakpoint
  7. Locate the positive response
  8. Change the program arguments so that it is the correct index
  9. Re-run the program and continue to the end


B debug_long.c
~~~~~~~~~~~~~~

  The file debug_long.c has another short debugging problem.  It
  requires an input string which is interpreted similarly to a
  demonstration code at the top of code.  The correct input will elicit
  the affirmative response.

  To determine the correct input take the following approach.
  1. Break after setting the variable `lng' to its large, mysterious
     value
  2. Print the bytes of long NOT as a number but interpreted as an array
     of characters (string). This can be done in `gdb' by coercing the
     types as in:
     ,----
     | gdb> print (char []) varname
     `----
  3. This should shed light on the correct input.

8 Again, What to Understand

Ensure that you understand

  • Some details of float layout such as where the sign, exponent, and mantissa are stored
  • The idea of a union to overlay two types of variable in the same memory
  • Use of the debugger to pause program execution, print values, and determine what is happening in a running program

Author: Chris Kauffman (kauffman@umn.edu)
Date: 2023-02-17 Fri 14:30