i dont use macro, just made it for this example.
    
  include 'win32a.inc'
  format PE console 4.0
macro __INSTALL_SEH {
    pushfd
    pushad
    push                __SEH ; our handler
    push                dword [fs:0] ; pointer to previous seh
    mov                 dword [fs:0],esp ; install it
}
macro __SEH_ROUTINE {
    jmp                 __NO_EXCEPTION
__SEH:
    mov                 eax,[ebp+8] ; pointer to exception code
    mov                 eax,[eax] ; read exception code
    mov                 [exception_code],eax
    cinvoke             itoa,eax,_exception,10h
    mov                 esp,[ebp-4] ; restore previous stack
    pop                 dword [fs:0] ; restore old handler
    add                 esp,4 ; get rid of our handler
    popad
    popfd
}
macro __END_SEH {
    jmp                 __EXCEPTION_HANDLED
__NO_EXCEPTION:
    pop                 dword [fs:0] ; no exceptions? restore old handler
    add                 esp,28h ; discard all PUSHes we made
__EXCEPTION_HANDLED:
}
section '.text' code readable executable
    __INSTALL_SEH
    int3 ; generate breakpoint exception
    invoke              MessageBox,0,_debugger,_seh,0
    __SEH_ROUTINE
    invoke              MessageBox,0,_exception,_seh,0
    __END_SEH
    xor                 eax,eax
    ret
section '.data' data readable writable
  exception_code dd 0
  _seh db 'seh',0
  _debugger db 'stop debugging or pass int3 exception to the program',0
  _exception rb 9
section '.idata' import data readable
  library ntdll,'NTDLL.DLL',\
          user32,'USER32.DLL'
  import ntdll,\
         itoa,'_itoa'
  import user32,\
         MessageBox,'MessageBoxA'
section '.reloc' fixups data readable discardable     
another example, skip over int3 instruction:
    
  include 'win32a.inc'
  format PE console 4.0
STATUS_BREAKPOINT = 80000003h
EXCEPTION_CONTINUE_SEARCH = 0
virtual at eax
  context:
    .ContextFlags  dd ?
    .Dr0           dd ?
    .Dr1           dd ?
    .Dr2           dd ?
    .Dr3           dd ?
    .Dr6           dd ?
    .Dr7           dd ?
    .ControlWord   dd ?
    .StatusWord    dd ?
    .TagWord       dd ?
    .ErrorOffset   dd ?
    .ErrorSelector dd ?
    .DataOffset    dd ?
    .DataSelector  dd ?
    .St0           dt ?
    .St1           dt ?
    .St2           dt ?
    .St3           dt ?
    .St4           dt ?
    .St5           dt ?
    .St6           dt ?
    .St7           dt ?
    .Cr0NpxState   dd ?
    .Gs            dd ?
    .Fs            dd ?
    .Es            dd ?
    .Ds            dd ?
    .Edi           dd ?
    .Esi           dd ?
    .Ebx           dd ?
    .Edx           dd ?
    .Ecx           dd ?
    .Eax           dd ?
    .Ebp           dd ?
    .Eip           dd ?
    .Cs            dd ?
    .EFlags        dd ?
    .Esp           dd ?
    .Ss            dd ?
end virtual
macro __INSTALL_SEH {
    pushfd
    pushad
    push                __SEH
    push                dword [fs:0]
    mov                 dword [fs:0],esp
}
macro __SEH_ROUTINE {
    jmp                 __NO_EXCEPTION
__SEH:
    mov                 eax,[ebp+8]
    mov                 eax,[eax]
    mov                 [exception_code],eax
    cmp                 eax,STATUS_BREAKPOINT
    jnz                 @F
    mov                 eax,[ebp+10h] ; pointer to context record
    inc                 [context.Eip] ; increase eip by one to skip int3
    mov                 eax,EXCEPTION_CONTINUE_SEARCH
    ret
@@:
    cinvoke             itoa,eax,_exception,10h
    mov                 esp,[ebp-4]
    pop                 dword [fs:0]
    add                 esp,4
    popad
    popfd
}
macro __END_SEH {
    jmp                 __EXCEPTION_HANDLED
__NO_EXCEPTION:
    pop                 dword [fs:0]
    add                 esp,28h
__EXCEPTION_HANDLED:
}
section '.text' code readable executable
    __INSTALL_SEH
    int3 ; generate breakpoint exception
    xor                 eax,eax
    mov                 [eax],eax ; generate access violation exception
    invoke              MessageBox,0,_debugger,_seh,0
    __SEH_ROUTINE
    invoke              MessageBox,0,_exception,_seh,0
    __END_SEH
    xor                 eax,eax
    ret
section '.data' data readable writable
  exception_code dd 0
  _seh db 'seh',0
  _debugger db 'stop debugging or pass int3/access violation exceptions to the program',0
  _exception rb 9
section '.idata' import data readable
  library ntdll,'NTDLL.DLL',\
          user32,'USER32.DLL'
  import ntdll,\
         itoa,'_itoa'
  import user32,\
         MessageBox,'MessageBoxA'
section '.reloc' fixups data readable discardable     
side notes:
- size of context record is increased on windows version => XP, to include a snapshot of xmm registers and other interesting stuff. (i did not include them here)
- ignore microsoft's description about EXCEPTION_CONTINUE_SEARCH, the meaning of EXCEPTION_CONTINUE_SEARCH changes based on the context (top-leve-filter-function vs SEH vs VEH).