-InternalAsmThunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15\r
- mov eax, ds\r
- push rax\r
- mov eax, es\r
- push rax\r
- push fs\r
- push gs\r
- mov rsi, rcx ; rsi <- RegSet\r
- push sizeof (IA32_REGS)\r
- pop rcx\r
- movzx r8, (IA32_REGS ptr [rsi])._SS\r
- xor rdi, rdi\r
- mov edi, (IA32_REGS ptr [rsi])._ESP\r
- sub rdi, rcx ; reserve space on realmode stack\r
- push rdi ; save stack offset\r
- imul rax, r8, 16\r
- add rdi, rax ; rdi <- linear address of 16-bit stack\r
- rep movsb ; copy RegSet\r
- mov rsi, r8 ; si <- 16-bit stack segment\r
- pop rbx ; rbx <- 16-bit stack offset\r
- mov rdi, rdx ; rdi <- realmode patch\r
- lea eax, @BackToThunk ; rax <- address to back from real mode\r
- push rax ; use in a far return\r
- mov eax, cs\r
- mov [rsp + 4], eax ; save CS\r
- lea eax, @16Return ; thus @Return must < 4GB\r
- stosd ; set ret address offset\r
- xor eax, eax\r
- stosw ; set ret CS base to 0\r
- mov eax, esp\r
- stosd ; rsp must < 4GB\r
- mov eax, ss\r
- stosd\r
- mov rax, cr0\r
- mov ecx, eax ; ecx <- CR0\r
- and ecx, 7ffffffeh ; clear PE, PG bits\r
- stosd\r
- mov rax, cr4\r
- mov ebp, eax\r
- and ebp, 300h ; clear all but PCE and OSFXSR bits\r
- stosd\r
- sidt fword ptr [rsp + 70h] ; use parameter space to save IDTR\r
- sgdt fword ptr [rdi]\r
- lea edi, _16Idtr\r
- lea eax, @16Start ; rax <- seg:offset of @16Start\r
- push rax\r
- mov dword ptr [rsp + 4], 8\r
- push 10h\r
- pop rax ; rax <- 10h as dataseg selector\r
- lgdt _16Gdtr\r
- retf\r
-@16Start: ; 16-bit starts here\r
- mov ss, eax ; set SS to be a 16-bit segment\r
- mov cr0, rcx ; disable protected mode\r
- mov cr4, rbp\r
- DB 66h\r
- mov ecx, 0c0000080h\r
- rdmsr\r
- and ah, NOT 1 ; clear LME\r
- wrmsr\r
- mov ss, esi ; set up 16-bit stack\r
- mov sp, bx ; mov esp, ebx actually\r
- lidt fword ptr [edi]\r
- DB 66h, 61h ; popad\r
- DB 1fh ; pop ds\r
- DB 7 ; pop es\r
- pop fs\r
- pop gs\r
- add sp, 8 ; skip _RFLAGS\r