📄 asmfuncs.asm
字号:
;******************************************************************************
;*
;* Copyright (c) 2000-2001 Intel Corporation. All rights reserved
;*
;* This software and associated documenation (if any) is furnished
;* under a license and may only be used or copied in accordance
;* with the terms of the license. Except as permitted by such
;* license, no part of this software or documentation may be
;* reproduced, stored in a retrieval system, or transmitted in any
;* form or by any means without the express written consent of
;* Intel Corporation.
;*
;******************************************************************************
.586p
.MODEL FLAT, C
EXCPT32_DIVIDE_ERROR EQU 0
EXCPT32_DEBUG EQU 1
EXCPT32_NMI EQU 2
EXCPT32_BREAKPOINT EQU 3
EXCPT32_OVERFLOW EQU 4
EXCPT32_BOUND EQU 5
EXCPT32_INVALID_OPCODE EQU 6
EXCPT32_DOUBLE_FAULT EQU 8
EXCPT32_INVALID_TSS EQU 10
EXCPT32_SEG_NOT_PRESENT EQU 11
EXCPT32_STACK_FAULT EQU 12
EXCPT32_GP_FAULT EQU 13
EXCPT32_PAGE_FAULT EQU 14
EXCPT32_FP_ERROR EQU 16
EXCPT32_ALIGNMENT_CHECK EQU 17
EXCPT32_MACHINE_CHECK EQU 18
EXCPT32_SIMD EQU 19
FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags
;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,
;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver
;; MUST check the CPUID feature flags to see that these instructions are available
;; and fail to init if they are not.
;; fxstor [edi]
FXSTOR_EDI MACRO
db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [edi]
ENDM
;; fxrstor [esi]
FXRSTOR_ESI MACRO
db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [esi]
ENDM
.DATA
public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport
StubSize dd InterruptEntryStubEnd - InterruptEntryStub
AppEsp dd 11111111h ; ?
DebugEsp dd 22222222h ; ?
ExtraPush dd 33333333h ; ?
ExceptData dd 44444444h ; ?
Eflags dd 55555555h ; ?
OrigVector dd 66666666h ; ?
;; The declarations below define the memory region that will be used for the debug stack.
;; The context record will be built by pushing register values onto this stack.
;; It is imparitive that alignment be carefully managed, since the FXSTOR and
;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.
;;
;; The stub will switch stacks from the application stack to the debuger stack
;; and pushes the exception number.
;;
;; Then we building the context record on the stack. Since the stack grows down,
;; we push the fields of the context record from the back to the front. There
;; are 132 bytes of stack used prior allocating the 512 bytes of stack to be
;; used as the memory buffer for the fxstor instruction. Therefore address of
;; the buffer used for the FXSTOR instruction is &Eax - 132 - 512, which
;; must be 16 byte aligned.
;;
;; We carefully locate the stack to make this happen.
;;
;; For reference, the context structure looks like this:
;; struct {
;; UINT32 ExceptionData;
;; FX_SAVE_STATE FxSaveState; // 512 bytes, must be 16 byte aligned
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
;; UINT32 Ldtr, Tr;
;; UINT64 Gdtr, Idtr;
;; UINT32 EFlags;
;; UINT32 Eip;
;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record
align 16
DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment
dd 1ffdh dup (000000000h) ;; 32K should be enough stack
;; This allocation is coocked to insure
;; that the the buffer for the FXSTORE instruction
;; will be 16 byte aligned also.
;;
ExceptionNumber dd ? ;; first entry will be the vector number pushed by the stub
DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub
.CODE
externdef InterruptDistrubutionHub:near
;------------------------------------------------------------------------------
; BOOLEAN
; FxStorSupport (
; void
; )
;
; Abstract: Returns TRUE if FxStor instructions are supported
;
FxStorSupport PROC C PUBLIC
;
; cpuid corrupts ebx which must be preserved per the C calling convention
;
push ebx
mov eax, 1
cpuid
mov eax, edx
and eax, FXSTOR_FLAG
shr eax, 24
pop ebx
ret
FxStorSupport ENDP
;------------------------------------------------------------------------------
; DESCRIPTOR *
; GetIdtr (
; void
; )
;
; Abstract: Returns physical address of IDTR
;
GetIdtr PROC C PUBLIC
LOCAL IdtrBuf:FWORD
sidt IdtrBuf
mov eax, DWORD PTR IdtrBuf + 2
ret
GetIdtr ENDP
;------------------------------------------------------------------------------
; BOOLEAN
; WriteInterruptFlag (
; BOOLEAN NewState
; )
;
; Abstract: Programs interrupt flag to the requested state and returns previous
; state.
;
WriteInterruptFlag PROC C PUBLIC State:DWORD
pushfd
pop eax
and eax, 200h
shr eax, 9
mov ecx, State
.IF ecx == 0
cli
.ELSE
sti
.ENDIF
ret
WriteInterruptFlag ENDP
;------------------------------------------------------------------------------
; void
; Vect2Desc (
; DESCRIPTOR * DestDesc,
; void (*Vector) (void)
; )
;
; Abstract: Encodes an IDT descriptor with the given physical address
;
Vect2Desc PROC C PUBLIC DestPtr:DWORD, Vector:DWORD
mov eax, Vector
mov ecx, DestPtr
mov word ptr [ecx], ax ; write bits 15..0 of offset
mov word ptr [ecx+2], 20h ; SYS_CODE_SEL from GDT
mov word ptr [ecx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
shr eax, 16
mov word ptr [ecx+6], ax ; write bits 31..16 of offset
ret
Vect2Desc ENDP
;------------------------------------------------------------------------------
; InterruptEntryStub
;
; Abstract: This code is not a function, but is a small piece of code that is
; copied and fixed up once for each IDT entry that is hooked.
;
InterruptEntryStub::
mov AppEsp, esp ; save stack top
mov esp, offset DebugStackBegin ; switch to debugger stack
push 0 ; push vector number - will be modified before installed
db 0e9h ; jump rel32
dd 0 ; fixed up to relative address of CommonIdtEntry
InterruptEntryStubEnd:
;------------------------------------------------------------------------------
; CommonIdtEntry
;
; Abstract: This code is not a function, but is the common part for all IDT
; vectors.
;
CommonIdtEntry::
;;
;; At this point, the stub has saved the current application stack esp into AppEsp
;; and switched stacks to the debug stack, where it pushed the vector number
;;
;; The application stack looks like this:
;;
;; ...
;; (last application stack entry)
;; eflags from interrupted task
;; CS from interrupted task
;; EIP from interrupted task
;; Error code <-------------------- Only present for some exeption types
;;
;;
;; The stub switched us to the debug stack and pushed the interrupt number.
;;
;; Next, construct the context record. It will be build on the debug stack by
;; pushing the registers in the correct order so as to create the context structure
;; on the debug stack. The context record must be built from the end back to the
;; beginning because the stack grows down...
;
;; For reference, the context record looks like this:
;;
;; typedef
;; struct {
;; UINT32 ExceptionData;
;; FX_SAVE_STATE FxSaveState;
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
;; UINT32 Cr0, Cr2, Cr3, Cr4;
;; UINT32 Ldtr, Tr;
;; UINT64 Gdtr, Idtr;
;; UINT32 EFlags;
;; UINT32 Eip;
;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
pushad
;; Save interrupt state eflags register...
pushfd
pop eax
mov dword ptr Eflags, eax
;; We need to determine if any extra data was pushed by the exception, and if so, save it
;; To do this, we check the exception number pushed by the stub, and cache the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -