📄 v86m_sup.s
字号:
/* Get the VDM State */
mov eax, 0x714
/* Get flat ESP */
movzx ecx, word ptr [ebp+KTRAP_FRAME_SS]
shl ecx, 4
movzx edx, word ptr [ebp+KTRAP_FRAME_ESP]
add ecx, edx
/* Check for OPER32 prefix */
test ebx, 0x4000
jnz Iret32
/* Get flat IP */
movzx edi, word ptr [ecx]
mov [ebp+KTRAP_FRAME_EIP], edi
movzx esi, word ptr [ecx+2]
mov [ebp+KTRAP_FRAME_CS], esi
/* Update ESP */
add edx, 6
mov [ebp+KTRAP_FRAME_ESP], edx
/* Get EFLAGS */
movzx ebx, word ptr [ecx+4]
MaskEFlags:
/* Mask out EFLAGS */
and ebx, ~(0x3000 + EFLAGS_VIF + 0x4000 + EFLAGS_VIP)
mov ecx, ebx
/* FIXME: Check for VME support */
/* Save VDM state */
push eax
/* Enable V86 and Interrupts */
or ebx, EFLAGS_V86_MASK + EFLAGS_INTERRUPT_MASK
/* Save old flags */
mov eax, [ebp+KTRAP_FRAME_EFLAGS]
push eax
/* Mask out VIP and set new eflags */
and eax, EFLAGS_VIP
or eax, ebx
mov [ebp+KTRAP_FRAME_EFLAGS], eax
/* Check if we have to update ESP0 */
pop ebx
test ebx, EFLAGS_V86_MASK
jnz NoEsp0Update
/* Save ECX and ECX */
push ecx
push edx
/* Update esp0 and restore registers */
push ebp
call _Ki386AdjustEsp0@4
pop edx
pop ecx
NoEsp0Update:
/* Put VDM state in EAX and update VDM EFlags */
pop eax
and ecx, EFLAGS_INTERRUPT_MASK
LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK
LOCK or [eax], ecx
/* Get flat EIP and check if this is the BOP */
shl esi, 4
add esi, edi
mov ax, [esi]
cmp ax, 0xC4C4
jz IsBop
/* FIXME: Check for VDM interrupts */
/* Return success */
RetIret:
mov eax, 1
ret
IsBop:
/* Call the BOP handler */
push ebp
call _VdmDispatchBop@4
jmp RetIret
Iret32:
/* Get 32-bit flat EIP */
mov edi, [ecx]
mov [ebp+KTRAP_FRAME_EIP], edi
movzx esi, word ptr [ecx+4]
mov [ebp+KTRAP_FRAME_CS], esi
/* Set new ESP */
add edx, 12
mov [ebp+KTRAP_FRAME_ESP], edx
/* Get EFLAGS and continue */
mov ebx, [ecx+8]
jmp MaskEFlags
.endfunc
.func OpcodeNPXV86
_OpcodeNPXV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINBimmV86
_OpcodeINBimmV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINWimmV86
_OpcodeINWimmV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTBimmV86
_OpcodeOUTBimmV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTWimmV86
_OpcodeOUTWimmV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINBV86
_OpcodeINBV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINWV86
_OpcodeINWV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTBV86
_OpcodeOUTBV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTWV86
_OpcodeOUTWV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeLOCKPrefixV86
_OpcodeLOCKPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeREPNEPrefixV86
_OpcodeREPNEPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeREPPrefixV86
_OpcodeREPPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeCLIV86
_OpcodeCLIV86:
/* Get VDM State */
mov eax, 0x714
/* FIXME: Support VME */
/* FIXME: Support VDM Interrupts */
/* Disable interrupts */
LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK
/* Update EIP (remember EDI == instruction size) */
add [ebp+KTRAP_FRAME_EIP], edi
/* Return success */
mov eax, 1
ret
.endfunc
.func OpcodeSTIV86
_OpcodeSTIV86:
/* Get VDM State */
mov eax, 0x714
/* FIXME: Support VME */
/* Enable interrupts */
LOCK or dword ptr [eax], EFLAGS_INTERRUPT_MASK
/* Update EIP (remember EDI == instruction size) */
add [ebp+KTRAP_FRAME_EIP], edi
/* FIXME: Support VDM Interrupts */
/* Return success */
mov eax, 1
ret
.endfunc
.func OpcodeHLTV86
_OpcodeHLTV86:
UNHANDLED_V86_OPCODE
.endfunc
/* FUNCTIONS *****************************************************************/
.globl _Ki386SetupAndExitToV86Mode@4
.func Ki386SetupAndExitToV86Mode@4
_Ki386SetupAndExitToV86Mode@4:
/* Save nonvolatiles */
push ebp
push ebx
push esi
push edi
/* Give us a little stack */
sub esp, 12
mov ecx, esp
/* Go past the KTRAP_FRAME and NPX Frame and set a new frame in EAX */
sub esp, NPX_FRAME_LENGTH
and esp, ~15
sub esp, KTRAP_FRAME_LENGTH
mov eax, esp
/* Create a fake user-mode frame */
mov dword ptr [eax+KTRAP_FRAME_CS], KGDT_R0_CODE + RPL_MASK
mov dword ptr [eax+KTRAP_FRAME_ES], 0
mov dword ptr [eax+KTRAP_FRAME_DS], 0
mov dword ptr [eax+KTRAP_FRAME_FS], 0
mov dword ptr [eax+KTRAP_FRAME_GS], 0
mov dword ptr [eax+KTRAP_FRAME_ERROR_CODE], 0
/* Get the current thread's initial stack */
mov ebx, [fs:KPCR_SELF]
mov edi, [ebx+KPCR_CURRENT_THREAD]
mov edx, [edi+KTHREAD_INITIAL_STACK]
sub edx, NPX_FRAME_LENGTH
/* Save it on our stack, as well as the real TEB addresses */
mov [ecx], edx
mov edx, [edi+KTHREAD_TEB]
mov [ecx+4], edx
mov edx, [fs:KPCR_TEB]
mov [ecx+8] , edx
/* Set our ESP in ESI, and the return function in EIP */
mov edi, offset _Ki386BiosCallReturnAddress
mov [eax+KTRAP_FRAME_ESI], ecx
mov [eax+KTRAP_FRAME_EIP], edi
/* Push the flags and sanitize them */
pushfd
pop edi
and edi, 0x60DD7
or edi, EFLAGS_INTERRUPT_MASK
/* Set SS and ESP, and fill out the rest of the frame */
mov dword ptr [eax+KTRAP_FRAME_SS], KGDT_R3_DATA + RPL_MASK;
mov dword ptr [eax+KTRAP_FRAME_ESP], 0x11FFE;
mov dword ptr [eax+KTRAP_FRAME_EFLAGS], edi
mov dword ptr [eax+KTRAP_FRAME_EXCEPTION_LIST], -1
mov dword ptr [eax+KTRAP_FRAME_PREVIOUS_MODE], -1
mov dword ptr [eax+KTRAP_FRAME_DR7], 0
mov dword ptr [eax+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
/* Jump past the frame now */
add eax, KTRAP_FRAME_LENGTH
cli
/* Save the current stack */
push ecx
/* Get the current thread's intial stack again */
mov edi, [ebx+KPCR_CURRENT_THREAD]
mov esi, [edi+KTHREAD_INITIAL_STACK]
sub esi, NPX_FRAME_LENGTH
/* Set the size of the copy, and the destination, and copy the NPX frame */
mov ecx, NPX_FRAME_LENGTH / 4
mov edi, eax
rep movsd
/* Restore stack */
pop ecx
/* Get the current thread and TSS */
mov edi, [ebx+KPCR_CURRENT_THREAD]
mov esi, [ebx+KPCR_TSS]
/* Bias the V86 vrame */
sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
/* Set exception list and new ESP */
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
mov [esi+KTSS_ESP0], eax
/* Now skip past the NPX frame and V86 fields and set this as the intial stack */
add eax, NPX_FRAME_LENGTH + (KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS)
mov [edi+KTHREAD_INITIAL_STACK], eax
/* Setup our fake TEB pointer */
mov eax, [ecx+0x20]
mov [fs:KPCR_TEB], eax
mov [edi+KTHREAD_TEB], eax
/* Setup the descriptors for the fake TEB */
mov ebx, [fs:KPCR_GDT]
mov [ebx+0x3A], ax
shr eax, 16
mov [ebx+0x3C], al
mov [ebx+0x3F], ah
sti
/*
* Start VDM execution. This will save this fake 32-bit KTRAP_FRAME and
* initialize a real 16-bit VDM context frame
*/
push 0
push 0 // VdmStartExecution
call _NtVdmControl@8
/* Exit to V86 mode */
mov ebp, esp
jmp _Kei386EoiHelper@0
.endfunc
.globl _Ki386BiosCallReturnAddress
.func Ki386BiosCallReturnAddress
_Ki386BiosCallReturnAddress:
/* Get the PCR */
mov eax, [fs:KPCR_SELF]
/* Get NPX destination */
mov edi, [ebp+KTRAP_FRAME_ESI]
mov edi, [edi]
/* Get initial stack */
mov ecx, [eax+KPCR_CURRENT_THREAD]
mov esi, [ecx+KTHREAD_INITIAL_STACK]
sub esi, NPX_FRAME_LENGTH
/* Set length and copy the NPX frame */
mov ecx, NPX_FRAME_LENGTH / 4
rep movsd
/* Restore stack */
mov esp, [ebp+KTRAP_FRAME_ESI]
add esp, 4
/* Set initial stack */
mov ecx, [eax+KPCR_CURRENT_THREAD]
mov [ecx+KTHREAD_INITIAL_STACK], edi
/* Get TSS and set the ESP 0 */
mov eax, [eax+KPCR_TSS]
sub edi, NPX_FRAME_LENGTH + (KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS)
mov [eax+KTSS_ESP0], edi
/* Restore KTHREAD TEB in EDX */
pop edx
mov [ecx+KTHREAD_TEB], edx
/* Restore PCR TEB in EDX */
pop edx
mov [fs:KPCR_TEB], edx
/* Setup the descriptors for the real TEB */
mov ebx, [fs:KPCR_GDT]
mov [ebx+0x3A], dx
shr edx, 16
mov [ebx+0x3C], dl
mov [ebx+0x3F], dh
/* Enable interrupts and pop back non-volatiles */
sti
pop edi
pop esi
pop ebx
pop ebp
ret 4
.endfunc
.globl _Ki386HandleOpcodeV86@0
.func Ki386HandleOpcodeV86@0
_Ki386HandleOpcodeV86@0:
/* Get flat EIP */
mov esi, [ebp+KTRAP_FRAME_CS]
shl esi, 4
add esi, [ebp+KTRAP_FRAME_EIP]
/* Get the opcode entry in the table */
movzx ecx, byte ptr [esi]
movzx edx, byte ptr OpcodeIndex[ecx]
/* Set instruction length and prefix flags */
mov edi, 1
xor ebx, ebx
/* Accounting statistics */
// inc dword ptr _ExVdmOpcodeDispatchCounts[edx*4] // FIXME: Generates protection fault
/* Handle the opcode */
jmp OpcodeDispatchV86[edx*4]
.endfunc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -