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

📄 asmmacro.s

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 S
📖 第 1 页 / 共 3 页
字号:
    mov edi, [ebp+KTRAP_FRAME_DR1]
    mov ebx, [ebp+KTRAP_FRAME_DR7]

    /* Load them */
    mov dr3, esi
    mov dr6, edi
    mov dr7, ebx
    jmp V86DebugContinue

PendingUserApc:

    /* Raise to APC level */
    mov ecx, APC_LEVEL
    call @KfRaiseIrql@4

    /* Save KIRQL and deliver APCs */
    push eax
    sti
    push ebp
    push 0
    push UserMode
    call _KiDeliverApc@12

    /* Restore IRQL */
    pop ecx
    call @KfLowerIrql@4
    cli

    /* Check if we're not in V86 anymore */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz ExitBegin
.endm

//
// @name TRAP_EPILOG
// 
// This macro creates an epilogue for leaving any system trap.
// It is used for exiting system calls, exceptions, interrupts and generic
// traps.
//
// @param SystemCall
//        Specifies whether this trap will exit a system call. If so, special
//        code will be assembled to potentially use SYSEXIT instead of IRETD.
//
// @param RestorePreviousMode
//        Specifies if the previous mode should be restored.
//
// @param RestoreSegments
//        Specifies if the segment registers should be restored.
//
// @param RestoreVolatiles
//        Specifies if the volatile registers should be restored.
//
// @param RestoreAllRegs
//        Specifies if volatiles and segments should both be restored.
//
// @remark
//
.macro TRAP_EPILOG SystemCall, RestorePreviousMode, RestoreSegments, RestoreVolatiles, RestoreAllRegs
#ifdef DBG
    /* Assert the flags */
    pushfd
    pop edx
    test edx, EFLAGS_INTERRUPT_MASK
    jnz 6f

    /* Assert the stack */
    cmp esp, ebp
    jnz 6f

    /* Assert the trap frame */
#endif
5:
#ifdef DBG
    sub dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
    jnz 0f

    /* Assert FS */
    mov bx, fs
    cmp bx, KGDT_R0_PCR
    jnz 1f

    /* Assert exception list */
    cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0
    jnz 2f

1:
    push -1
    call _KeBugCheck@4
#endif

2:
    /* Get exception list */
    mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]

#ifdef DBG
    /* Assert the saved exception list */
    or edx, edx
    jnz 1f
    UNHANDLED_PATH
1:
#endif

    /* Restore it */
    mov PCR[KPCR_EXCEPTION_LIST], edx

.if \RestorePreviousMode
    /* Get previous mode */
    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]

#ifdef DBG
    /* Assert the saved previous mode */
    cmp ecx, -1
    jnz 1f
    UNHANDLED_PATH
1:
#endif

    /* Restore the previous mode */
    mov esi, PCR[KPCR_CURRENT_THREAD]
    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
.else

#ifdef DBG
    /* Assert the saved previous mode */
    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
    cmp ecx, -1
    jz 1f
    UNHANDLED_PATH
