It seems some of my problems are related to the fact that gcc ignores my pretty 'unsigned' letters in front of the variables. At least I have overflows at less than 32 bits, and I can put negative values into them as well.
That's an easy problem to fix. The thing is, integer constants in C (or C++) are assumed by the compiler to be of type int (ie signed). So when you say
unsigned long x = 0xffffffaa;
the compiler takes that as meaning
unsigned long x = (int) 0xffffffaa;
So the solution is to tell the compiler that your integer constant is an unsigned long instead of an int. You do that like this:
unsigned long x = 0xffffffaaUL;
The UL at the end tells the compiler it's an Unsigned Long instead of an int. You can also use U or L on their own (eg 0L or 45U), but most of the time it doesn't make a difference - only when you're dealing with large unsigned constants like 0xffffffaa.