__declspec(naked) int _call_function()
{
__asm {
PUSH EBP;//save ebp (used to address stack frame)
MOV EBP, ESP;//use EBP as stack frame pointer
SUB ESP, __LOCAL_SIZE;//make 16 dwords on stack for local data
;//**************** install handler and its ERR structure
PUSHAD;
PUSHFD;
//构造 _EXCEPTION_HXSTACK
PUSH EBP;//ERR+14h save ebp (being ebp at safe-place)
PUSH 0;//ERR+10h area for flags
PUSH 0;//ERR+0Ch information for handler
PUSH OFFSET SAFE_PLACE;//ERR+8h new eip at safe-place
;//PUSH _except_handler_new;//ERR+4h address of handler
PUSH OFFSET HANDLER
//PUSH FS:[0] ;//ERR+0h keep next ERR up the chain
//MOV FS:[0],ESP ;//point to ERR just made on the stack
mov eax, dword ptr fs : [00000000h];
push eax;
mov eax, esp;
mov dword ptr fs : [00000000h], eax;
mov ebx, 0x1254;
mov eax, 0;
mov[eax], 0
SAFE_PLACE:;//handler sets eip/esp/ebp for here
POP FS : [0];//restore next ERR up the chain
ADD ESP, 0x16;// sizeof _EXCEPTION_HXSTACK
POPFD;
POPAD;
MOV ESP, EBP;
POP EBP;
RET;
HANDLER:
PUSH EBP;
MOV EBP, ESP;
SUB ESP, __LOCAL_SIZE;
PUSH EBX;
PUSH EDI;
PUSH ESI;
MOV EBX, [EBP + 8];// get exception record in ebx
TEST[EBX + 4], 01h;// see if its a non - continuable exception
JNZ L5;// yes, so must not deal with it
TEST[EBX + 4], 02h;// see if its EH_UNWINDING(from Unwind)
JZ L2;// no
JMP L5;// must return 1 to go to next handler
L2:
PUSH 0;// return value(not used)
PUSH[EBP + 8h];// pointer to this exception record
PUSH OFFSET UN23;// code address for RtlUnwind to return
PUSH[EBP + 0Ch];// pointer to this ERR structure
CALL RtlUnwind;
UN23:
MOV ESI, [EBP + 10h];// get context record in esi
MOV EDX, [EBP + 0Ch];// get pointer to ERR structure
MOV[ESI + 0C4h], EDX;// use it as new esp
MOV EAX, [EDX + 8];// get safe place given in ERR structure
MOV[ESI + 0B8h], EAX;// insert new eip
MOV EAX, [EDX + 14h];// get ebp at safe place given in ERR
MOV[ESI + 0B4h], EAX;// insert new ebp
MOV EAX, 1;// get eax at safe place given in ERR
MOV[ESI + 0B0h], EAX;// insert new return value
XOR EAX, EAX;// reload context & return to system eax = 0
JMP L6;
L5:
MOV EAX, 1;// go to next handler - return eax = 1
L6:
POP ESI;
POP EDI;
POP EBX;
MOV ESP, EBP;
POP EBP;
RET;// ordinary return (no actual arguments)
}
}
int main() {
_call_function();
return 0;
}