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

📄 asmmacro.s

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 S
📖 第 1 页 / 共 3 页
字号:
    push ecx
    push edx
    push ds
    push es
    push gs

    /* Set the R3 data segment */
    mov ax, KGDT_R3_DATA + RPL_MASK

    /* Skip debug registers and debug stuff */
    sub esp, 0x30

    /* Load the segment registers */
    .byte 0x66
    mov ds, ax
    .byte 0x66
    mov es, ax

    /* Check if this interrupt happened in 16-bit mode */
    cmp esp, 0x10000
    jb _Ki16BitStackException

    /* Set up frame */
    mov ebp, esp

    /* Check if this was from V86 Mode */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86_&Label

V86_&EndLabel:
    /* Get current thread */
    mov ecx, fs:[KPCR_CURRENT_THREAD]
    cld

    /* Flush DR7 */
    and dword ptr [ebp+KTRAP_FRAME_DR7], 0

    /* Check if the thread was being debugged */
    test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
    jnz Dr_&Label

    /* Set the Trap Frame Debug Header */
Dr_&EndLabel:
    SET_TF_DEBUG_HEADER
.endm

//
// @name INT_PROLOG
// 
// This macro creates a standard interrupt entry prologue.
// It should be used for entry into any interrupt, including software.
//
// @param Label
//        Identifying name of the caller function; will be used to append
//        to the name V86, ABIOS and DR helper functions, which must exist.
//
// @remark For software interrupts, make sure that a fake INT stack is created.
//
.macro INT_PROLOG Label EndLabel FakeErrorCode

.if \FakeErrorCode
    /* Save fake error code */
    push esp
.endif

    /* Save the non-volatiles */
    push ebp
    push ebx
    push esi
    push edi

    /* Skip debug registers and other stuff */
    sub esp, 0x54

    /* Set up frame */
    mov ebp, esp

    /* Save volatiles */ 
    mov [esp+KTRAP_FRAME_EAX], eax
    mov [esp+KTRAP_FRAME_ECX], ecx
    mov [esp+KTRAP_FRAME_EDX], edx
    mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1

    /* Check if this was from V86 Mode */
    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
    jnz V86_&Label

    /* Check if this was kernel mode */
V86_&EndLabel:
    cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
    jz 1f

    /* Set segments */
    mov word ptr [esp+KTRAP_FRAME_FS], fs
    mov word ptr [esp+KTRAP_FRAME_DS], ds
    mov word ptr [esp+KTRAP_FRAME_ES], es
    mov [esp+KTRAP_FRAME_GS], gs

    /* Load the segment registers (use OVERRIDE (0x66)) */
    mov ebx, KGDT_R0_PCR
    mov eax, KGDT_R3_DATA | RPL_MASK
    .byte 0x66
    mov fs, bx
    .byte 0x66
    mov ds, ax
    .byte 0x66
    mov es, ax

1: 
    /* Get the previous exception list */
    mov ebx, fs:[KPCR_EXCEPTION_LIST]

    /* Set the exception handler chain terminator */
    mov dword ptr fs:[KPCR_EXCEPTION_LIST], -1

    /* Save the previous exception list */
    mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx

.ifeq \FakeErrorCode
    /* Setup the 16-bit stack */
    lea eax, [esp+KTRAP_FRAME_ERROR_CODE]
    lea ecx, [esp+KTRAP_FRAME_EIP]
    mov ebx, ss:[eax]
    mov ss:[eax], ecx
.endif

    /* Check if this is the ABIOS stack */
    /* cmp esp, 0x10000*/
    /* jb Abios_Label*/

    /* Delete error code */
    and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0

    /* Get the current thread and clear direction flag */
    mov ecx, PCR[KPCR_CURRENT_THREAD]
    cld

    /* Flush DR7 */
    and dword ptr [ebp+KTRAP_FRAME_DR7], 0

    /* Check if the thread was being debugged */
    test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF

.ifeq \FakeErrorCode
    /* Push parameter */
    push ebx
.endif

    /* Save DR registers if needed */
    jnz Dr_&Label

    /* Set the trap frame debug header */
