void kernel_assert_print(const char *str, unsigned int len,
                         unsigned int start) {
  char *fb = (char *)(0xB8000 + (start << 1));
  register int i;
  for (i = 0; i < len; ++i) {
    fb[i << 1] = str[i];
    fb[(i << 1) + 1] = 0x07;
  }
}


x86 assembly (clang, -O0):
<kernel_assert_print>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    -0x10(%rbp),%eax
shl    $0x1,%eax
add    $0xb8000,%eax
mov    %eax,%eax
mov    %rax,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0xc(%rbp),%eax
jae    116f <kernel_assert_print+0x6f>
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movb   $0x7,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1126 <kernel_assert_print+0x26>
pop    %rbp
ret

x86 assembly (clang, -O2):
<kernel_assert_print>:
push   %r14
push   %rbx
test   %esi,%esi
je     11c2 <kernel_assert_print+0xc2>
lea    (%rdx,%rdx,1),%r14d
add    $0xb8000,%r14d
mov    %esi,%r9d
cmp    $0x10,%esi
jae    11c6 <kernel_assert_print+0xc6>
xor    %eax,%eax
mov    %rax,%rcx
not    %rcx
test   $0x1,%r9b
je     1152 <kernel_assert_print+0x52>
mov    (%rdi,%rax,1),%bl
mov    %rax,%rsi
shl    $0x21,%rsi
sar    $0x20,%rsi
mov    %bl,(%r14,%rsi,1)
lea    (%rax,%rax,1),%esi
movslq %esi,%rsi
movb   $0x7,0x1(%r14,%rsi,1)
or     $0x1,%rax
add    %r9,%rcx
je     11c2 <kernel_assert_print+0xc2>
lea    (%rax,%rax,1),%ecx
add    $0x1,%ecx
mov    %rax,%rdx
shl    $0x21,%rdx
movabs $0x200000000,%r8
movabs $0x400000000,%r10
nopl   0x0(%rax,%rax,1)
movzbl (%rdi,%rax,1),%ebx
mov    %rdx,%rsi
sar    $0x20,%rsi
mov    %bl,(%r14,%rsi,1)
movslq %ecx,%rcx
movb   $0x7,(%r14,%rcx,1)
movzbl 0x1(%rdi,%rax,1),%ebx
lea    (%rdx,%r8,1),%rsi
sar    $0x20,%rsi
mov    %bl,(%r14,%rsi,1)
lea    0x2(%rcx),%esi
movslq %esi,%rsi
movb   $0x7,(%r14,%rsi,1)
add    $0x2,%rax
add    $0x4,%ecx
add    %r10,%rdx
cmp    %rax,%r9
jne    1180 <kernel_assert_print+0x80>
pop    %rbx
pop    %r14
ret
lea    -0x1(%r9),%rsi
mov    %esi,%ecx
add    %esi,%ecx
setb   %r10b
mov    %rsi,%r11
add    %rsi,%r11
setb   %r8b
xor    %eax,%eax
test   %ecx,%ecx
js     1124 <kernel_assert_print+0x24>
test   %r10b,%r10b
jne    1124 <kernel_assert_print+0x24>
shr    $0x20,%rsi
jne    1124 <kernel_assert_print+0x24>
lea    (%r14,%r11,1),%rcx
cmp    %r14,%rcx
jb     1124 <kernel_assert_print+0x24>
test   %r8b,%r8b
jne    1124 <kernel_assert_print+0x24>
lea    0x1(%r14),%rcx
lea    (%r14,%r11,1),%rsi
add    $0x1,%rsi
cmp    %rcx,%rsi
jb     1124 <kernel_assert_print+0x24>
test   %r8b,%r8b
jne    1124 <kernel_assert_print+0x24>
lea    (%r14,%r9,2),%rcx
cmp    %rdi,%rcx
jbe    1243 <kernel_assert_print+0x143>
lea    (%rdi,%r9,1),%rcx
cmp    %r14,%rcx
ja     1122 <kernel_assert_print+0x22>
mov    %r9d,%eax
and    $0xfffffff0,%eax
lea    -0x10(%rax),%rcx
mov    %rcx,%r8
shr    $0x4,%r8
add    $0x1,%r8
test   %rcx,%rcx
je     132c <kernel_assert_print+0x22c>
mov    %r8,%r10
and    $0xfffffffffffffffe,%r10
mov    $0x31,%ecx
xor    %esi,%esi
movdqa 0xd89(%rip),%xmm0
nopw   0x0(%rax,%rax,1)
movq   (%rdi,%rsi,1),%xmm1
movq   0x8(%rdi,%rsi,1),%xmm2
lea    -0x30(%rcx),%r11d
lea    -0x20(%rcx),%ebx
movslq %r11d,%r11
movslq %ebx,%rbx
punpcklbw %xmm0,%xmm1
movdqu %xmm1,-0x1(%r14,%r11,1)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,-0x1(%r14,%rbx,1)
movq   0x10(%rdi,%rsi,1),%xmm1
movq   0x18(%rdi,%rsi,1),%xmm2
lea    -0x10(%rcx),%ebx
movslq %ebx,%rbx
movslq %ecx,%rcx
punpcklbw %xmm0,%xmm1
movdqu %xmm1,-0x1(%r14,%rbx,1)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,-0x1(%r14,%rcx,1)
add    $0x20,%rsi
add    $0x40,%ecx
add    $0xfffffffffffffffe,%r10
jne    1280 <kernel_assert_print+0x180>
test   $0x1,%r8b
je     131e <kernel_assert_print+0x21e>
movq   (%rdi,%rsi,1),%xmm0
movq   0x8(%rdi,%rsi,1),%xmm1
lea    (%rsi,%rsi,1),%ecx
movslq %ecx,%rcx
movdqa 0xcfb(%rip),%xmm2
punpcklbw %xmm2,%xmm0
movdqu %xmm0,(%r14,%rcx,1)
or     $0x11,%rcx
punpcklbw %xmm2,%xmm1
movdqu %xmm1,-0x1(%r14,%rcx,1)
cmp    %r9,%rax
jne    1124 <kernel_assert_print+0x24>
jmp    11c2 <kernel_assert_print+0xc2>
xor    %esi,%esi
test   $0x1,%r8b
jne    12ec <kernel_assert_print+0x1ec>
jmp    131e <kernel_assert_print+0x21e>

