program sehtest;

{$mode objfpc}{$H+}
{$asmmode intel}

uses
  SEH, sysutils;


procedure foo2(foobaz: integer);
var
  x : integer;
begin
  x := 1 div foobaz;
  //PInteger(nil)^ := foobaz;
end;

procedure foo1(foobaz: integer);
var
  x : integer;
begin
  foo2(foobaz);
end;

procedure foo(foobaz: integer);
var
  x : integer;
begin
  foo1(foobaz);
end;



procedure test;
label
  __except, __finally;
begin
  writeln(IntToHex(PtrUInt(@__except), 8));

  // ****** TRY ****** (push the except address and ebp and then install SEH)
  asm
    lea eax, __except
    push eax
    push ebp
    push handler
    push fs:[0]
    mov fs:[0], esp
  end;
  // ****** TRY ******

  writeln('trying...');
  foo(0); // provoke exception somewhere deeper in the callstack
  goto __finally;

  __except:
  writeln('except');

  __finally:
  // ****** FINALLY ****** (undo the things done in try)
  asm
    pop eax
    mov fs:[0], eax
    pop eax // handler
    pop ebp
    pop eax // except label
  end;
  // ****** FINALLY ******

  writeln('finally');
end;

begin
  test;
end.
