A literal like 0x10001 will be of type int (if it can fit inside an int, which is true in this case). int is a signed type.
Since the variable u is a small integer type, it gets integer promoted to int whenever used in an expression.
0xaabb * 0x10001 would supposedly give the result 0xAABBAABB. However, that result is too large to fit inside an int on a 32 bit two's complement system, where the largest number for an int is 0x7FFFFFFF. So you get an overflow on a signed integer and therefore invoke undefined behavior - anything can happen.
Never use signed integers when doing any form of binary arithmetic!
Furthermore, the final cast to (unsigned short) is futile, because printf argument promotes the passed value to int anyhow. Which is strictly speaking incorrect too, because %x means that printf expects an unsigned int.
To avoid all trouble with the unpredictable and limited default integer types in C, use stdint.h instead. Also, using unsigned int literals solves a lot of implicit type promotion bugs.
Example:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main( void ){
  uint16_t u = 0xaabb;
  uint16_t v = 0xaabb;
  printf ("%08" PRIx16 " %08" PRIx16 "\n", u, (uint16_t)(u*0x10001u/0x100u));
  printf ("%08" PRIx16 " %08" PRIx16 "\n", v, (uint16_t)(v*0x10001u/0x100u));
  return 0;
}
(This code will have argument promotion too, but by using the PRIx16 format specifier, you tell printf that it is now the compiler's business to make the code work, regardless of what type promotions that might be present in the function call.)