unsigned char Multiply(unsigned char num, unsigned char factor) {
  unsigned char mask = 1;
  unsigned char result = 0;
  while (mask != 0) {
    if (mask & factor) {
      result ^= num;
    }
    mask <<= 1;
    num = (num << 1) ^ (num & 0x80 ? 0x1b : 0);
  }
  return result;
}


x86 assembly (clang, -O0):
<Multiply>:
push   %rbp
mov    %rsp,%rbp
mov    %sil,%al
mov    %dil,%cl
mov    %cl,-0x1(%rbp)
mov    %al,-0x2(%rbp)
movb   $0x1,-0x3(%rbp)
movb   $0x0,-0x4(%rbp)
movzbl -0x3(%rbp),%eax
cmp    $0x0,%eax
je     1177 <Multiply+0x77>
movzbl -0x3(%rbp),%eax
movzbl -0x2(%rbp),%ecx
and    %ecx,%eax
cmp    $0x0,%eax
je     1145 <Multiply+0x45>
movzbl -0x1(%rbp),%ecx
movzbl -0x4(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x4(%rbp)
movzbl -0x3(%rbp),%eax
shl    $0x1,%eax
mov    %al,-0x3(%rbp)
movzbl -0x1(%rbp),%eax
shl    $0x1,%eax
movzbl -0x1(%rbp),%esi
and    $0x80,%esi
xor    %ecx,%ecx
mov    $0x1b,%edx
cmp    $0x0,%esi
cmovne %edx,%ecx
xor    %ecx,%eax
mov    %al,-0x1(%rbp)
jmp    1118 <Multiply+0x18>
movzbl -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<Multiply>:
push   %rbx
lea    (%rdi,%rdi,1),%r9d
mov    %edi,%r8d
sar    $0x7,%r8b
and    $0x1b,%r8b
xor    %r9b,%r8b
lea    (%r8,%r8,1),%r10d
sar    $0x7,%r9b
and    $0x1b,%r9b
xor    %r10b,%r9b
lea    (%r9,%r9,1),%r11d
sar    $0x7,%r10b
and    $0x1b,%r10b
xor    %r11b,%r10b
lea    (%r10,%r10,1),%ecx
sar    $0x7,%r11b
and    $0x1b,%r11b
xor    %cl,%r11b
lea    (%r11,%r11,1),%edx
sar    $0x7,%cl
and    $0x1b,%cl
xor    %dl,%cl
lea    (%rcx,%rcx,1),%eax
sar    $0x7,%dl
and    $0x1b,%dl
xor    %al,%dl
lea    (%rdx,%rdx,1),%ebx
sar    $0x7,%al
and    $0x1b,%al
movd   %esi,%xmm0
pshufd $0x0,%xmm0,%xmm1
movdqa 0xe90(%rip),%xmm0
pand   %xmm1,%xmm0
pand   0xe94(%rip),%xmm1
xor    %bl,%al
pxor   %xmm2,%xmm2
pcmpeqd %xmm2,%xmm1
pcmpeqd %xmm2,%xmm0
packssdw %xmm1,%xmm0
movzbl %al,%eax
movzbl %dl,%edx
shl    $0x8,%edx
or     %eax,%edx
movd   %edx,%xmm1
movzbl %cl,%eax
movzbl %r11b,%ecx
shl    $0x8,%ecx
or     %eax,%ecx
pinsrw $0x1,%ecx,%xmm1
packsswb %xmm0,%xmm0
movzbl %r10b,%eax
movzbl %r9b,%ecx
shl    $0x8,%ecx
or     %eax,%ecx
pinsrw $0x2,%ecx,%xmm1
movzbl %r8b,%eax
shl    $0x8,%edi
or     %eax,%edi
pinsrw $0x3,%edi,%xmm1
pandn  %xmm1,%xmm0
pshufd $0x55,%xmm0,%xmm1
pxor   %xmm0,%xmm1
movdqa %xmm1,%xmm0
psrld  $0x10,%xmm0
pxor   %xmm1,%xmm0
movdqa %xmm0,%xmm1
psrlw  $0x8,%xmm1
pxor   %xmm0,%xmm1
movd   %xmm1,%eax
pop    %rbx
ret

LLVM IR (-O0):
define zeroext i8 @Multiply(i8 zeroext %0, i8 zeroext %1) {
%3 = alloca i8
%4 = alloca i8
%5 = alloca i8
%6 = alloca i8
store i8 %0, i8* %3
store i8 %1, i8* %4
store i8 1, i8* %5
store i8 0, i8* %6
br label %7
7: ; preds = %25, %2
%8 = load i8, i8* %5
%9 = zext i8 %8 to i32
%10 = icmp ne i32 %9, 0
br i1 %10, label %11, label %41
11: ; preds = %7
%12 = load i8, i8* %5
%13 = zext i8 %12 to i32
%14 = load i8, i8* %4
%15 = zext i8 %14 to i32
%16 = and i32 %13, %15
%17 = icmp ne i32 %16, 0
br i1 %17, label %18, label %25
18: ; preds = %11
%19 = load i8, i8* %3
%20 = zext i8 %19 to i32
%21 = load i8, i8* %6
%22 = zext i8 %21 to i32
%23 = xor i32 %22, %20
%24 = trunc i32 %23 to i8
store i8 %24, i8* %6
br label %25
25: ; preds = %18, %11
%26 = load i8, i8* %5
%27 = zext i8 %26 to i32
%28 = shl i32 %27, 1
%29 = trunc i32 %28 to i8
store i8 %29, i8* %5
%30 = load i8, i8* %3
%31 = zext i8 %30 to i32
%32 = shl i32 %31, 1
%33 = load i8, i8* %3
%34 = zext i8 %33 to i32
%35 = and i32 %34, 128
%36 = icmp ne i32 %35, 0
%37 = zext i1 %36 to i64
%38 = select i1 %36, i32 27, i32 0
%39 = xor i32 %32, %38
%40 = trunc i32 %39 to i8
store i8 %40, i8* %3
br label %7
41: ; preds = %7
%42 = load i8, i8* %6
ret i8 %42
}

LLVM IR (-O2):
define zeroext i8 @Multiply(i8 zeroext %0, i8 zeroext %1) {
%3 = zext i8 %1 to i32
%4 = shl i8 %0, 1
%5 = icmp slt i8 %0, 0
%6 = select i1 %5, i8 27, i8 0
%7 = xor i8 %6, %4
%8 = shl i8 %7, 1
%9 = icmp slt i8 %7, 0
%10 = select i1 %9, i8 27, i8 0
%11 = xor i8 %10, %8
%12 = shl i8 %11, 1
%13 = icmp slt i8 %11, 0
%14 = select i1 %13, i8 27, i8 0
%15 = xor i8 %14, %12
%16 = shl i8 %15, 1
%17 = icmp slt i8 %15, 0
%18 = select i1 %17, i8 27, i8 0
%19 = xor i8 %18, %16
%20 = shl i8 %19, 1
%21 = icmp slt i8 %19, 0
%22 = select i1 %21, i8 27, i8 0
%23 = xor i8 %22, %20
%24 = shl i8 %23, 1
%25 = icmp slt i8 %23, 0
%26 = select i1 %25, i8 27, i8 0
%27 = xor i8 %26, %24
%28 = shl i8 %27, 1
%29 = icmp slt i8 %27, 0
%30 = select i1 %29, i8 27, i8 0
%31 = xor i8 %30, %28
%32 = insertelement <8 x i32> poison, i32 %3, i64 0
%33 = shufflevector <8 x i32> %32, <8 x i32> poison, <8 x i32> zeroinitializer
%34 = and <8 x i32> %33, <i32 128, i32 64, i32 32, i32 16, i32 8, i32 4, i32 2, i32 1>
%35 = icmp eq <8 x i32> %34, zeroinitializer
%36 = insertelement <8 x i8> poison, i8 %0, i64 7
%37 = insertelement <8 x i8> %36, i8 %31, i64 0
%38 = insertelement <8 x i8> %37, i8 %27, i64 1
%39 = insertelement <8 x i8> %38, i8 %23, i64 2
%40 = insertelement <8 x i8> %39, i8 %19, i64 3
%41 = insertelement <8 x i8> %40, i8 %15, i64 4
%42 = insertelement <8 x i8> %41, i8 %11, i64 5
%43 = insertelement <8 x i8> %42, i8 %7, i64 6
%44 = select <8 x i1> %35, <8 x i8> zeroinitializer, <8 x i8> %43
%45 = call i8 @llvm.vector.reduce.xor.v8i8(<8 x i8> %44)
ret i8 %45
}