I expected b to be promoted to a 16 bit type prior to the left shift, but I didn't expect the promotion to be from an unsigned type (byte) to a signed type (int). It seems to me that it should have been promoted to an unsigned int.
byte b = 0x80; unsigned long ul = 256; unsigned long r = b * ul; Serial.println(r, HEX);
The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.
Or is it? Would both operands be promoted to unsigned long? But they can't be or the results would be 0x8000.