mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 12:26:09 +00:00
Fix setjmp (didn't save correct ESP, so it crashed after longjmp).
Fix the kernel debugger. svn path=/trunk/; revision=16002
This commit is contained in:
parent
8502799382
commit
faeb567e1c
4 changed files with 132 additions and 89 deletions
|
@ -8,15 +8,17 @@ _KdbEnter:
|
||||||
/*
|
/*
|
||||||
* Set up a trap frame
|
* Set up a trap frame
|
||||||
*/
|
*/
|
||||||
/* Ss - space already reserved by return EIP */
|
|
||||||
pushl %esp /* Esp */
|
|
||||||
pushfl /* Eflags */
|
pushfl /* Eflags */
|
||||||
pushl %cs /* Cs */
|
pushl %cs /* Cs */
|
||||||
pushl 12(%esp) /* Eip */
|
|
||||||
movl %ss, 16(%esp) /* Save Ss */
|
|
||||||
pushl $0 /* ErrorCode */
|
pushl $0 /* ErrorCode */
|
||||||
pushl %ebp /* Ebp */
|
pushl %ebp /* Ebp */
|
||||||
pushl %ebx /* Ebx */
|
pushl %ebx /* Ebx */
|
||||||
|
movl 20(%esp), %ebp /* Eip */
|
||||||
|
movl 16(%esp), %ebx /* Eflags */
|
||||||
|
movl %ebx, 20(%esp)
|
||||||
|
movl 12(%esp), %ebx /* Cs */
|
||||||
|
movl %ebx, 16(%esp)
|
||||||
|
movl %ebp, 12(%esp)
|
||||||
pushl %esi /* Esi */
|
pushl %esi /* Esi */
|
||||||
pushl %edi /* Edi */
|
pushl %edi /* Edi */
|
||||||
pushl %fs /* Fs */
|
pushl %fs /* Fs */
|
||||||
|
@ -43,8 +45,9 @@ _KdbEnter:
|
||||||
pushl %eax /* Dr1 */
|
pushl %eax /* Dr1 */
|
||||||
movl %dr0, %eax
|
movl %dr0, %eax
|
||||||
pushl %eax /* Dr0 */
|
pushl %eax /* Dr0 */
|
||||||
pushl $0 /* TempEip */
|
leal 0x58(%esp), %eax
|
||||||
pushl $0 /* TempCs */
|
pushl %eax /* TempEsp */
|
||||||
|
pushl %ss /* TempSegSs */
|
||||||
pushl $0 /* DebugPointer */
|
pushl $0 /* DebugPointer */
|
||||||
pushl $3 /* DebugArgMark (Exception number) */
|
pushl $3 /* DebugArgMark (Exception number) */
|
||||||
pushl 0x60(%esp) /* DebugEip */
|
pushl 0x60(%esp) /* DebugEip */
|
||||||
|
@ -67,8 +70,8 @@ _KdbEnter:
|
||||||
* DebugEip
|
* DebugEip
|
||||||
* DebugArgMark
|
* DebugArgMark
|
||||||
* DebugPointer
|
* DebugPointer
|
||||||
* TempCs
|
* TempSegSs
|
||||||
* TempEip
|
* TempEsp
|
||||||
*/
|
*/
|
||||||
addl $(11*4), %esp
|
addl $(11*4), %esp
|
||||||
|
|
||||||
|
@ -98,23 +101,13 @@ _KdbEnter:
|
||||||
popl %edx /* Edx */
|
popl %edx /* Edx */
|
||||||
popl %ecx /* Ecx */
|
popl %ecx /* Ecx */
|
||||||
popl %eax /* Eax */
|
popl %eax /* Eax */
|
||||||
addl $4, %esp /* PreviousMode */
|
addl $8, %esp /* PreviousMode, ExceptionList */
|
||||||
addl $4, %esp /* ExceptionList */
|
|
||||||
popl %fs /* Fs */
|
popl %fs /* Fs */
|
||||||
popl %edi /* Edi */
|
popl %edi /* Edi */
|
||||||
popl %esi /* Esi */
|
popl %esi /* Esi */
|
||||||
popl %ebx /* Ebx */
|
popl %ebx /* Ebx */
|
||||||
|
|
||||||
/* Remove SS:ESP from the stack */
|
|
||||||
movl 16(%esp), %ebp
|
|
||||||
movl %ebp, 24(%esp)
|
|
||||||
movl 12(%esp), %ebp
|
|
||||||
movl %ebp, 20(%esp)
|
|
||||||
movl 8(%esp), %ebp
|
|
||||||
movl %ebp, 16(%esp)
|
|
||||||
|
|
||||||
popl %ebp /* Ebp */
|
popl %ebp /* Ebp */
|
||||||
addl $12, %esp /* ErrorCode and SS:ESP */
|
addl $4, %esp /* ErrorCode */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return to the caller.
|
* Return to the caller.
|
||||||
|
|
|
@ -38,7 +38,9 @@
|
||||||
* return PC
|
* return PC
|
||||||
*/
|
*/
|
||||||
.globl _setjmp
|
.globl _setjmp
|
||||||
|
.globl __setjmp
|
||||||
_setjmp:
|
_setjmp:
|
||||||
|
__setjmp:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp,%ebp
|
movl %esp,%ebp
|
||||||
|
|
||||||
|
@ -55,5 +57,5 @@ _setjmp:
|
||||||
|
|
||||||
xorl %eax,%eax /* return 0 the first time */
|
xorl %eax,%eax /* return 0 the first time */
|
||||||
leave
|
leave
|
||||||
ret $4
|
ret
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: Gregor Anich
|
* PROGRAMMERS: Gregor Anich
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
|
@ -106,6 +106,65 @@ STATIC CONST PCHAR ExceptionNrToString[] =
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
STATIC VOID
|
||||||
|
KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
|
||||||
|
{
|
||||||
|
/* Copy the TrapFrame only up to Eflags and zero the rest*/
|
||||||
|
RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, Esp));
|
||||||
|
RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, Esp)),
|
||||||
|
sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, Esp));
|
||||||
|
asm volatile(
|
||||||
|
"movl %%cr0, %0" "\n\t"
|
||||||
|
"movl %%cr2, %1" "\n\t"
|
||||||
|
"movl %%cr3, %2" "\n\t"
|
||||||
|
"movl %%cr4, %3" "\n\t"
|
||||||
|
: "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
|
||||||
|
"=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
|
||||||
|
|
||||||
|
if (TrapFrame->PreviousMode == KernelMode)
|
||||||
|
{
|
||||||
|
/* If the trapframe is a kmode one use the temp ss:esp */
|
||||||
|
KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
|
||||||
|
KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise use ss:esp pushed by the CPU */
|
||||||
|
/* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
|
||||||
|
* can handle umode and kmode the same way */
|
||||||
|
KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
|
||||||
|
KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC VOID
|
||||||
|
KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
/* Copy the TrapFrame only up to Eflags and zero the rest*/
|
||||||
|
RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, Esp));
|
||||||
|
|
||||||
|
/* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
|
||||||
|
|
||||||
|
if (TrapFrame->PreviousMode == KernelMode)
|
||||||
|
{
|
||||||
|
/* If the trapframe is a kmode one write to the temp ss:esp */
|
||||||
|
TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
|
||||||
|
TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise write to ss:esp pushed by the CPU */
|
||||||
|
/* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
|
||||||
|
* can handle umode and kmode the same way */
|
||||||
|
TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
|
||||||
|
TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
||||||
|
}
|
||||||
|
|
||||||
/*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
|
/*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
|
||||||
* the old instruction in *OldInst.
|
* the old instruction in *OldInst.
|
||||||
*
|
*
|
||||||
|
@ -981,7 +1040,7 @@ KdbpAttachToThread(
|
||||||
if (KdbCurrentThread != KdbOriginalThread)
|
if (KdbCurrentThread != KdbOriginalThread)
|
||||||
{
|
{
|
||||||
ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
|
ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
|
||||||
RtlCopyMemory(KdbCurrentThread->Tcb.TrapFrame, &KdbCurrentTrapFrame->Tf, sizeof (KTRAP_FRAME));
|
KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -991,15 +1050,12 @@ KdbpAttachToThread(
|
||||||
/* Switch to the thread's context */
|
/* Switch to the thread's context */
|
||||||
if (Thread != KdbOriginalThread)
|
if (Thread != KdbOriginalThread)
|
||||||
{
|
{
|
||||||
ASSERT(Thread->Tcb.TrapFrame != NULL);
|
if (Thread->Tcb.TrapFrame == NULL)
|
||||||
RtlCopyMemory(&KdbThreadTrapFrame.Tf, Thread->Tcb.TrapFrame, sizeof (KTRAP_FRAME));
|
{
|
||||||
asm volatile(
|
KdbpPrint("Threads TrapFrame is NULL! Cannot attach.\n");
|
||||||
"movl %%cr0, %0" "\n\t"
|
return FALSE;
|
||||||
"movl %%cr2, %1" "\n\t"
|
}
|
||||||
"movl %%cr3, %2" "\n\t"
|
KdbpTrapFrameToKdbTrapFrame(Thread->Tcb.TrapFrame, &KdbThreadTrapFrame);
|
||||||
"movl %%cr4, %3" "\n\t"
|
|
||||||
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
|
|
||||||
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
|
|
||||||
KdbCurrentTrapFrame = &KdbThreadTrapFrame;
|
KdbCurrentTrapFrame = &KdbThreadTrapFrame;
|
||||||
}
|
}
|
||||||
else /* Switching back to original thread */
|
else /* Switching back to original thread */
|
||||||
|
@ -1243,14 +1299,7 @@ KdbEnterDebuggerException(
|
||||||
if (BreakPoint->Condition != NULL)
|
if (BreakPoint->Condition != NULL)
|
||||||
{
|
{
|
||||||
/* Setup the KDB trap frame */
|
/* Setup the KDB trap frame */
|
||||||
RtlCopyMemory(&KdbTrapFrame.Tf, TrapFrame, sizeof (KTRAP_FRAME));
|
KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
|
||||||
asm volatile(
|
|
||||||
"movl %%cr0, %0" "\n\t"
|
|
||||||
"movl %%cr2, %1" "\n\t"
|
|
||||||
"movl %%cr3, %2" "\n\t"
|
|
||||||
"movl %%cr4, %3" "\n\t"
|
|
||||||
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
|
|
||||||
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
|
|
||||||
|
|
||||||
ull = 0;
|
ull = 0;
|
||||||
if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
|
if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
|
||||||
|
@ -1395,14 +1444,7 @@ KdbEnterDebuggerException(
|
||||||
KdbCurrentTrapFrame = &KdbTrapFrame;
|
KdbCurrentTrapFrame = &KdbTrapFrame;
|
||||||
|
|
||||||
/* Setup the KDB trap frame */
|
/* Setup the KDB trap frame */
|
||||||
RtlCopyMemory(&KdbTrapFrame.Tf, TrapFrame, sizeof(KTRAP_FRAME));
|
KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
|
||||||
asm volatile(
|
|
||||||
"movl %%cr0, %0" "\n\t"
|
|
||||||
"movl %%cr2, %1" "\n\t"
|
|
||||||
"movl %%cr3, %2" "\n\t"
|
|
||||||
"movl %%cr4, %3" "\n\t"
|
|
||||||
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
|
|
||||||
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
|
|
||||||
|
|
||||||
/* Enter critical section */
|
/* Enter critical section */
|
||||||
Ke386SaveFlags(OldEflags);
|
Ke386SaveFlags(OldEflags);
|
||||||
|
@ -1436,7 +1478,7 @@ KdbEnterDebuggerException(
|
||||||
/* Save the current thread's trapframe */
|
/* Save the current thread's trapframe */
|
||||||
if (KdbCurrentTrapFrame == &KdbThreadTrapFrame)
|
if (KdbCurrentTrapFrame == &KdbThreadTrapFrame)
|
||||||
{
|
{
|
||||||
RtlCopyMemory(KdbCurrentThread->Tcb.TrapFrame, KdbCurrentTrapFrame, sizeof (KTRAP_FRAME));
|
KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach from attached process */
|
/* Detach from attached process */
|
||||||
|
@ -1446,16 +1488,7 @@ KdbEnterDebuggerException(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the exception TrapFrame */
|
/* Update the exception TrapFrame */
|
||||||
RtlCopyMemory(TrapFrame, &KdbTrapFrame.Tf, sizeof(KTRAP_FRAME));
|
KdbpKdbTrapFrameToTrapFrame(&KdbTrapFrame, TrapFrame);
|
||||||
#if 0
|
|
||||||
asm volatile(
|
|
||||||
"movl %0, %%cr0" "\n\t"
|
|
||||||
"movl %1, %%cr2" "\n\t"
|
|
||||||
"movl %2, %%cr3" "\n\t"
|
|
||||||
"movl %3, %%cr4" "\n\t"
|
|
||||||
: : "r"(KdbTrapFrame.Cr0), "r"(KdbTrapFrame.Cr2),
|
|
||||||
"r"(KdbTrapFrame.Cr3), "r"(KdbTrapFrame.Cr4));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Decrement the entry count */
|
/* Decrement the entry count */
|
||||||
InterlockedDecrement(&KdbEntryCount);
|
InterlockedDecrement(&KdbEntryCount);
|
||||||
|
|
|
@ -116,7 +116,7 @@ BadThread:
|
||||||
.globl @KiSwapContextInternal@0
|
.globl @KiSwapContextInternal@0
|
||||||
@KiSwapContextInternal@0:
|
@KiSwapContextInternal@0:
|
||||||
#ifdef KDBG
|
#ifdef KDBG
|
||||||
//jmp SaveTrapFrameForKDB
|
jmp SaveTrapFrameForKDB
|
||||||
SaveTrapFrameForKDB_Return:
|
SaveTrapFrameForKDB_Return:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -298,32 +298,55 @@ SameProcess:
|
||||||
|
|
||||||
SaveTrapFrameForKDB:
|
SaveTrapFrameForKDB:
|
||||||
/* Set up a trap frame */
|
/* Set up a trap frame */
|
||||||
|
|
||||||
/* Fake Interrupt Stack */
|
|
||||||
push esp // 0x74
|
|
||||||
pushf // 0x70
|
pushf // 0x70
|
||||||
push cs // 0x6C
|
push cs // 0x6C
|
||||||
push [esp+12] /* EIP */ // 0x68
|
push 0 /* Error Code */ // 0x64
|
||||||
mov [esp+16], ss // 0x78
|
|
||||||
|
|
||||||
/* Trap Frame */
|
|
||||||
push 0 /* Error Code */ // 0x64
|
|
||||||
push ebp // 0x60
|
push ebp // 0x60
|
||||||
push ebx
|
push ebx
|
||||||
|
|
||||||
|
/* Fake Interrupt Stack */
|
||||||
|
mov ebp, [esp+20] /* Eip */
|
||||||
|
mov ebx, [esp+16] /* Eflags */
|
||||||
|
mov [esp+20], ebx
|
||||||
|
mov ebx, [esp+12] /* Cs */
|
||||||
|
mov [esp+16], ebx
|
||||||
|
mov [esp+12], ebp
|
||||||
|
|
||||||
push esi
|
push esi
|
||||||
push edi
|
push edi
|
||||||
push fs
|
push fs
|
||||||
push -1 /* Exception List */ // 0x4C
|
push -1 /* Exception List */ // 0x4C
|
||||||
push 0 /* Previous Mode */ // 0x48
|
push 0 /* Previous Mode */ // 0x48
|
||||||
push eax
|
push eax
|
||||||
push ecx
|
push ecx
|
||||||
push edx
|
push edx
|
||||||
push ds
|
push ds
|
||||||
push es
|
push es
|
||||||
push gs // 0x30
|
push gs // 0x30
|
||||||
sub esp, 0x28 /* Debug Registers */ // 0x8
|
|
||||||
push [esp+60] /* Debug EIP */ // 0x4
|
mov eax, dr7
|
||||||
push ebp /* Debug EBP */ // 0x0
|
push eax /* Dr7 */
|
||||||
|
/* Clear breakpoint enables in dr7. */
|
||||||
|
and eax, 0xffff0000
|
||||||
|
mov dr7, eax
|
||||||
|
mov eax, dr6
|
||||||
|
push eax /* Dr6 */
|
||||||
|
mov eax, dr3
|
||||||
|
push eax /* Dr3 */
|
||||||
|
mov eax, dr2
|
||||||
|
push eax /* Dr2 */
|
||||||
|
mov eax, dr1
|
||||||
|
push eax /* Dr1 */
|
||||||
|
mov eax, dr0
|
||||||
|
push eax /* Dr0 */
|
||||||
|
|
||||||
|
lea eax, [esp+0x58]
|
||||||
|
push eax /* TempEsp */
|
||||||
|
push ss /* TempSegSs */
|
||||||
|
push 0 /* DebugPointer */
|
||||||
|
push -1 /* DebugArgMark */
|
||||||
|
push [esp+60] /* Debug EIP */ // 0x4
|
||||||
|
push ebp /* Debug EBP */ // 0x0
|
||||||
|
|
||||||
/* Set Stack */
|
/* Set Stack */
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -334,19 +357,21 @@ SaveTrapFrameForKDB:
|
||||||
/* Save new one */
|
/* Save new one */
|
||||||
mov [edi+KTHREAD_TRAP_FRAME], ebp
|
mov [edi+KTHREAD_TRAP_FRAME], ebp
|
||||||
|
|
||||||
|
/* Restore EBP, EBX and EAX */
|
||||||
|
mov ebp, [ebp+KTRAP_FRAME_EBP]
|
||||||
|
mov ebx, [ebp+KTRAP_FRAME_EBX]
|
||||||
|
mov eax, [ebp+KTRAP_FRAME_EAX]
|
||||||
|
|
||||||
/* Return EIP */
|
/* Return EIP */
|
||||||
push offset RestoreTrapFrameForKDB
|
push offset RestoreTrapFrameForKDB
|
||||||
|
|
||||||
/* Restore EBP */
|
|
||||||
mov ebp, [ebp+KTRAP_FRAME_EBP]
|
|
||||||
|
|
||||||
/* Jump to normal code */
|
/* Jump to normal code */
|
||||||
jmp SaveTrapFrameForKDB_Return
|
jmp SaveTrapFrameForKDB_Return
|
||||||
|
|
||||||
RestoreTrapFrameForKDB:
|
RestoreTrapFrameForKDB:
|
||||||
|
|
||||||
/* Restore the old trapframe */
|
/* Restore the old trapframe */
|
||||||
pop [edi+KTHREAD_TRAP_FRAME]
|
pop [esi+KTHREAD_TRAP_FRAME]
|
||||||
|
|
||||||
/* Pop unused portions of the trap frame */
|
/* Pop unused portions of the trap frame */
|
||||||
add esp, 0x30
|
add esp, 0x30
|
||||||
|
@ -358,23 +383,13 @@ RestoreTrapFrameForKDB:
|
||||||
pop edx
|
pop edx
|
||||||
pop ecx
|
pop ecx
|
||||||
pop eax
|
pop eax
|
||||||
add esp, 8
|
add esp, 8 /* ExceptionList and PreviousMode */
|
||||||
pop fs
|
pop fs
|
||||||
pop edi
|
pop edi
|
||||||
pop esi
|
pop esi
|
||||||
pop ebx
|
pop ebx
|
||||||
|
|
||||||
/* Remove SS:ESP from the stack */
|
|
||||||
mov ebp, [esp+16]
|
|
||||||
mov [esp+24], ebp
|
|
||||||
mov ebp, [esp+12]
|
|
||||||
mov [esp+20], ebp
|
|
||||||
mov ebp, [esp+8]
|
|
||||||
mov [esp+16], ebp
|
|
||||||
|
|
||||||
/* Restore Fake INT Stack */
|
|
||||||
pop ebp
|
pop ebp
|
||||||
add esp, 12
|
add esp, 4 /* ErrorCode */
|
||||||
|
|
||||||
/* Return to the caller. */
|
/* Return to the caller. */
|
||||||
iret
|
iret
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue