+\r
+#THUNK_ATTRIBUTE_BIG_REAL_MODE EQU 1\r
+#THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2\r
+#THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4\r
+\r
+ .code: \r
+\r
+_m16Start: \r
+\r
+SavedGdt: .space 6\r
+\r
+_BackFromUserCode:\r
+ push %ss\r
+ push %cs\r
+ .byte 0x66\r
+ call @Base1 # push eip\r
+@Base1: \r
+ pushfw # pushfd actually\r
+ cli # disable interrupts\r
+ push %gs\r
+ push %fs\r
+ push %es\r
+ push %ds\r
+ pushaw # pushad actually\r
+ .byte 0x66,0xba # mov edx, imm32\r
+_ThunkAttr: .space 4\r
+ testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl\r
+ jz @1\r
+ movl $0x15cd2401, %eax # mov ax, 2401h & int 15h\r
+ cli # disable interrupts\r
+ jnc @2\r
+@1: \r
+ testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl\r
+ jz @2\r
+ inb $0x92, %al\r
+ orb $2, %al\r
+ outb %al, $0x92 # deactivate A20M#\r
+@2: \r
+ movl %ss, %eax\r
+ .byte 0x67, 0x66, 0x8d, 0x6c, 0x24, 0x34, 0x66\r
+ mov %ebp,0xffffffd8(%esi)\r
+ mov 0xfffffff8(%esi),%ebx\r
+ shlw $4, %ax # shl eax, 4\r
+ addw %ax, %bp # add ebp, eax\r
+ .byte 0x66,0xb8 # mov eax, imm32\r
+SavedCr4: .space 4\r
+ movl %eax, %cr4\r
+ lgdtw %cs:0xfffffff2(%edi)\r
+ .byte 0x66,0xb8 # mov eax, imm32\r
+SavedCr0: .space 4\r
+ movl %eax, %cr0\r
+ .byte 0xb8 # mov ax, imm16\r
+SavedSs: .space 2\r
+ movl %eax, %ss\r
+ .byte 0x66,0xbc # mov esp, imm32\r
+SavedEsp: .space 4\r
+ .byte 0x66\r
+ lret # return to protected mode\r
+\r
+_EntryPoint: .long _ToUserCode - _m16Start\r
+ .word 0x8\r
+_16Idtr: .word 0x3ff\r
+ .long 0\r
+_16Gdtr: .word GdtEnd - _NullSegDesc - 1\r
+_16GdtrBase: .long _NullSegDesc\r
+\r
+_ToUserCode:\r
+ movl %ss, %edx\r
+ movl %ecx, %ss # set new segment selectors\r
+ movl %ecx, %ds\r
+ movl %ecx, %es\r
+ movl %ecx, %fs\r
+ movl %ecx, %gs\r
+ movl %eax, %cr0\r
+ movl %ebp, %cr4 # real mode starts at next instruction\r
+ movl %esi, %ss # set up 16-bit stack segment\r
+ xchgw %bx, %sp # set up 16-bit stack pointer\r
+ .byte 0x66\r
+ call @Base # push eip\r
+@Base: \r
+ popw %bp # ebp <- offset @Base\r
+ addr16 pushl 36(%si)\r
+ .byte 0x36\r
+ lea 0xc(%esi),%eax\r
+ pushl %eax\r
+ lret\r
+\r
+@RealMode: \r
+ mov %edx,%cs:0xffffffc5(%esi)\r
+ mov %bx,%cs:0xffffffcb(%esi)\r
+ lidtw %cs:0xffffffd7(%esi)\r
+ popaw # popad actually\r
+ popl %ds\r
+ popl %es\r
+ popl %fs\r
+ popl %gs\r
+ popfw # popfd\r
+ lretw # transfer control to user code\r
+\r
+_NullSegDesc: .quad 0\r
+_16CsDesc:\r
+ .word -1\r
+ .word 0\r
+ .byte 0\r
+ .byte 0x9b\r
+ .byte 0x8f # 16-bit segment, 4GB limit\r
+ .byte 0\r
+_16DsDesc:\r
+ .word -1\r
+ .word 0\r
+ .byte 0\r
+ .byte 0x93\r
+ .byte 0x8f # 16-bit segment, 4GB limit\r
+ .byte 0\r
+GdtEnd:\r
+\r
+#\r
+# @param RegSet Pointer to a IA32_DWORD_REGS structure\r
+# @param Transition Pointer to the transition code\r
+# @return The address of the 16-bit stack after returning from user code\r
+#\r