⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v86m_sup.s

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 S
📖 第 1 页 / 共 2 页
字号:
    /* 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 + -