int string_compare_max(const char *string1, const char *string2,
                       unsigned int count) {
  register int eax;
  int esi, edi, ecx;
  asm volatile("cld\n"
               "1:  decl %3\n"
               "js 2f\n"
               "lodsb\n"
               "scasb\n"
               "jne 3f\n"
               "testb %%al, %%al\n"
               "jne 1b\n"
               "2:  xorl %%eax, %%eax\n"
               "jmp 4f\n"
               "3:  sbbl %%eax, %%eax\n"
               "orb $1, %%al\n"
               "4:"
               : "=a"(eax), "=&S"(esi), "=&D"(edi), "=&c"(ecx)
               : "1"(string1), "2"(string2), "3"(count));
  return eax;
}


x86 assembly (clang, -O0):
<string_compare_max>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    -0x8(%rbp),%rsi
mov    -0x10(%rbp),%rdi
mov    -0x14(%rbp),%ecx
cld
dec    %ecx
js     1133 <string_compare_max+0x33>
lods   %ds:(%rsi),%al
scas   %es:(%rdi),%al
jne    113a <string_compare_max+0x3a>
test   %al,%al
jne    111b <string_compare_max+0x1b>
xor    %eax,%eax
jmp    113e <string_compare_max+0x3e>
sbb    %eax,%eax
or     $0x1,%al
mov    %eax,-0x18(%rbp)
mov    %esi,%eax
mov    %eax,-0x1c(%rbp)
mov    %edi,%eax
mov    %eax,-0x20(%rbp)
mov    %ecx,-0x24(%rbp)
mov    -0x18(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<string_compare_max>:
mov    %edx,%ecx
mov    %rdi,%rax
mov    %rsi,%rdi
mov    %rax,%rsi
cld
dec    %ecx
js     1118 <string_compare_max+0x18>
lods   %ds:(%rsi),%al
scas   %es:(%rdi),%al
jne    111c <string_compare_max+0x1c>
test   %al,%al
jne    110c <string_compare_max+0xc>
xor    %eax,%eax
jmp    1120 <string_compare_max+0x20>
sbb    %eax,%eax
or     $0x1,%al
ret

LLVM IR (-O0):
define i32 @string_compare_max(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%11 = load i8*, i8** %4
%12 = load i8*, i8** %5
%13 = load i32, i32* %6
%14 = call { i32, i8*, i8*, i32 } asm sideeffect "cld\0A1: decl $3\0Ajs 2f\0Alodsb\0Ascasb\0Ajne 3f\0Atestb %al, %al\0Ajne 1b\0A2: xorl %eax, %eax\0Ajmp 4f\0A3: sbbl %eax, %eax\0Aorb $$1, %al\0A4:", "={ax},=&{si},=&{di},=&{cx},1,2,3,~{dirflag},~{fpsr},~{flags}"(i8* %11, i8* %12, i32 %13)
%15 = extractvalue { i32, i8*, i8*, i32 } %14, 0
%16 = extractvalue { i32, i8*, i8*, i32 } %14, 1
%17 = extractvalue { i32, i8*, i8*, i32 } %14, 2
%18 = extractvalue { i32, i8*, i8*, i32 } %14, 3
store i32 %15, i32* %7
%19 = ptrtoint i8* %16 to i64
%20 = trunc i64 %19 to i32
store i32 %20, i32* %8
%21 = ptrtoint i8* %17 to i64
%22 = trunc i64 %21 to i32
store i32 %22, i32* %9
store i32 %18, i32* %10
%23 = load i32, i32* %7
ret i32 %23
}

LLVM IR (-O2):
define i32 @string_compare_max(i8* %0, i8* %1, i32 %2) {
%4 = tail call { i32, i8*, i8*, i32 } asm sideeffect "cld\0A1: decl $3\0Ajs 2f\0Alodsb\0Ascasb\0Ajne 3f\0Atestb %al, %al\0Ajne 1b\0A2: xorl %eax, %eax\0Ajmp 4f\0A3: sbbl %eax, %eax\0Aorb $$1, %al\0A4:", "={ax},=&{si},=&{di},=&{cx},1,2,3,~{dirflag},~{fpsr},~{flags}"(i8* %0, i8* %1, i32 %2)
%5 = extractvalue { i32, i8*, i8*, i32 } %4, 0
ret i32 %5
}