Тема ?C?IMUL не раскрыта. Думаю, там 3 операции умножения с
возвратом 2-байтового результат (4 умножения не нужно, т.к.
умножения 2-х старших байт перевалит за 2-байтовый результат). К слову - у тебя там результаты каждого произведения, и их суммы - 2 байтовые. Все по правилам.
Можно попробовать поиграться так - поставить явно преобразование типа:
s+=x1*(unsigned char)c1 + x2*(unsigned char)20;
Возможно, что компилятор тупой, и тупо промотит до int. Помню, что подобные трюки иногда помогали.