1:
#endif
.endif

    /* Check for debug registers */
    test dword ptr [esp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
    jnz 2f

    /* Check for V86 */
4:
    test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86_Exit

    /* Check if the frame was edited */
    test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
    jz 7f

.if \RestoreAllRegs
    /* Check the old mode */
    cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
    bt word ptr [esp+KTRAP_FRAME_CS], 0
    cmc
    ja 8f
.endif

.if \RestoreVolatiles
    /* Restore volatiles */
    mov edx, [esp+KTRAP_FRAME_EDX]
    mov ecx, [esp+KTRAP_FRAME_ECX]
    mov eax, [esp+KTRAP_FRAME_EAX]
.endif

    /* Check if we were called from kernel mode */
    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
    jz 9f

.if \RestoreSegments
    /* Restore segment registers */
    lea esp, [ebp+KTRAP_FRAME_GS]
    pop gs
    pop es
    pop ds
.endif

    /* Restore FS */
3:
    lea esp, [ebp+KTRAP_FRAME_FS]
    pop fs

9:
    /* Skip debug information and unsaved registers */
    lea esp, [ebp+KTRAP_FRAME_EDI]
    pop edi
    pop esi
    pop ebx
    pop ebp

    /* Check for ABIOS */
    cmp word ptr [esp+8], 0x80
    ja AbiosExit

    /* Pop error code */
    add esp, 4

.if \SystemCall
    /* Check if previous CS is from user-mode */
    test dword ptr [esp+4], 1

    /* It is, so use Fast Exit */
    jnz FastExit

    /* Jump back to stub */
    pop edx
    pop ecx
    popf
    jmp edx

.ret:
.endif
    iret

.if \SystemCall
FastExit:
    /* Is SYSEXIT Supported/Wanted? */
    cmp dword ptr ss:[_KiFastSystemCallDisable], 0
    jnz .ret
    test dword ptr [esp+8], EFLAGS_TF
    jnz .ret

    /* Restore FS to TIB */
    mov ecx, KGDT_R3_TEB + RPL_MASK
    mov fs, ecx

    /* We will be cleaning up the stack ourselves */
    pop edx                                 /* New Ring 3 EIP */
    add esp, 4                              /* Skip Ring 3 DS */
    and dword ptr [esp], 0xfffffdff         /* Remove EFLAGS_INTERRUPT_MASK from EFLAGS */
    popf                                    /* Restore old EFLAGS */
    pop ecx                                 /* Old Ring 3 SS:ESP */

    /*
     * At this point:
     *     ECX points to the old User Stack.
     *     EDX points to the instruction to execute in usermode after the sysenter
     */
    sti
    sysexit
.endif

.if \RestoreAllRegs
8:
    /* Restore EAX */
    mov eax, [esp+KTRAP_FRAME_EAX]

    /* Skip registers */
    add esp, 0x30

    /* Restore segments and volatiles */
    pop gs
    pop es
    pop ds
    pop edx
    pop ecx

    /* Jump back to mainline code */
    jmp 3b
.endif

#if DBG
0:
    /* Fix up the mask */
    add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00

6:
    UNHANDLED_PATH
    jmp 5b
#endif

2:
    /* Check if this was V86 mode */
    test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz 1f

    /* Check if it was user mode */
    test word ptr [esp+KTRAP_FRAME_CS], MODE_MASK
    jz 4b

1:
    /* Clear DR7 */
    xor ebx, ebx
    mov dr7, ebx

    /* Get DR0, 1, 2 */
    mov esi, [ebp+KTRAP_FRAME_DR0]
    mov edi, [ebp+KTRAP_FRAME_DR1]
    mov ebx, [ebp+KTRAP_FRAME_DR2]

    /* Set them */
    mov dr0, esi
    mov dr1, edi
    mov dr2, ebx

    /* Get DR3, 6, 7 */
    mov esi, [ebp+KTRAP_FRAME_DR3]
    mov edi, [ebp+KTRAP_FRAME_DR6]
    mov ebx, [ebp+KTRAP_FRAME_DR7]

    /* Set them */
    mov dr3, esi
    mov dr6, edi
    mov dr7, ebx
    jmp 4b

7:
    /* Restore real CS value */
    mov ebx, [esp+KTRAP_FRAME_TEMPCS]
    mov [esp+KTRAP_FRAME_CS], ebx

    /*
     * If ESP was modified, then a special interrupt exit stack
     * must be created to "update" ESP's value in a legal manner
     */
    mov ebx, [esp+KTRAP_FRAME_TEMPESP]
    sub ebx, 0xC
    mov [esp+KTRAP_FRAME_ERROR_CODE], ebx

    /* Copy Interrupt Stack */
    mov esi, [esp+KTRAP_FRAME_EFLAGS]
    mov [ebx+8], esi
    mov esi, [esp+KTRAP_FRAME_CS]
    mov [ebx+4], esi
    mov esi, [esp+KTRAP_FRAME_EIP]
    mov [ebx], esi

.if \RestoreVolatiles
    /* Restore volatiles */
    mov eax, [esp+KTRAP_FRAME_EAX]
    mov edx, [esp+KTRAP_FRAME_EDX]
    mov ecx, [esp+KTRAP_FRAME_ECX]
.endif

    /* Return */
    add esp, KTRAP_FRAME_EDI
    pop edi
    pop esi
    pop ebx
    pop ebp
    mov esp, [esp]
    iret
.endm

//
// @name INT_EPILOG
// 
// This macro creates an epilogue for leaving any system trap.
// It is used for exiting system calls, exceptions, interrupts and generic
// traps.
//
// @param Spurious - TRUE if the interrupt was unexpected and spurious.
//
// @remark None.
//
.macro INT_EPILOG Spurious

.if \Spurious
    /* Just exit the trap */
    jmp _Kei386EoiHelper@0
.else
    /* Disable interrupts */
    cli

    /* End the interrupt and do EOI */
    call _HalEndSystemInterrupt@8
    jmp _Kei386EoiHelper@0
.endif
.endm

#ifdef DBG

.macro VERIFY_INT Label
    /* Get the current time and mask it to 192 ticks */
    mov eax, _KeTickCount
    and eax, 0xC0

    /* Check if we're in the same tick area */
    cmp eax, dword ptr [edi+KINTERRUPT_TICK_COUNT]
    jg VfRst_&Label
    jl VfWrap_&Label

    /* If we got here, then our count is too large */
    dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT]
    jz VfOvr_&Label
Vf_&Label:
.endm

.macro VERIFY_INT_END Label, Info
VfOvr_&Label:

    /* Decrement the dispatch count and check if we should bug check */
    dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2]
    jz 1f

    /* Update the tick count */
    add eax, 0x40
    mov [edi+KINTERRUPT_TICK_COUNT], eax
    jmp VfRstDef_&Label

.1:
    /* Check if the debugger is enabled */
    cmp byte ptr __KdDebuggerEnabled, 0
    jnz 1f

    /* It isn't, bugcheck */
    push Info
    push edi
    push [edi+KINTERRUPT_SERVICE_CONTEXT]
    push [edi+KINTERRUPT_SERVICE_ROUTINE]
    push HARDWARE_INTERRUPT_STORM
    call _KeBugCheckEx@20

1:
    /* Debugger enabled, do a debug print + break instead */
    push [edi+KINTERRUPT_SERVICE_ROUTINE]
    push offset _IsrOverflowMsg
    call _DbgPrint
    add esp, 8
    int 3

    /* Breakpoint handled, get the new tick count */
    mov eax, _KeTickCount
    and eax, 0xC0

VfRst_&Label:
    /* Reset tick count */
    mov dword ptr [edi+KINTERRUPT_TICK_COUNT], eax
    mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2], 64

VfRstDef_&Label:
    /* Put default overflow count and continue */
    mov ax, _KiISROverflow
    mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT], ax
    jmp Vf_&Label

VfWrap_&Label:
    /* Check if we wrapped */
    add eax, 0x40
    cmp eax, [edi+KINTERRUPT_TICK_COUNT]
    je Vf_&Label

    /* We did, start over */
    mov eax, _KeTickCount
    jmp VfRst_&Label
.endm

#else

/* We don't verify interrupts on retail builds */
.macro VERIFY_INT Label
.endm
.macro VERIFY_INT_END Label, Info
.endm

#endif


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -