o     SFN  .

; Routine() -> ... -> Notify().

Initialize:
Graph = CreateGraph(@Routine, NL = 1)
-
Notify:
    Frame:PSTACK_FRAME
    Frame = rEbp
    Do
       if CheckIpBelongToGraph(Graph, Frame.Ip)
       Tls = AllocateTls()
       Tls.Ip = Frame.Ip
       Frame.Ip = @2ndDispatch()
       End
       endif
       Frame = Frame.Next
    Loop END_OF_CHAIN

2ndDispatch:
    Payload()
    Ip = Tls.Ip
    FreeTls(Tls)
    Jmp Ip

;			~
o     SFN  .
o   ,     .

; Routine() -> ... -> Notify().

Initialize:
   CreateGraph(@Routine, @ParseCallback)
-
ParseCallback(CurrentEntry:PGRAPH_ENTRY, CallList:PCALL_ENTRY):
   if CurrentEntry.Ip = TargetIp
      Graph = CallList[0].BranchLink
-
Notify:
    Frame:PSTACK_FRAME
    Frame = rEbp
    Do
       if CheckIpBelongToGraph(Graph, Frame.Ip)
       Tls = AllocateTls()
       Tls.Ip = Frame.Ip
       Frame.Ip = @2ndDispatch()
       End
       endif
       Frame = Frame.Next
    Loop END_OF_CHAIN

2ndDispatch:
    Payload()
    Ip = Tls.Ip
    FreeTls(Tls)
    Jmp Ip

;			~
o    .,    .

Initialize:
   CreateGraph(@Routine, @ParseCallback)
-
ParseCallback(CurrentEntry:PGRAPH_ENTRY, CallList:PCALL_ENTRY):
   if CurrentEntry.Ip = TargetIp
      Ip = CallList[0].Address + LDE(CallList[0].Address)
      ; Ip = CallList[0].Flink.Address
-
Notify:
    Frame:PSTACK_FRAME
    Frame = rEbp
    Do
       if Frame.Ip = Ip
       Tls = AllocateTls()
       Tls.Ip = Frame.Ip
       Frame.Ip = @2ndDispatch()
       End
       endif
       Frame = Frame.Next
    Loop END_OF_CHAIN

2ndDispatch:
    Payload()
    Ip = Tls.Ip
    FreeTls(Tls)
    Jmp Ip

;			~
o      .

    Do
    ENTRY.ACCESSED_MASK_FLAG -> 0
    Loop EOL
;			~
o   .
    if ENTRY.SEPARATE_MACRO_FLAG
       Size = 0
       Do
          Callback()
          Size = Size + LDE(ENTRY.Ip + Size)
       Loop Size < ENTRY.Size
    else
       Callback()
    endif

;			~
o   .

	Size = 0
	Do
	if ENTRY.Type = TYPE_LINE
	   Size = Size + ENTRY.Size
	else
	   Size = Size + LDE(ENTRY.Ip)
	endif
	Loop END_OF_CHAIN

;			~
o     .

PARSE_CALLBACK_ROUTINE(GE:PGRAPH_ENTRY, CallList:PCALL_ENTRY):
   if GE.Type = TYPE_CALL
      if GE.BranchAddress = @DbgPrint()
         GE = GE.Blink
         if GE.Type = TYPE_LINE
            if BYTE[GE.Address] = 0x68
               Message = DWORD[GE.Address + 1]
                  if StrCmp(TargetMessage, Message)
                     Routine = CallList[0]
;			~