unsigned long str$position(const struct dsc$descriptor_s *first_source_string,
                           const struct dsc$descriptor_s *second_source_string,
                           const long *start_position) {
  char *s1_ptr;
  unsigned short s1_length;
  char *s2_ptr;
  unsigned short s2_length;
  long loop;
  long start_pos;
  str$analyze_sdesc(first_source_string, &s1_length, &s1_ptr);
  str$analyze_sdesc(second_source_string, &s2_length, &s2_ptr);
  start_pos = *start_position;
  if (start_pos < 0)
    start_pos = 0;
  if (start_pos > s1_length)
    start_pos = s1_length;
  if (s2_length == 0) {
    return s1_length + 1;
  }
  for (loop = start_pos - 1; loop <= s1_length - s2_length; loop++) {
    if (memcmp(s1_ptr + loop, s2_ptr, s2_length) == 0) {
      return loop + 1;
    }
  }
  return 0;
}


x86 assembly (clang, -O0):
<str$position>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
mov    -0x10(%rbp),%rdi
lea    -0x2a(%rbp),%rsi
lea    -0x28(%rbp),%rdx
mov    $0x0,%al
call   1030 <str$analyze_sdesc@plt>
mov    -0x18(%rbp),%rdi
lea    -0x3a(%rbp),%rsi
lea    -0x38(%rbp),%rdx
mov    $0x0,%al
call   1030 <str$analyze_sdesc@plt>
mov    -0x20(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x50(%rbp)
cmpq   $0x0,-0x50(%rbp)
jge    1178 <str$position+0x58>
movq   $0x0,-0x50(%rbp)
mov    -0x50(%rbp),%rax
movzwl -0x2a(%rbp),%ecx
cmp    %rcx,%rax
jle    1191 <str$position+0x71>
movzwl -0x2a(%rbp),%eax
mov    %rax,-0x50(%rbp)
movzwl -0x3a(%rbp),%eax
cmp    $0x0,%eax
jne    11b0 <str$position+0x90>
movzwl -0x2a(%rbp),%eax
add    $0x1,%eax
cltq
mov    %rax,-0x8(%rbp)
jmp    1225 <str$position+0x105>
mov    -0x50(%rbp),%rax
sub    $0x1,%rax
mov    %rax,-0x48(%rbp)
mov    -0x48(%rbp),%rax
movzwl -0x2a(%rbp),%ecx
movzwl -0x3a(%rbp),%edx
sub    %edx,%ecx
movslq %ecx,%rcx
cmp    %rcx,%rax
jg     121d <str$position+0xfd>
mov    -0x28(%rbp),%rdi
add    -0x48(%rbp),%rdi
mov    -0x38(%rbp),%rsi
movzwl -0x3a(%rbp),%eax
mov    %eax,%edx
call   1040 <memcmp@plt>
cmp    $0x0,%eax
jne    1207 <str$position+0xe7>
mov    -0x48(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
jmp    1225 <str$position+0x105>
jmp    120c <str$position+0xec>
mov    -0x48(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x48(%rbp)
jmp    11bc <str$position+0x9c>
movq   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<str$position>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x20,%rsp
mov    %rdx,%r14
mov    %rsi,%r15
xor    %ebx,%ebx
lea    0xe(%rsp),%rsi
lea    0x18(%rsp),%rdx
xor    %eax,%eax
call   1030 <str$analyze_sdesc@plt>
lea    0xc(%rsp),%rsi
lea    0x10(%rsp),%rdx
mov    %r15,%rdi
xor    %eax,%eax
call   1030 <str$analyze_sdesc@plt>
mov    (%r14),%rax
test   %rax,%rax
cmovns %rax,%rbx
movzwl 0xe(%rsp),%r12d
movzwl 0xc(%rsp),%r14d
test   %r14,%r14
je     11c7 <str$position+0xa7>
cmp    %r12,%rbx
cmova  %r12,%rbx
lea    -0x1(%rbx),%rax
sub    %r14,%r12
cmp    %r12,%rax
jg     11c3 <str$position+0xa3>
mov    0x18(%rsp),%r13
mov    0x10(%rsp),%r15
add    $0xffffffffffffffff,%r13
cs nopw 0x0(%rax,%rax,1)
lea    (%rbx,%r13,1),%rdi
mov    %r15,%rsi
mov    %r14,%rdx
call   1040 <bcmp@plt>
test   %eax,%eax
je     11ce <str$position+0xae>
lea    0x1(%rbx),%rax
add    $0xffffffffffffffff,%rbx
cmp    %r12,%rbx
mov    %rax,%rbx
jl     11a0 <str$position+0x80>
xor    %ebx,%ebx
jmp    11ce <str$position+0xae>
add    $0x1,%r12
mov    %r12,%rbx
mov    %rbx,%rax
add    $0x20,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
%"struct.dsc$descriptor_s" = type opaque
define i64 @"str$position"(%"struct.dsc$descriptor_s"* %0, %"struct.dsc$descriptor_s"* %1, i64* %2) {
%4 = alloca i64
%5 = alloca %"struct.dsc$descriptor_s"*
%6 = alloca %"struct.dsc$descriptor_s"*
%7 = alloca i64*
%8 = alloca i8*
%9 = alloca i16
%10 = alloca i8*
%11 = alloca i16
%12 = alloca i64
%13 = alloca i64
store %"struct.dsc$descriptor_s"* %0, %"struct.dsc$descriptor_s"** %5
store %"struct.dsc$descriptor_s"* %1, %"struct.dsc$descriptor_s"** %6
store i64* %2, i64** %7
%14 = load %"struct.dsc$descriptor_s"*, %"struct.dsc$descriptor_s"** %5
%15 = call i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...) bitcast (i32 (...)* @"str$analyze_sdesc" to i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...)*)(%"struct.dsc$descriptor_s"* %14, i16* %9, i8** %8)
%16 = load %"struct.dsc$descriptor_s"*, %"struct.dsc$descriptor_s"** %6
%17 = call i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...) bitcast (i32 (...)* @"str$analyze_sdesc" to i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...)*)(%"struct.dsc$descriptor_s"* %16, i16* %11, i8** %10)
%18 = load i64*, i64** %7
%19 = load i64, i64* %18
store i64 %19, i64* %13
%20 = load i64, i64* %13
%21 = icmp slt i64 %20, 0
br i1 %21, label %22, label %23
22: ; preds = %3
store i64 0, i64* %13
br label %23
23: ; preds = %22, %3
%24 = load i64, i64* %13
%25 = load i16, i16* %9
%26 = zext i16 %25 to i64
%27 = icmp sgt i64 %24, %26
br i1 %27, label %28, label %31
28: ; preds = %23
%29 = load i16, i16* %9
%30 = zext i16 %29 to i64
store i64 %30, i64* %13
br label %31
31: ; preds = %28, %23
%32 = load i16, i16* %11
%33 = zext i16 %32 to i32
%34 = icmp eq i32 %33, 0
br i1 %34, label %35, label %40
35: ; preds = %31
%36 = load i16, i16* %9
%37 = zext i16 %36 to i32
%38 = add nsw i32 %37, 1
%39 = sext i32 %38 to i64
store i64 %39, i64* %4
br label %69
40: ; preds = %31
%41 = load i64, i64* %13
%42 = sub nsw i64 %41, 1
store i64 %42, i64* %12
br label %43
43: ; preds = %65, %40
%44 = load i64, i64* %12
%45 = load i16, i16* %9
%46 = zext i16 %45 to i32
%47 = load i16, i16* %11
%48 = zext i16 %47 to i32
%49 = sub nsw i32 %46, %48
%50 = sext i32 %49 to i64
%51 = icmp sle i64 %44, %50
br i1 %51, label %52, label %68
52: ; preds = %43
%53 = load i8*, i8** %8
%54 = load i64, i64* %12
%55 = getelementptr inbounds i8, i8* %53, i64 %54
%56 = load i8*, i8** %10
%57 = load i16, i16* %11
%58 = zext i16 %57 to i64
%59 = call i32 @memcmp(i8* %55, i8* %56, i64 %58)
%60 = icmp eq i32 %59, 0
br i1 %60, label %61, label %64
61: ; preds = %52
%62 = load i64, i64* %12
%63 = add nsw i64 %62, 1
store i64 %63, i64* %4
br label %69
64: ; preds = %52
br label %65
65: ; preds = %64
%66 = load i64, i64* %12
%67 = add nsw i64 %66, 1
store i64 %67, i64* %12
br label %43
68: ; preds = %43
store i64 0, i64* %4
br label %69
69: ; preds = %68, %61, %35
%70 = load i64, i64* %4
ret i64 %70
}

