Gettysburg College

CS 221
Computer Organization and Assembly Language Programming

Fall 2025

Assignment 2

Due: Thu, Sep 11, by 11:59pm

Readings

Description

This assignment will focus on C++ and bitwise operations. There are two tasks:

Testing the Converter

Copy the following functions and use assertEquals for testing the code. This is similar to testing in JUnit.

string to_string( const string& str )
{
	return str;
}

template<typename E1, typename E2>
void assertEquals( E1 a, E2 b )
{
	string strA = to_string( a );
	string strB = to_string( b );

	if ( strA != strB ) {
		cout << "failed: " << a << " != " << b << endl;
	}
}

Note that you will need to put at the very top:

#include <iostream>
#include <string>
using namespace std;

Converter

Create C++ project called Converter with source file Converter.cpp and re-write all methods from Assignment 1 in C++.

Note the following:

Here are the C++ versions of the given Java code samples:

char getSymbol(long digit)
{
    if (digit >= 0 && digit <= 9) {
        return (char)('0' + digit);
    }
    else {
        return (char)('A' + (digit - 10));
    }
}
long getValue(char symbol)
{
    if (symbol >= '0' && symbol <= '9') {
        return symbol - '0';
    }
    else {
        return (symbol - 'A') + 10;
    }
}
                               // no new, no =, just list key-value pairs
map<?, ?> theNameOfMap = { {key1, value1}, {key2, value2}, ... };

theNameOfMap[symbol] = value;   // CS111:  map[symbol] = value;

value = theNameOfMap[symbol];   // CS111:  value = map[symbol];

Bitset

Create C++ project called Bitset with source file Bitset.cpp.

Write class Bitset and test it in a main() function at the end of the file.

The class will have one data member of type unsigned short. This is 2 bytes and the bits are indexed from right-to-left (unlike strings or arrays):

15            2 1 0
 x x x x .... x x x

Note: If you use variables for intermediate quantities, make them of type unsigned short.

Note: Avoid loops, arithmetic operators, and if where possible; comparison operators are fine.

Here is the list of required methods:

testing the Bitset

At the top add:
#include <cassert>
Before main add the following function:
unsigned short id( unsigned short value )
{
    return value;
}
Then in main can write:
assert( bitset.getValue() == id(0xABCD) );  // when bitset value needed
  
assert( bitset.count() == 5 )               // when bitset value not needed
assert( bitset.any() );
the 0 constant

At the top of the data members section put the following:
const unsigned short ZERO = 0;
Unless indicated explicitly, the only numeric value that can be used is ZERO or its bitwise variation. You may use 1 to initialize a mask.
explicit constructor(unsigned short theBits)

Initializes the bitset to the given bits. Note the keyword explicit before constructor name.
u.s. getValue()

Returns the bitset value (for testing).
void print()

The method is given for now. It will be modified later:

// prints the value of the bitset as hex number    
// note: oct would print the octal version
//       dec would print the decimal version
//       there is no specifier for binary
void print()
{
    cout << hex << the-data-member << endl;

    cout << dec;   // should always be the last line in this method to reset to decimal
}
bool none()

[no loops] Returns true if all bits are 0.
bool any()

[no loops] Returns true if at least one bit is set to 1.
bool all()

[no loops] Returns true if all bits have value 1.
void flip()

[no loops] Inverts the bits in the set (0s to 1s and 1s to 0s). Do not use ~data.
bool get(int index)

[no loops] Returns true if the bit at the given index is set to 1.

Consider bitshift operation of a suitable mask.

void set()

[no loops] Sets all bits to 1. Should be simple.
void set(int index)

[no loops] Sets the bit at the given index to 1.
void clear()

[no loops] Sets all bits to 0. Do not use numeric constants.
void clear(int index)

[no loops] Sets the bit at the given index to 0.
void swap()

[no loops] Swaps the values of the two halves (here the two bytes) of the data member. No restriction on using ZERO.
void swapHi()

[no loops] Swaps the two halves in the high byte of the data member, i.e. the byte that corresponds to the higher powers of 2. No restriction on using ZERO.
void swapLo()

[no loops] Swaps the two halves in the low byte of the data member, i.e. the byte that corresponds to the lower powers of 2. No restriction on using ZERO.
bool isPow2()

[no loops] Returns true if the value stored in the bitset is a power of 2.

If you want to see a hint, highlight the space below:

We discussed properties of powers of 2 and numbers closely related to powers of 2.
void clearLast1()

[no loops] Sets to 0 only the last 1 in the bitset, i.e. the 1 bit that corresponds to the lowest power of 2. The rest of the bits are unchanged.

If you want to see a hint, highlight the space below:

This has something in common with isPow2. Start by applying the isPow2 steps to numbers that are not powers of 2 and see if you notice a pattern.
int count()

[loop needed] Returns the number of bits that are set to 1.

Use a loop with a mask that is shifted by one position on each cycle.

void printBinary()

[loop needed] Prints the binary representation of the data member

// assuming the bitset has value 25, the output would be
  
bits.printBinary();          0b0000000000011001
void print()

Prints the bits in decimal, hexadecimal, octal, and binary in this format [implicit loop for binary]:

// assuming the bitset has value 25, the output would be
  
bits.print();          [25, 0x19, 031, 0b0000000000011001]


What to turn in

Upload Converter.cpp and Bitset.cpp to the Moodle dropbox.