Dr_&EndLabel:
    SET_TF_DEBUG_HEADER
.endm

//
// @name SYSCALL_PROLOG
// 
// This macro creates a system call entry prologue.
// It should be used for entry into any fast-system call (KiGetTickCount,
// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
// (KiSystemService)
//
// @param Label
//        Unique label identifying the name of the caller function; will be
//        used to append to the name of the DR helper function, which must
//        already exist.
//
// @remark None.
//
.macro SYSCALL_PROLOG Label EndLabel
    /* Create a trap frame */
    push 0
    push ebp
    push ebx
    push esi
    push edi
    push fs

    /* Load PCR Selector into fs */
    mov ebx, KGDT_R0_PCR
    .byte 0x66
    mov fs, bx

    /* Get a pointer to the current thread */
    mov esi, PCR[KPCR_CURRENT_THREAD]

    /* Save the previous exception list */
    push PCR[KPCR_EXCEPTION_LIST]

    /* Set the exception handler chain terminator */
    mov dword ptr PCR[KPCR_EXCEPTION_LIST], -1

    /* Save the old previous mode */
    push [esi+KTHREAD_PREVIOUS_MODE]

    /* Skip the other registers */
    sub esp, 0x48

    /* Set the new previous mode based on the saved CS selector */
    mov ebx, [esp+0x6C]
    and ebx, 1
    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], bl

    /* Go on the Kernel stack frame */
    mov ebp, esp

    /* Save the old trap frame pointer where EDX would be saved */
    mov ebx, [esi+KTHREAD_TRAP_FRAME]
    mov [ebp+KTRAP_FRAME_EDX], ebx

    /* Flush DR7 */
    and dword ptr [ebp+KTRAP_FRAME_DR7], 0

    /* Check if the thread was being debugged */
    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF

    /* Set the thread's trap frame and clear direction flag */
    mov [esi+KTHREAD_TRAP_FRAME], ebp
    cld

    /* Save DR registers if needed */
    jnz Dr_&Label

    /* Set the trap frame debug header */
Dr_&EndLabel:
    SET_TF_DEBUG_HEADER

    /* Enable interrupts */
    sti
.endm

//
// @name FASTCALL_PROLOG
// 
// TODO
//
// @param Label
//        Unique label identifying the name of the caller function; will be
//        used to append to the name of the DR helper function, which must
//        already exist.
//
// @remark None.
//
.macro FASTCALL_PROLOG Label EndLabel

    /* Set user selector */
    mov ecx, KGDT_R3_DATA | RPL_MASK

    /* Set FS to PCR */
    push KGDT_R0_PCR
    pop fs

    /* Set DS/ES to User Selector */
    mov ds, cx
    mov es, cx

    /* Set the current stack to Kernel Stack */
    mov ecx, PCR[KPCR_TSS]
    mov esp, [ecx+KTSS_ESP0]

    /* Set up a fake INT Stack. */
    push KGDT_R3_DATA + RPL_MASK
    push edx                            /* Ring 3 SS:ESP */
    pushf                               /* Ring 3 EFLAGS */
    push 2                              /* Ring 0 EFLAGS */
    add edx, 8                          /* Skip user parameter list */
    popf                                /* Set our EFLAGS */
    or dword ptr [esp], EFLAGS_INTERRUPT_MASK   /* Re-enable IRQs in EFLAGS, to fake INT */
    push KGDT_R3_CODE + RPL_MASK
    push dword ptr ds:KUSER_SHARED_SYSCALL_RET

    /* Setup the Trap Frame stack */
    push 0
    push ebp
    push ebx
    push esi
    push edi
    push KGDT_R3_TEB + RPL_MASK

    /* Save pointer to our PCR */
    mov ebx, PCR[KPCR_SELF]

    /* Get a pointer to the current thread */
    mov esi, [ebx+KPCR_CURRENT_THREAD]

    /* Set the exception handler chain terminator */
    push [ebx+KPCR_EXCEPTION_LIST]
    mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1

    /* Use the thread's stack */
    mov ebp, [esi+KTHREAD_INITIAL_STACK]

    /* Push previous mode */
    push UserMode

    /* Skip the other registers */
    sub esp, 0x48

    /* Make space for us on the stack */
    sub ebp, 0x29C

    /* Write the previous mode */
    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode

    /* Sanity check */
    cmp ebp, esp
    jnz BadStack

    /* Flush DR7 */
    and dword ptr [ebp+KTRAP_FRAME_DR7], 0

    /* Check if the thread was being debugged */
    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF

    /* Set the thread's trap frame */
    mov [esi+KTHREAD_TRAP_FRAME], ebp

    /* Save DR registers if needed */
    jnz Dr_&Label

    /* Set the trap frame debug header */
Dr_&EndLabel:
    SET_TF_DEBUG_HEADER

    /* Enable interrupts */
    sti
.endm

//
// @name V86_TRAP_PROLOG
// 
// This macro creates a V86 Trap entry prologue.
// It should be used for entry into any fast-system call (KiGetTickCount,
// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
// (KiSystemService)
//
// @param Label
//        Unique label identifying the name of the caller function; will be
//        used to append to the name of the DR helper function, which must
//        already exist.
//
// @remark None.
//
.macro V86_TRAP_PROLOG Label EndLabel

    /* Skip everything to the error code */
    sub esp, KTRAP_FRAME_ERROR_CODE

    /* Clear the error code */
    mov word ptr [esp+KTRAP_FRAME_ERROR_CODE+2], 0

    /* Save the registers we'll trample */
    mov [esp+KTRAP_FRAME_EBX], ebx
    mov [esp+KTRAP_FRAME_EAX], eax
    mov [esp+KTRAP_FRAME_EBP], ebp
    mov [esp+KTRAP_FRAME_ESI], esi
    mov [esp+KTRAP_FRAME_EDI], edi

    /* Save PCR and Ring 3 segments */
    mov ebx, KGDT_R0_PCR
    mov eax, KGDT_R3_DATA + RPL_MASK

    /* Save ECX and EDX too */
    mov [esp+KTRAP_FRAME_ECX], ecx
    mov [esp+KTRAP_FRAME_EDX], edx

    /* Set debugging markers */
    mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
    mov dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00

    /* Now set segments (use OVERRIDE, 0x66) */
    .byte 0x66
    mov fs, bx
    .byte 0x66
    mov ds, ax
    .byte 0x66
    mov es, ax

    /* Set the trap frame in the stack and clear the direction flag */
    mov ebp, esp
    cld

    /* Save the exception list */
    mov eax, fs:[KPCR_EXCEPTION_LIST]
    mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax

    /* Check if we need debugging */
    mov eax, dr7
    test eax, ~DR7_RESERVED_MASK
    mov [esp+KTRAP_FRAME_DR7], eax
    jnz Dr_&Label

Dr_&EndLabel:
.endm

//
// @name V86_TRAP_EPILOG
// 
// This macro creates an epilogue for leaving V86 traps
//
// @param None.
//
// @remark None.
//
.macro V86_TRAP_EPILOG

    /* Get the current thread and make it unalerted */
ExitBegin:
    mov ebx, PCR[KPCR_CURRENT_THREAD]
    mov byte ptr [ebx+KTHREAD_ALERTED], 0

    /* Check if it has User-mode APCs pending */
    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
    jne PendingUserApc

    /* It doesn't, pop the frame */
    add esp, KTRAP_FRAME_EDX
    pop edx
    pop ecx
    pop eax

    /* Check if DR registers should be restored */
    test dword ptr [ebp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
    jnz V86DebugRestore

    /* Finish popping the rest of the frame, and return to P-mode */
V86DebugContinue:
    add esp, 12
    pop edi
    pop esi
    pop ebx
    pop ebp
    add esp, 4
    iretd

V86DebugRestore:

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

    /* Clear DR 7 */
    mov dr7, ebx

    /* Get DR2 and load DR0-2 */
    mov ebx, [ebp+KTRAP_FRAME_DR2]
    mov dr0, esi
    mov dr1, edi
    mov dr2, ebx

    /* Get DR3-7 */
    mov esi, [ebp+KTRAP_FRAME_DR0]

⌨️ 快捷键说明

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