; Listing6-2.asm
;
; A program that demonstrates protocols in MASM.

            option     casemap:none
	.nolist
            include    aoaTypes.inc
            include    aoaMacros.inc
            include    aoaClasses.inc
            include    aoalib.inc
            includelib aoalib.lib
	.list
            
            .const

; Program title:

             align  word
ttlStr       byte   "Listing 6-2", 0


protocol pro1
    virtual p1A
    virtual p2A
endpr pro1


protocol pro2, inherits( pro1 )
    virtual p3A
    virtual p4A
endpr pro2
            
            
; A sample class that uses a protocol.
; It adds one additional function that
; is not part of the protocol.

class  protoClass
            b       byte    ?
            a       byte    64 dup (?)
            c       byte    ?
            d       dword   ?
            virtual pcFunc
endc   protoClass     
 
            
; A second class that uses the proto123 protocol.


protocol pro1a, inherits( pro1 )
            override p1A, protoClass2$p1A
            override p2A, protoClass2$p2A
endpr pro1a



class protoClass2, inherits(protoClass)
             e      real4   ?
             
             supports pro1a
             
             virtual  pcFunc2
             override pcFunc, protoClass2$pcFunc1
endc  protoClass2
             
            
 
; Emit the VMTs for these classes.

            .const
            
            emitVMT protoClass     
            emitVMT protoClass2
            emitVMT pro1a     
            
            .data

pc          protoClass  {}
pc2         protoClass2 {}

            
            
            .code


;---------------------------------------------------
;
; Procedures for the protoClass class:

protoClass$create proc
                  push rcx
                  push rdx
                  
                  mov  ecx, sizeof protoClass
                  xor  edx, edx
                  lea  rdi, vmtAdrs(protoClass)
                  call generic$Class$Constructor
                  
                  pop  rdx
                  pop  rcx
                  ret
protoClass$create endp






protoClass$pcFunc proc
                  call print
                  byte "Inside protoClass$pcFunc"
                  byte nl, 0
                  ret
protoClass$pcFunc endp

        
;---------------------------------------------------
;
; Procedures for the protoClass2 class:

protoClass2$create proc
            push rcx
            push rdx

            mov  ecx, sizeof protoClass2
            xor  edx, edx
            lea  rdi, vmtAdrs(protoClass2)
            call generic$Class$Constructor

; Must initialize the VMT pointer for the
; pro1 protocol:

            lea  rdx, vmtAdrs(pro1a)
            mov  protoClass2@.vmtPtr(pro1a), rdx
            pop  rdx
            pop  rcx
            ret
protoClass2$create endp


protoClass2$pcFunc1 proc
                    call print
                    byte "Inside protoClass2$pcFunc1"
                    byte nl, 0
                    ret
protoClass2$pcFunc1 endp


protoClass2$pcFunc2 proc
                    call print
                    byte "Inside protoClass2$pcFunc2"
                    byte nl, 0
                    ret
protoClass2$pcFunc2 endp


protoClass2$p1A proc
                call print
                byte "Inside protoClass2$p1a"
                byte nl, 0
                ret
protoClass2$p1A endp


protoClass2$p2A proc
                call print
                byte "Inside protoClass2$p2a"
                byte nl, 0
                ret
protoClass2$p2A endp

              
 
        
;--------------------------------------------------
;
; Here is the main assembly language function.

            
            public  asmMain
asmMain     proc
saveRBX     textequ <[rbp-8]>
saveRSI     textequ <[rbp-16]>
saveRDI     textequ <[rbp-24]>
            
            push    rbp
            mov     rbp, rsp
            sub     rsp, 128
            and     rsp, -16
            
            mov     saveRBX, rbx
            mov     saveRSI, rsi
            mov     saveRDI, rdi

            
; Initialize the pc/pc2 class objects:

            lea     rsi, pc
            call    protoClass$create
            
            lea     rsi, pc2
            call    protoClass2$create
            
            
; Directly call the methods in pc, just to demonstrate
; that they work:

            call    print
            byte    "Calling protoClass.pcFunc", nl, 0
            inv     protoClass, pcFunc
            
            call    print
            byte    "Calling protoClass2.pcFunc", nl, 0
            inv     protoClass2, pcFunc
            
            call    print
            byte    "Calling protoClass2.pcFunc2", nl, 0
            inv     protoClass2, pcFunc2
            
            call    print
            byte    nl
            byte    "Calling protoClass.p1A/P2A"
            byte    "functions", nl, 0

            inv     pro1, p1A, rsi, protoClass2@.vmtPtr(pro1a)  
            inv     pro1, p2A, rsi, protoClass2@.vmtPtr(pro1a)  
                            
                        
            mov     rbx, saveRBX
            mov     rsi, saveRSI
            mov     rdi, saveRDI
            leave
            ret     ;Returns to caller
        
asmMain     endp
            end