blob: 7084b44c5d7a0cd2c41fa86b3b80b44f6a3854be [file] [log] [blame]
; Copyright Oliver Kowalke 2009.
; Distributed under the Boost Software License, Version 1.0.
; (See accompanying file LICENSE_1_0.txt or copy at
; http://www.boost.org/LICENSE_1_0.txt)
; ---------------------------------------------------------------------------------
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
; ---------------------------------------------------------------------------------
; | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch |
; ---------------------------------------------------------------------------------
; | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI |
; ---------------------------------------------------------------------------------
; ---------------------------------------------------------------------------------
; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
; ---------------------------------------------------------------------------------
; | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch |
; ---------------------------------------------------------------------------------
; | ESI | EBX | EBP | EIP | EXIT | | SEH NXT |SEH HNDLR|
; ---------------------------------------------------------------------------------
.386
.XMM
.model flat, c
; standard C library function
_exit PROTO, value:SDWORD
.code
make_fcontext PROC EXPORT
; first arg of make_fcontext() == top of context-stack
mov eax, [esp+04h]
; reserve space for first argument of context-function
; rax might already point to a 16byte border
lea eax, [eax-08h]
; shift address in EAX to lower 16 byte boundary
and eax, -16
; reserve space for context-data on context-stack
; size for fc_mxcsr .. EIP + return-address for context-function
; on context-function entry: (ESP -0x4) % 8 == 0
; additional space is required for SEH
lea eax, [eax-03ch]
; first arg of make_fcontext() == top of context-stack
mov ecx, [esp+04h]
; save top address of context stack as 'base'
mov [eax+014h], ecx
; second arg of make_fcontext() == size of context-stack
mov edx, [esp+08h]
; negate stack size for LEA instruction (== substraction)
neg edx
; compute bottom address of context stack (limit)
lea ecx, [ecx+edx]
; save bottom address of context-stack as 'limit'
mov [eax+010h], ecx
; save bottom address of context-stack as 'dealloction stack'
mov [eax+0ch], ecx
; third arg of make_fcontext() == address of context-function
mov ecx, [esp+0ch]
mov [eax+02ch], ecx
; save MMX control- and status-word
stmxcsr [eax]
; save x87 control-word
fnstcw [eax+04h]
; compute abs address of label finish
mov ecx, finish
; save address of finish as return-address for context-function
; will be entered after context-function returns
mov [eax+030h], ecx
; traverse current seh chain to get the last exception handler installed by Windows
; note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default
; the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler
; at its end by RaiseException all seh-handlers are disregarded if not present and the
; program is aborted
assume fs:nothing
; load NT_TIB into ECX
mov ecx, fs:[0h]
assume fs:error
walk:
; load 'next' member of current SEH into EDX
mov edx, [ecx]
; test if 'next' of current SEH is last (== 0xffffffff)
inc edx
jz found
dec edx
; exchange content; ECX contains address of next SEH
xchg edx, ecx
; inspect next SEH
jmp walk
found:
; load 'handler' member of SEH == address of last SEH handler installed by Windows
mov ecx, [ecx+04h]
; save address in ECX as SEH handler for context
mov [eax+03ch], ecx
; set ECX to -1
mov ecx, 0ffffffffh
; save ECX as next SEH item
mov [eax+038h], ecx
; load address of next SEH item
lea ecx, [eax+038h]
; save next SEH
mov [eax+018h], ecx
ret ; return pointer to context-data
finish:
; exit code is zero
xor eax, eax
mov [esp], eax
; exit application
call _exit
hlt
make_fcontext ENDP
END