1/*
2            Copyright Oliver Kowalke 2009.
3            Copyright Thomas Sailer 2013.
4   Distributed under the Boost Software License, Version 1.0.
5      (See accompanying file LICENSE_1_0.txt or copy at
6            http://www.boost.org/LICENSE_1_0.txt)
7*/
8
9/********************************************************************
10  ---------------------------------------------------------------------------------
11  |    0    |    1    |    2    |    3    |    4    |    5    |    6    |    7    |
12  ---------------------------------------------------------------------------------
13  |    0h   |   04h   |   08h   |   0ch   |   010h  |   014h  |   018h  |   01ch  |
14  ---------------------------------------------------------------------------------
15  | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo|  limit  |   base  |  fc_seh |   EDI   |
16  ---------------------------------------------------------------------------------
17  ---------------------------------------------------------------------------------
18  |    8    |    9    |   10    |    11   |    12   |    13   |    14   |    15   |
19  ---------------------------------------------------------------------------------
20  |   020h  |  024h   |  028h   |   02ch  |   030h  |   034h  |   038h  |   03ch  |
21  ---------------------------------------------------------------------------------
22  |   ESI   |   EBX   |   EBP   |   EIP   |   EXIT  |         | SEH NXT |SEH HNDLR|
23  ---------------------------------------------------------------------------------
24*******************************************************************/
25
26.file	"make_i386_ms_pe_gas.asm"
27.text
28.p2align 4,,15
29.globl	_make_fcontext
30.def	_make_fcontext;	.scl	2;	.type	32;	.endef
31_make_fcontext:
32    /* first arg of make_fcontext() == top of context-stack */
33    movl  0x04(%esp), %eax
34
35    /* reserve space for first argument of context-function */
36    /* EAX might already point to a 16byte border */
37    leal  -0x08(%eax), %eax
38
39    /* shift address in EAX to lower 16 byte boundary */
40    andl  $-16, %eax
41
42    /* reserve space for context-data on context-stack */
43    /* size for fc_mxcsr .. EIP + return-address for context-function */
44    /* on context-function entry: (ESP -0x4) % 8 == 0 */
45    /* additional space is required for SEH */
46    leal  -0x3c(%eax), %eax
47
48    /* first arg of make_fcontext() == top of context-stack */
49    movl  0x04(%esp), %ecx
50    /* save top address of context stack as 'base' */
51    movl  %ecx, 0x14(%eax)
52    /* second arg of make_fcontext() == size of context-stack */
53    movl  0x08(%esp), %edx
54    /* negate stack size for LEA instruction (== substraction) */
55    negl  %edx
56    /* compute bottom address of context stack (limit) */
57    leal  (%ecx,%edx), %ecx
58    /* save bottom address of context-stack as 'limit' */
59    movl  %ecx, 0x10(%eax)
60    /* save bottom address of context-stack as 'dealloction stack' */
61    movl  %ecx, 0xc(%eax)
62
63    /* third arg of make_fcontext() == address of context-function */
64    movl  0xc(%esp), %ecx
65    movl  %ecx, 0x2c(%eax)
66
67    /* save MMX control- and status-word */
68    stmxcsr  (%eax)
69    /* save x87 control-word */
70    fnstcw  0x04(%eax)
71
72    /* compute abs address of label finish */
73    movl  $finish, %ecx
74    /* save address of finish as return-address for context-function */
75    /* will be entered after context-function returns */
76    movl  %ecx, 0x30(%eax)
77
78    /* traverse current seh chain to get the last exception handler installed by Windows */
79    /* note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default */
80    /* the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler */
81    /* at its end by RaiseException all seh andlers are disregarded if not present and the */
82    /* program is aborted */
83    /* load NT_TIB into ECX */
84    movl  %fs:(0x0), %ecx
85
86walk:
87    /* load 'next' member of current SEH into EDX */
88    movl  (%ecx), %edx
89    /* test if 'next' of current SEH is last (== 0xffffffff) */
90    incl  %edx
91    jz  found
92    decl  %edx
93    /* exchange content; ECX contains address of next SEH */
94    xchgl  %ecx, %edx
95    /* inspect next SEH */
96    jmp  walk
97
98found:
99    /* load 'handler' member of SEH == address of last SEH handler installed by Windows */
100    movl  0x04(%ecx), %ecx
101    /* save address in ECX as SEH handler for context */
102    movl  %ecx, 0x3c(%eax)
103    /* set ECX to -1 */
104    movl  $0xffffffff, %ecx
105    /* save ECX as next SEH item */
106    movl  %ecx, 0x38(%eax)
107    /* load address of next SEH item */
108    leal  0x38(%eax), %ecx
109    /* save next SEH */
110    movl  %ecx, 0x18(%eax)
111
112    /* return pointer to context-data */
113    ret
114
115finish:
116    /* ESP points to same address as ESP on entry of context function + 0x4 */
117    xorl  %eax, %eax
118    /* exit code is zero */
119    movl  %eax, (%esp)
120    /* exit application */
121    call  __exit
122    hlt
123
124.def	__exit;	.scl	2;	.type	32;	.endef  /* standard C library function */
125