📄 asmmacro.s
字号:
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 + -