#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <excpt.h>

#define EXCEPTION_DISPOSITION int

void *INITIAL_ESP;
void *INITIAL_EBP;
void *INITIAL_HANDLER;

void *RESTORED_ESP;
void *RESTORED_EBP;
void *RESTORED_HANDLER;

int main()
{
    __asm__ __volatile__ (
             "movl %%esp, %0" "\n\t" : "=r" (INITIAL_ESP) );
    __asm__ __volatile__ (
             "movl %%ebp, %0" "\n\t" : "=r" (INITIAL_EBP) );
    __asm__ __volatile__ (
             "movl %%fs:0, %0" "\n\t" : "=r" (INITIAL_HANDLER) );

    __asm__ __volatile__ (
             "pushl %ebp" "\n\t"
             "pushl $__except_handler" "\n\t"
             "pushl %fs:0" "\n\t"
             "movl  %esp, %fs:0");

    *(PDWORD) 0 = 0;

    __asm__ __volatile__ (
             "main_reentry:" "\n\t"
             "movl %fs:0, %eax" "\n\t"
             "movl 0x8(%eax), %esp" "\n\t"
             "movl (%esp), %eax" "\n\t"
             "movl %eax, %fs:0" "\n\t"
             "movl 0x8(%esp), %ebp" "\n\t"
             "add  $12, %esp");

    __asm__ __volatile__ (
             "movl %%esp, %0" "\n\t" : "=r" (RESTORED_ESP) );
    __asm__ __volatile__ (
             "movl %%ebp, %0" "\n\t" : "=r" (RESTORED_EBP) );
    __asm__ __volatile__ (
             "movl %%fs:0, %0" "\n\t" : "=r" (RESTORED_HANDLER) );

    if (INITIAL_ESP != RESTORED_ESP)
        exit(-1);
    if (INITIAL_EBP != RESTORED_EBP)
        exit(-1);
    if (INITIAL_HANDLER != RESTORED_HANDLER)
        exit(-1);

    printf( "Everything gonna be alright ...\n" );
    return 0;
}

__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
_except_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void * EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void * DispatcherContext )
{
    __asm__ __volatile__ (
             "jmp main_reentry");
    return 0; /* Function does not return */
}

