# 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_foreach zap_foreach: # rbx: Address of the current element. # r12: Address of the element after the last input element. # r13: Size of each input element. # r14: Address of the function. # We're gonna use callee-saved registers for storing values so they don't get overwritten with each function call. # Push the callee-saved registers: pushq %rbx pushq %r12 pushq %r13 pushq %r14 # Move registers into place: movq %rdi,%rbx movq %rsi,%r13 movq %rcx,%r14 # Get the one-past-the-end address: movq %rdx,%r12 imulq %r13,%r12 # Calculate the array size in bytes (sz * num). We're using signed multiply because the equivalent using the unsigned instruction would use more instructions. addq %rbx,%r12 # Iterate through the array: .loop: # Check if we have reached the one-past-the-end address: cmpq %rbx,%r12 je .done # Call the provided function: movq %rbx,%rdi # Provide the current address to the function. call *%r14 # We don't need to save any registers for this as we only use callee-saved registers. # Continue to the next element: addq %r13,%rbx jmp .loop # Finish: .done: # Restore the callee-saved registers: popq %r14 popq %r13 popq %r12 popq %rbx ret