; Listing9-1.asm ; ; A program that demonstrates a call-by-name ; parameter. option casemap:none .nolist include aoalib.inc include aoaProcs.inc include aoaTypes.inc includelib aoalib.lib .list .const ; Program title: align word ttlStr byte "Listing 9-1", 0 .code ; procedure zeroStorage( name array:integer, var index:integer ); parms zeroStorage, rbp, 16, \ array:thunk_t, \ index:qword zeroStorage proc push rbp mov rbp, rsp push rax push rbx push rcx push rdx ; Array is a thunk. Load the environment pointer ; into RCX (where the thunk expects it to be) so ; we can easily access it later. Note that the ; following code assumes that the thunk code ; (zeroStorage$array.procedure) does not ; change RCX (or RDX). mov rcx, zeroStorage$array.environment ; Assume index is a 32-bit integer ; ; for index := 0 to 10 ; ; Note that index is passed by reference, so we have ; to deference it whenever we want to use it. Load ; the address of index into RDX and keep it there ; so that dereferencing RDX is easy. mov rdx, zeroStorage$index mov dword ptr [rdx], 0 ;index forLp: call zeroStorage$array.procedure ;thunk ; Now RAX contains the address returned by the thunk ; (which happens to be the address of a[i] in the ; main program). Store a zero into that array element. mov dword ptr [rax], 0 ;Pointer to A[I] ; Increment the index variable (remember, it is passed ; by reference). inc dword ptr [rdx] ;index ; See if index (dereferenced) is greater than 10. If so, ; quit the loop; else repeat. cmp dword ptr [rdx], 10 ;index jbe forLp pop rdx pop rcx pop rbx pop rax pop rbp ret zeroStorage endp ;-------------------------------------------------- ; ; Here is the main assembly language function. public asmMain locals asmMain, i:dword, a:dword[11] asmMain proc push rbp mov rbp, rsp sub rsp, 80 ; Initialize a with non-zero values just to show ; that the pass by name parameter works: lea rcx, asmMain$a mov edx, 10 storeLp: mov [rcx+rdx*4], edx dec edx jnz storeLp ; Just pass the parameters on the stack lea rax, asmMain$i ;Pass i by reference mov [rsp+16], rax ; The thunk computes the address of a[i] and returns ; that address in RAX. It is passed the environment ; pointer (the pointer to asmMain's activation record) ; in the RCX register. Note: rather than copy RCX into ; RBP (and preserve RBP), this code just indexes off ; RCX into asmMain's activation record. ; ; Put the thunk on the stack: setTh (thunk_t ptr [rsp]) push rbx mov ebx, [rcx+asmMain$i$ofs] lea rax, [rcx+asmMain$a$ofs+rbx*4] pop rbx ret endTh call zeroStorage ; Print the contents of a to show that all the ; elements have been zeroed: call print byte "a: ", 0 lea rcx, asmMain$a mov r10d, 0 printLp: mov edx, [rcx+r10*4] call print byte "%d ", 0 inc r10d cmp r10d, 11 jb printLp call print byte nl, 0 leave ret asmMain endp end