; Listing7-5.asm
;
; A program that demonstrates handling
; an exception using the try/endtry
; macros.


            option     casemap:none
            .nolist
            include    aoalib.inc
            include    aoaExcepts.inc
            includelib aoalib.lib
            .list
            
            .const

; Program title:

             align  word
ttlStr       byte   "Listing 7-5", 0


            .code

            

; tstSEH-
;
; This procedure tests exception handling code in
; assembly language.


tstSEH      xproc   (filterProc(tstSEH), <>)
            
            local   endTryPtr:qword 
            local   shadowStorage[48]:byte

            try
                        
                call    print
                byte    "startTry: int 3 is next instr"
                byte    nl, 0
                
                int     3       ;Cause an exception
                
                call    print
                byte    "This should not print"
                byte    nl, 0
            
            exception(ex(brkpt))


                ; Here's the code that executes whenever 
                ; a breakpoint occurs in the protected 
                ; block.
                ;            
                ; Upon entry into this code, RAX contains 
                ; a pointer to the DispatcherContext 
                ; record. Print a couple of useful 
                ; values from that record:

                mov   edx, [rax].ExceptionRecord_t.ExceptionCode
                call  print
                byte  "Breakpoint encountered (0x%x)"
                byte  nl, 0
                
                
            finally
            
                ; Here's the finally code: 

                call    print
                byte    "Executed finally code", nl, 0
                        

            ; This is where the code exits the 
            ; protected loop.
 
            endtry
           
; Generate the epilog code (including ret) and end
; the procedure:

tstSEH      endxp()


        
;--------------------------------------------------
;
; Here is the main assembly language function.

            
            public  asmMain
            
; For the main assembly procedure, preserve all the 
; non-volatile registers. It would be cool to save  
; the XMM non-volatile registers, too, but there isn't 
; room in the prolog for them.
; 
; Had this code used a biased frame pointer (RBP) value, 
; it could have gotten away with saving them. Epilog 
; and prolog  macros don't allow that, however. So this 
; code preserves what it can (the general-purpose 64-bit 
; non-volatile registers).
            
asmMain     xproc   (frame,<rbx, rsi, rdi, r12, r13, r14, r15>)
            local   shadowStorage[56]:byte
            

; Call the procedure the demonstrates exception handling:

            call    print
            byte    "Calling tstSEH", nl, 0
            
; Call the procedure that raises an exception:

            call    tstSEH
            
            call    print
            byte    "Back from tstSEH", nl, 0
            
asmMain     endxp()
            end