LLVM IR (-O2):
%"struct.dsc$descriptor_s" = type opaque
define i64 @"str$position"(%"struct.dsc$descriptor_s"* %0, %"struct.dsc$descriptor_s"* %1, i64* nocapture %2) {
%4 = alloca i8*
%5 = alloca i16
%6 = alloca i8*
%7 = alloca i16
%8 = bitcast i8** %4 to i8*
%9 = bitcast i16* %5 to i8*
%10 = bitcast i8** %6 to i8*
%11 = bitcast i16* %7 to i8*
%12 = call i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...) bitcast (i32 (...)* @"str$analyze_sdesc" to i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...)*)(%"struct.dsc$descriptor_s"* %0, i16* %5, i8** %4)
%13 = call i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...) bitcast (i32 (...)* @"str$analyze_sdesc" to i32 (%"struct.dsc$descriptor_s"*, i16*, i8**, ...)*)(%"struct.dsc$descriptor_s"* %1, i16* %7, i8** %6)
%14 = load i64, i64* %2
%15 = icmp sgt i64 %14, 0
%16 = select i1 %15, i64 %14, i64 0
%17 = load i16, i16* %5
%18 = zext i16 %17 to i64
%19 = load i16, i16* %7
%20 = icmp eq i16 %19, 0
br i1 %20, label %21, label %23
21: ; preds = %3
%22 = add nuw nsw i64 %18, 1
br label %41
23: ; preds = %3
%24 = icmp ugt i64 %16, %18
%25 = select i1 %24, i64 %18, i64 %16
%26 = add nsw i64 %25, -1
%27 = zext i16 %19 to i64
%28 = sub nsw i64 %18, %27
%29 = icmp sgt i64 %26, %28
br i1 %29, label %41, label %30
30: ; preds = %23
%31 = load i8*, i8** %4
%32 = load i8*, i8** %6
br label %33
33: ; preds = %30, %39
%34 = phi i64 [ %26, %30 ], [ %38, %39 ]
%35 = getelementptr inbounds i8, i8* %31, i64 %34
%36 = call i32 @bcmp(i8* %35, i8* %32, i64 %27)
%37 = icmp eq i32 %36, 0
%38 = add nsw i64 %34, 1
br i1 %37, label %41, label %39
39: ; preds = %33
%40 = icmp slt i64 %34, %28
br i1 %40, label %33, label %41
41: ; preds = %39, %33, %23, %21
%42 = phi i64 [ %22, %21 ], [ 0, %23 ], [ 0, %39 ], [ %38, %33 ]
ret i64 %42
}