- Update to r53061
[reactos.git] / dll / ntdll / dispatch / i386 / dispatch.S
index 526e5b8..10706e2 100644 (file)
-/*\r
- * COPYRIGHT:       See COPYING in the top level directory\r
- * PROJECT:         ReactOS NT Library\r
- * FILE:            dl/ntdll/dispatch/i386/dispatch.S\r
- * PURPOSE:         User-Mode NT Dispatchers\r
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ndk/asm.h>\r
-.intel_syntax noprefix\r
-\r
-/* FUNCTIONS ****************************************************************/\r
-\r
-.func LdrInitializeThunk@16\r
-.globl _LdrInitializeThunk@16\r
-_LdrInitializeThunk@16:\r
-\r
-    /* Get the APC Context */\r
-    lea eax, [esp+16]\r
-\r
-    /* Send it as the first parameter */\r
-    mov [esp+4], eax\r
-\r
-    /* Terminate the frame list */\r
-    xor ebp, ebp\r
-\r
-    /* Jump into the C initialization routine */\r
-    jmp _LdrpInit@12\r
-.endfunc\r
-\r
-.func KiUserApcExceptionHandler\r
-_KiUserApcExceptionHandler:\r
-\r
-    /* Put the exception record in ECX and check the Flags */\r
-    mov ecx, [esp+4]\r
-    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING\r
-    jz .return\r
-\r
-    /* Test alert the thread */\r
-    call _NtTestAlert@0\r
-\r
-.return:\r
-    /* We'll execute handler */\r
-    mov eax, EXCEPTION_EXECUTE_HANDLER\r
-    ret 16\r
-.endfunc\r
-\r
-.func KiUserApcDispatcher@16\r
-.globl _KiUserApcDispatcher@16\r
-_KiUserApcDispatcher@16:\r
-\r
-    /* Setup SEH stack */\r
-    lea eax, [esp+CONTEXT_ALIGNED_SIZE+16]\r
-    mov ecx, fs:[TEB_EXCEPTION_LIST]\r
-    mov edx, offset _KiUserApcExceptionHandler\r
-    mov [eax], ecx\r
-    mov [eax+4], edx\r
-\r
-    /* Enable SEH */\r
-    mov fs:[TEB_EXCEPTION_LIST], eax\r
-\r
-    /* Put the Context in EDI */\r
-    pop eax\r
-    lea edi, [esp+12]\r
-\r
-    /* Call the APC Routine */\r
-    call eax\r
-\r
-    /* Restore exception list */\r
-    mov ecx, [edi+CONTEXT_ALIGNED_SIZE]\r
-    mov fs:[TEB_EXCEPTION_LIST], ecx\r
-\r
-    /* Switch back to the context */\r
-    push 1\r
-    push edi\r
-    call _ZwContinue@8\r
-\r
-    /* Save callback return value */\r
-    mov esi, eax\r
-\r
-    /* Raise status */\r
-StatusRaiseApc:\r
-    push esi\r
-    call _RtlRaiseStatus@4\r
-    jmp StatusRaiseApc\r
-    ret 16\r
-.endfunc\r
-\r
-.func KiUserCallbackExceptionHandler\r
-_KiUserCallbackExceptionHandler:\r
-\r
-    /* Put the exception record in ECX and check the Flags */\r
-    mov ecx, [esp+4]\r
-    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING\r
-    jz return\r
-\r
-    /* Tell the kernel to invalidate the stack */\r
-    push STATUS_CALLBACK_POP_STACK\r
-    push 0\r
-    push 0\r
-    call _ZwCallbackReturn@12\r
-\r
-return:\r
-    /* We'll execute the handler */\r
-    mov eax, EXCEPTION_EXECUTE_HANDLER\r
-    ret 16\r
-.endfunc\r
-\r
-.func KiUserCallbackDispatcher@12\r
-.globl _KiUserCallbackDispatcher@12\r
-_KiUserCallbackDispatcher@12:\r
-\r
-    /* Setup SEH stack */\r
-    mov ecx, fs:[TEB_EXCEPTION_LIST]\r
-    mov edx, offset _KiUserCallbackExceptionHandler\r
-    lea eax, [esp+16]\r
-    mov [esp+16], ecx\r
-    mov [esp+20], edx\r
-\r
-    /* Enable SEH */\r
-    mov fs:[TEB_EXCEPTION_LIST], eax\r
-\r
-    /* Get the callback Index */\r
-    add esp, 4\r
-    pop edx\r
-\r
-    /* Get the callback table */\r
-    mov eax, [fs:TEB_PEB]\r
-    mov eax, [eax+PEB_KERNEL_CALLBACK_TABLE]\r
-\r
-    /* Call the routine */\r
-    call [eax+edx*4]\r
-\r
-    /* Return from callback */\r
-    push eax\r
-    push 0\r
-    push 0\r
-    call _ZwCallbackReturn@12\r
-\r
-    /* Save callback return value */\r
-    mov esi, eax\r
-\r
-    /* Raise status */\r
-StatusRaise:\r
-    push esi\r
-    call _RtlRaiseStatus@4\r
-    jmp StatusRaise\r
-    ret 12\r
-.endfunc\r
-\r
-.func KiRaiseUserExceptionDispatcher@0\r
-.globl _KiRaiseUserExceptionDispatcher@0\r
-_KiRaiseUserExceptionDispatcher@0:\r
-\r
-    /* Setup stack for EXCEPTION_RECORD */\r
-    push ebp\r
-    mov ebp, esp\r
-    sub esp, EXCEPTION_RECORD_LENGTH\r
-\r
-    /* Fill out the record */\r
-    mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], eax\r
-    mov eax, [fs:KPCR_TEB]\r
-    mov eax, [eax+TEB_EXCEPTION_CODE]\r
-    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax\r
-    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], 0\r
-    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], 0\r
-    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0\r
-\r
-    /* Raise the exception */\r
-    push esp\r
-    call _RtlRaiseException@4\r
-\r
-    /* Return exception code */\r
-    mov eax, [esp+EXCEPTION_RECORD_EXCEPTION_CODE]\r
-    mov esp, ebp\r
-    pop ebp\r
-    ret\r
-.endfunc\r
-\r
-.func KiUserExceptionDispatcher@8\r
-.globl _KiUserExceptionDispatcher@8\r
-_KiUserExceptionDispatcher@8:\r
-\r
-    /* clear the direct flag \r
-     * text from bug 2279\r
-     * if it not clear it means that if an exception occurs while\r
-     * the direction flag is set (typically inside memmove), the \r
-     * exception handlers will be called with the direction flag still\r
-     * set.  The Windows x86-32 and x86-64 ABI requires that the \r
-     * direction flag be Calling memset() with a compile-time constant \r
-     * size on both GCC and MSVC will result in inlining a "rep stosd" \r
-     * instruction.  Because of the ABI, they will assume that the \r
-     * direction flag is clear and not emit a "cld" instruction. \r
-     * Using memset() in an exception handler therefore will \r
-     * corrupt memory if the exception occurred during a reverse copy \r
-     * such as a forward overlapping memmove().\r
-     *\r
-     * For reliability and ease of debugging, please add "cld" to the beginning of\r
-     * KiUserExceptionDispatcher.  Note that the same will be true of x86-64 whenever\r
-     * that happens.  This does not affect continuing execution; the CONTEXT of the\r
-     * exception has the direction flag set and will be restored upon NtContinue. \r
-     * KiUserApcDispatcher and KiUserCallbackDispatcher need to be evaluated for this\r
-     * issue.\r
-     */\r
-     \r
-    cld\r
-\r
-    /* Save the Context and Exception Records */\r
-    mov ecx, [esp+4]\r
-    mov ebx, [esp]\r
-\r
-    /* Call the vectored exception handler */\r
-    push ecx\r
-    push ebx\r
-    call _RtlpExecuteVectoredExceptionHandlers@8\r
-\r
-    /* Check for success */\r
-    or al, al\r
-    jnz ContinueExecution\r
-\r
-    /* Dispatch the exception */\r
-    sub esp, 8\r
-    call _RtlDispatchException@8\r
-\r
-    /* Check for success */\r
-    or al, al\r
-    jz RaiseException\r
-\r
-ContinueExecution:\r
-    /* Pop off the records */\r
-    pop ebx\r
-    pop ecx\r
-\r
-    /* We're fine, continue execution */\r
-    push 0\r
-    push ecx\r
-    call _ZwContinue@8\r
-\r
-    /* Exit */\r
-    jmp Exit\r
-\r
-RaiseException:\r
-    /* Pop off the records */\r
-    pop ebx\r
-    pop ecx\r
-\r
-    /* Raise the exception */\r
-    push 0\r
-    push ecx\r
-    push ebx\r
-    call _ZwRaiseException@12\r
-\r
-Exit:\r
-    /* Allocate space for the nested exception record */\r
-    add esp, -SIZEOF_EXCEPTION_RECORD\r
-\r
-    /* Set it up */\r
-    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax\r
-    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_NONCONTINUABLE\r
-    mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], ebx\r
-    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0\r
-\r
-    /* Raise the exception */\r
-    push esp\r
-    call _RtlRaiseException@4\r
-    ret 8\r
-.endfunc\r
-\r
-.func KiIntSystemCall@0\r
-.globl _KiIntSystemCall@0\r
-_KiIntSystemCall@0:\r
-\r
-    /* Set stack in EDX and do the interrupt */\r
-    lea edx, [esp+8]\r
-    int 0x2E\r
-\r
-    /* Return to caller */\r
-    ret\r
-.endfunc\r
-\r
-.func KiFastSystemCall@0\r
-.globl _KiFastSystemCall@0\r
-_KiFastSystemCall@0:\r
-\r
-    /* Put ESP in EDX and do the SYSENTER */\r
-    mov edx, esp\r
-    sysenter\r
-.endfunc\r
-\r
-.func KiFastSystemCallRet@0\r
-.globl _KiFastSystemCallRet@0\r
-_KiFastSystemCallRet@0:\r
-\r
-    /* Just return to caller */\r
-    ret\r
-.endfunc\r
-\r
-.func RtlpGetStackLimits@8\r
-.globl _RtlpGetStackLimits@8\r
-_RtlpGetStackLimits@8:\r
-\r
-    /* Get the stack limits */\r
-    mov eax, [fs:TEB_STACK_LIMIT]\r
-    mov ecx, [fs:TEB_STACK_BASE]\r
-\r
-    /* Return them */\r
-    mov edx, [esp+4]\r
-    mov [edx], eax\r
-    mov edx, [esp+8]\r
-    mov [edx], ecx\r
-\r
-    /* return */\r
-    ret 8\r
-.endfunc\r
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS NT Library
+ * FILE:            dl/ntdll/dispatch/i386/dispatch.S
+ * PURPOSE:         User-Mode NT Dispatchers
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <asm.inc>
+#include <ks386.inc>
+
+EXTERN _LdrpInit@12:PROC
+EXTERN _NtTestAlert@0:PROC
+EXTERN _RtlDispatchException@8:PROC
+EXTERN _RtlRaiseException@4:PROC
+EXTERN _RtlRaiseStatus@4:PROC
+EXTERN _ZwCallbackReturn@12:PROC
+EXTERN _ZwContinue@8:PROC
+EXTERN _ZwRaiseException@12:PROC
+
+/* FUNCTIONS ****************************************************************/
+.code
+
+PUBLIC _LdrInitializeThunk@16
+_LdrInitializeThunk@16:
+
+    /* Get the APC Context */
+    lea eax, [esp+16]
+
+    /* Send it as the first parameter */
+    mov [esp+4], eax
+
+    /* Terminate the frame list */
+    xor ebp, ebp
+
+    /* Jump into the C initialization routine */
+    jmp _LdrpInit@12
+
+
+_KiUserApcExceptionHandler:
+
+    /* Put the exception record in ECX and check the Flags */
+    mov ecx, [esp+4]
+    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
+    jz .return
+
+    /* Test alert the thread */
+    call _NtTestAlert@0
+
+.return:
+    /* We'll execute handler */
+    mov eax, EXCEPTION_EXECUTE_HANDLER
+    ret 16
+
+
+PUBLIC _KiUserApcDispatcher@16
+_KiUserApcDispatcher@16:
+
+    /* Setup SEH stack */
+    lea eax, [esp+CONTEXT_ALIGNED_SIZE+16]
+    mov ecx, fs:[TEB_EXCEPTION_LIST]
+    mov edx, offset _KiUserApcExceptionHandler
+    mov [eax], ecx
+    mov [eax+4], edx
+
+    /* Enable SEH */
+    mov fs:[TEB_EXCEPTION_LIST], eax
+
+    /* Put the Context in EDI */
+    pop eax
+    lea edi, [esp+12]
+
+    /* Call the APC Routine */
+    call eax
+
+    /* Restore exception list */
+    mov ecx, [edi+CONTEXT_ALIGNED_SIZE]
+    mov fs:[TEB_EXCEPTION_LIST], ecx
+
+    /* Switch back to the context */
+    push 1
+    push edi
+    call _ZwContinue@8
+
+    /* Save callback return value */
+    mov esi, eax
+
+    /* Raise status */
+StatusRaiseApc:
+    push esi
+    call _RtlRaiseStatus@4
+    jmp StatusRaiseApc
+    ret 16
+
+
+_KiUserCallbackExceptionHandler:
+
+    /* Put the exception record in ECX and check the Flags */
+    mov ecx, [esp+4]
+    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
+    jz return
+
+    /* Tell the kernel to invalidate the stack */
+    push STATUS_CALLBACK_POP_STACK
+    push 0
+    push 0
+    call _ZwCallbackReturn@12
+
+return:
+    /* We'll execute the handler */
+    mov eax, EXCEPTION_EXECUTE_HANDLER
+    ret 16
+
+
+PUBLIC _KiUserCallbackDispatcher@12
+_KiUserCallbackDispatcher@12:
+
+    /* Setup SEH stack */
+    mov ecx, fs:[TEB_EXCEPTION_LIST]
+    mov edx, offset _KiUserCallbackExceptionHandler
+    lea eax, [esp+16]
+    mov [esp+16], ecx
+    mov [esp+20], edx
+
+    /* Enable SEH */
+    mov fs:[TEB_EXCEPTION_LIST], eax
+
+    /* Get the callback Index */
+    add esp, 4
+    pop edx
+
+    /* Get the callback table */
+    mov eax, [fs:TEB_PEB]
+    mov eax, [eax+PEB_KERNEL_CALLBACK_TABLE]
+
+    /* Call the routine */
+    call dword ptr [eax+edx*4]
+
+    /* Return from callback */
+    push eax
+    push 0
+    push 0
+    call _ZwCallbackReturn@12
+
+    /* Save callback return value */
+    mov esi, eax
+
+    /* Raise status */
+StatusRaise:
+    push esi
+    call _RtlRaiseStatus@4
+    jmp StatusRaise
+    ret 12
+
+
+PUBLIC _KiRaiseUserExceptionDispatcher@0
+_KiRaiseUserExceptionDispatcher@0:
+
+    /* Setup stack for EXCEPTION_RECORD */
+    push ebp
+    mov ebp, esp
+    sub esp, EXCEPTION_RECORD_LENGTH
+
+    /* Fill out the record */
+    mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], eax
+    mov eax, [fs:KPCR_TEB]
+    mov eax, [eax+TEB_EXCEPTION_CODE]
+    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
+    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], 0
+    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], 0
+    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
+
+    /* Raise the exception */
+    push esp
+    call _RtlRaiseException@4
+
+    /* Return exception code */
+    mov eax, [esp+EXCEPTION_RECORD_EXCEPTION_CODE]
+    mov esp, ebp
+    pop ebp
+    ret
+
+
+PUBLIC _KiUserExceptionDispatcher@8
+.PROC KiUserExceptionDispatcher@8
+    FPO 0, 0, 0, 0, 0, FRAME_FPO
+
+    /* Clear direction flag */
+    cld
+
+    /* Save the Context and Exception Records */
+    mov ecx, [esp+4]
+    mov ebx, [esp]
+
+    /* Dispatch the exception */
+    push ecx
+    push ebx
+    call _RtlDispatchException@8
+
+    /* Check for success */
+    or al, al
+    jz RaiseException
+
+    /* Pop off the records */
+    pop ebx
+    pop ecx
+
+    /* We're fine, continue execution */
+    push 0
+    push ecx
+    call _ZwContinue@8
+
+    /* Exit */
+    jmp Exit
+
+RaiseException:
+    /* Pop off the records */
+    pop ebx
+    pop ecx
+
+    /* Raise the exception */
+    push 0
+    push ecx
+    push ebx
+    call _ZwRaiseException@12
+
+Exit:
+    /* Allocate space for the nested exception record */
+    add esp, -SIZEOF_EXCEPTION_RECORD
+
+    /* Set it up */
+    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
+    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_NONCONTINUABLE
+    mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], ebx
+    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
+
+    /* Raise the exception */
+    push esp
+    call _RtlRaiseException@4
+    ret 8
+
+.ENDP KiUserExceptionDispatcher@8
+
+PUBLIC _KiIntSystemCall@0
+.PROC KiIntSystemCall@0
+    FPO 0, 0, 0, 0, 0, FRAME_FPO
+
+    /* Set stack in EDX and do the interrupt */
+    lea edx, [esp+8]
+    int HEX(2E)
+
+    /* Return to caller */
+    ret
+
+.ENDP KiIntSystemCall@0
+
+PUBLIC _KiFastSystemCall@0
+.PROC KiFastSystemCall@0
+    FPO 0, 0, 0, 0, 0, FRAME_FPO
+
+    /* Put ESP in EDX and do the SYSENTER */
+    mov edx, esp
+    sysenter
+
+.ENDP KiFastSystemCall@0
+
+PUBLIC _KiFastSystemCallRet@0
+.PROC KiFastSystemCallRet@0
+    FPO 0, 0, 0, 0, 0, FRAME_FPO
+
+    /* Just return to caller */
+    ret
+
+.ENDP KiFastSystemCallRet@0
+
+PUBLIC _RtlpGetStackLimits@8
+_RtlpGetStackLimits@8:
+
+    /* Get the stack limits */
+    mov eax, [fs:TEB_STACK_LIMIT]
+    mov ecx, [fs:TEB_STACK_BASE]
+
+    /* Return them */
+    mov edx, [esp+4]
+    mov [edx], eax
+    mov edx, [esp+8]
+    mov [edx], ecx
+
+    /* return */
+    ret 8
+
+END