LLVM IR (-O0):
define void @kernel_assert_print(i8* %0, i32 %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i32
store i8* %0, i8** %4
store i32 %1, i32* %5
store i32 %2, i32* %6
%9 = load i32, i32* %6
%10 = shl i32 %9, 1
%11 = add i32 753664, %10
%12 = zext i32 %11 to i64
%13 = inttoptr i64 %12 to i8*
store i8* %13, i8** %7
store i32 0, i32* %8
br label %14
14: ; preds = %35, %3
%15 = load i32, i32* %8
%16 = load i32, i32* %5
%17 = icmp ult i32 %15, %16
br i1 %17, label %18, label %38
18: ; preds = %14
%19 = load i8*, i8** %4
%20 = load i32, i32* %8
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds i8, i8* %19, i64 %21
%23 = load i8, i8* %22
%24 = load i8*, i8** %7
%25 = load i32, i32* %8
%26 = shl i32 %25, 1
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds i8, i8* %24, i64 %27
store i8 %23, i8* %28
%29 = load i8*, i8** %7
%30 = load i32, i32* %8
%31 = shl i32 %30, 1
%32 = add nsw i32 %31, 1
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds i8, i8* %29, i64 %33
store i8 7, i8* %34
br label %35
35: ; preds = %18
%36 = load i32, i32* %8
%37 = add nsw i32 %36, 1
store i32 %37, i32* %8
br label %14
38: ; preds = %14
ret void
}

LLVM IR (-O2):
define void @kernel_assert_print(i8* nocapture %0, i32 %1, i32 %2) {
%4 = shl i32 %2, 1
%5 = add i32 %4, 753664
%6 = zext i32 %5 to i64
%7 = inttoptr i64 %6 to i8*
%8 = icmp eq i32 %1, 0
br i1 %8, label %175, label %9
9: ; preds = %3
%10 = zext i32 %1 to i64
%11 = icmp ult i32 %1, 16
br i1 %11, label %129, label %12
12: ; preds = %9
%13 = add nsw i64 %10, -1
%14 = trunc i64 %13 to i32
%15 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %14, i32 2)
%16 = extractvalue { i32, i1 } %15, 0
%17 = extractvalue { i32, i1 } %15, 1
%18 = icmp slt i32 %16, 0
%19 = or i1 %18, %17
%20 = icmp ugt i64 %13, 4294967295
%21 = or i1 %19, %20
%22 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %13, i64 2)
%23 = extractvalue { i64, i1 } %22, 0
%24 = extractvalue { i64, i1 } %22, 1
%25 = getelementptr i8, i8* %7, i64 %23
%26 = icmp ult i8* %25, %7
%27 = or i1 %26, %24
%28 = getelementptr i8, i8* %7, i64 1
%29 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %13, i64 2)
%30 = extractvalue { i64, i1 } %29, 0
%31 = extractvalue { i64, i1 } %29, 1
%32 = getelementptr i8, i8* %28, i64 %30
%33 = icmp ult i8* %32, %28
%34 = or i1 %33, %31
%35 = or i1 %21, %27
%36 = or i1 %35, %34
br i1 %36, label %129, label %37
37: ; preds = %12
%38 = getelementptr i8, i8* %0, i64 %10
%39 = shl nuw nsw i64 %10, 1
%40 = getelementptr i8, i8* %7, i64 %39
%41 = icmp ugt i8* %40, %0
%42 = icmp ugt i8* %38, %7
%43 = and i1 %41, %42
br i1 %43, label %129, label %44
44: ; preds = %37
%45 = and i64 %10, 4294967280
%46 = add nsw i64 %45, -16
%47 = lshr exact i64 %46, 4
%48 = add nuw nsw i64 %47, 1
%49 = and i64 %48, 1
%50 = icmp eq i64 %46, 0
br i1 %50, label %102, label %51
51: ; preds = %44
%52 = and i64 %48, 2305843009213693950
%53 = getelementptr inbounds i8, i8* %7, i64 -1
%54 = getelementptr inbounds i8, i8* %7, i64 -1
%55 = getelementptr inbounds i8, i8* %7, i64 -1
%56 = getelementptr inbounds i8, i8* %7, i64 -1
br label %57
57: ; preds = %57, %51
%58 = phi i64 [ 0, %51 ], [ %99, %57 ]
%59 = phi i64 [ 0, %51 ], [ %100, %57 ]
%60 = trunc i64 %58 to i32
%61 = getelementptr inbounds i8, i8* %0, i64 %58
%62 = bitcast i8* %61 to <8 x i8>*
%63 = load <8 x i8>, <8 x i8>* %62
%64 = getelementptr inbounds i8, i8* %61, i64 8
%65 = bitcast i8* %64 to <8 x i8>*
%66 = load <8 x i8>, <8 x i8>* %65
%67 = shl i32 %60, 1
%68 = shl i32 %60, 1
%69 = or i32 %67, 1
%70 = or i32 %68, 17
%71 = sext i32 %69 to i64
%72 = sext i32 %70 to i64
%73 = getelementptr inbounds i8, i8* %53, i64 %71
%74 = bitcast i8* %73 to <16 x i8>*
%75 = getelementptr inbounds i8, i8* %54, i64 %72
%76 = bitcast i8* %75 to <16 x i8>*
%77 = shufflevector <8 x i8> %63, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %77, <16 x i8>* %74
%78 = shufflevector <8 x i8> %66, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %78, <16 x i8>* %76
%79 = or i64 %58, 16
%80 = trunc i64 %79 to i32
%81 = getelementptr inbounds i8, i8* %0, i64 %79
%82 = bitcast i8* %81 to <8 x i8>*
%83 = load <8 x i8>, <8 x i8>* %82
%84 = getelementptr inbounds i8, i8* %81, i64 8
%85 = bitcast i8* %84 to <8 x i8>*
%86 = load <8 x i8>, <8 x i8>* %85
%87 = shl i32 %80, 1
%88 = shl i32 %80, 1
%89 = or i32 %87, 1
%90 = or i32 %88, 17
%91 = sext i32 %89 to i64
%92 = sext i32 %90 to i64
%93 = getelementptr inbounds i8, i8* %55, i64 %91
%94 = bitcast i8* %93 to <16 x i8>*
%95 = getelementptr inbounds i8, i8* %56, i64 %92
%96 = bitcast i8* %95 to <16 x i8>*
%97 = shufflevector <8 x i8> %83, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %97, <16 x i8>* %94
%98 = shufflevector <8 x i8> %86, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %98, <16 x i8>* %96
%99 = add nuw i64 %58, 32
%100 = add i64 %59, 2
%101 = icmp eq i64 %100, %52
br i1 %101, label %102, label %57
102: ; preds = %57, %44
%103 = phi i64 [ 0, %44 ], [ %99, %57 ]
%104 = icmp eq i64 %49, 0
br i1 %104, label %127, label %105
105: ; preds = %102
%106 = trunc i64 %103 to i32
%107 = getelementptr inbounds i8, i8* %0, i64 %103
%108 = bitcast i8* %107 to <8 x i8>*
%109 = load <8 x i8>, <8 x i8>* %108
%110 = getelementptr inbounds i8, i8* %107, i64 8
%111 = bitcast i8* %110 to <8 x i8>*
%112 = load <8 x i8>, <8 x i8>* %111
%113 = shl i32 %106, 1
%114 = shl i32 %106, 1
%115 = or i32 %113, 1
%116 = or i32 %114, 17
%117 = sext i32 %115 to i64
%118 = sext i32 %116 to i64
%119 = getelementptr inbounds i8, i8* %7, i64 -1
%120 = getelementptr inbounds i8, i8* %7, i64 -1
%121 = getelementptr inbounds i8, i8* %119, i64 %117
%122 = bitcast i8* %121 to <16 x i8>*
%123 = getelementptr inbounds i8, i8* %120, i64 %118
%124 = bitcast i8* %123 to <16 x i8>*
%125 = shufflevector <8 x i8> %109, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %125, <16 x i8>* %122
%126 = shufflevector <8 x i8> %112, <8 x i8> <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %126, <16 x i8>* %124
br label %127
127: ; preds = %102, %105
%128 = icmp eq i64 %45, %10
br i1 %128, label %175, label %129
129: ; preds = %37, %12, %9, %127
%130 = phi i64 [ 0, %37 ], [ 0, %12 ], [ 0, %9 ], [ %45, %127 ]
%131 = xor i64 %130, -1
%132 = and i64 %10, 1
%133 = icmp eq i64 %132, 0
br i1 %133, label %146, label %134
134: ; preds = %129
%135 = getelementptr inbounds i8, i8* %0, i64 %130
%136 = load i8, i8* %135
%137 = shl i64 %130, 33
%138 = ashr exact i64 %137, 32
%139 = getelementptr inbounds i8, i8* %7, i64 %138
store i8 %136, i8* %139
%140 = trunc i64 %130 to i32
%141 = shl i32 %140, 1
%142 = or i32 %141, 1
%143 = sext i32 %142 to i64
%144 = getelementptr inbounds i8, i8* %7, i64 %143
store i8 7, i8* %144
%145 = or i64 %130, 1
br label %146
146: ; preds = %134, %129
%147 = phi i64 [ %130, %129 ], [ %145, %134 ]
%148 = sub nsw i64 0, %10
%149 = icmp eq i64 %131, %148
br i1 %149, label %175, label %150
150: ; preds = %146, %150
%151 = phi i64 [ %173, %150 ], [ %147, %146 ]
%152 = getelementptr inbounds i8, i8* %0, i64 %151
%153 = load i8, i8* %152
%154 = shl i64 %151, 33
%155 = ashr exact i64 %154, 32
%156 = getelementptr inbounds i8, i8* %7, i64 %155
store i8 %153, i8* %156
%157 = trunc i64 %151 to i32
%158 = shl i32 %157, 1
%159 = or i32 %158, 1
%160 = sext i32 %159 to i64
%161 = getelementptr inbounds i8, i8* %7, i64 %160
store i8 7, i8* %161
%162 = add nuw nsw i64 %151, 1
%163 = getelementptr inbounds i8, i8* %0, i64 %162
%164 = load i8, i8* %163
%165 = shl i64 %162, 33
%166 = ashr exact i64 %165, 32
%167 = getelementptr inbounds i8, i8* %7, i64 %166
store i8 %164, i8* %167
%168 = trunc i64 %162 to i32
%169 = shl i32 %168, 1
%170 = or i32 %169, 1
%171 = sext i32 %170 to i64
%172 = getelementptr inbounds i8, i8* %7, i64 %171
store i8 7, i8* %172
%173 = add nuw nsw i64 %151, 2
%174 = icmp eq i64 %173, %10
br i1 %174, label %175, label %150
175: ; preds = %146, %150, %127, %3
ret void
}