# Copyright 2022 Gabriel Jensen. # This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. # If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. .globl zap_memcnt zap_memcnt: # Address of the current element: #define addr %rbx # Address of the element after the last input element: #define afterbuf %r12 # Size of each input element: #define sz %r13 # Address of the function: #define fn %r14 # Count: #define cnt %r15 # Push the callee-saved registers: pushq addr pushq afterbuf pushq sz pushq fn pushq cnt # Move registers into place: movq %rdi,addr movq %rsi,sz movq %rdx,afterbuf movq %rcx,fn # Get the one-past-the-end address: imulq sz,afterbuf # afterbuf *= sz addq addr,afterbuf # afterbuf += addr movq $0x0,cnt # cnt = 0x0 # Iterate through the array: .loop: # Check if we have reached the one-past-the-end address: cmpq addr,afterbuf # if (addr == afterbuf) je .done # goto done # Call the provided function: movq addr,%rdi call *fn # fn(addr) # Check the return value of the function: testb %al,%al # if (fn(addr) == zap_false) jz .skip # goto skip incq cnt # ++cnt # Skip the incrementation: .skip: # Continue to the next element: addq sz,addr # addr += sz jmp .loop # goto loop # Finish: .done: # Move count into return register: movq cnt,%rax # Restore the callee-saved registers: popq cnt popq fn popq sz popq afterbuf popq addr ret # return cnt