/******************************************************* * File: ArrayFnsSearch.m * Date: Nov. 22, 2021 * Author: Dr. Spiegel * Computer: Acad * Execute: ArrayFnsSearch * Purpose: to demonstrate using functions to read, search, and print an array * Shows how arrays are passed in assembled C/C++, * with the address and count passed in the standard registers. * * It illustrates how components of the arrays are referenced * efficiently and demonstrates offsets via an index search * * This program will define an array (size 10) stored in the stack * and use a two-exit loop in a function to read in *up to* ten values and * another function and another loop to print them out. * * It uses minimal code, optimizing several things *******************************************************/ define(count,%r14) # Counter register define(index,%r15) define(baseAdrs,%r13) # Array base address to pass to functions define(srchKey,%r12) .global main main: push %rbp # keep stack aligned # Make room for 10 ints on the stack subq $48, %rsp # It must also remain divisible by 16 movq %rsp, baseAdrs movq %rsp, %rdi # Pass the base address call getList movq %rax, count # getList returns number of elements read movq %rsp, %rdi # Pass the base address movq count, %rsi # Pass the # elts call printList movq baseAdrs, %rdi # Pass the base Adrs movq count, %rsi # Pass the #elts pushq baseAdrs # Save the register pushq count # Save the register call searchList popq count # Restore the register popq baseAdrs # Restore the register done: addq $48, %rsp # Deallocate the array pop %rbp ret getList: pushq %rbx # We don't actually have to save these as they weren't in use, but if they were... pushq count # Save any value that might be in register count pushq baseAdrs # Save any value that might be in register baseAdrs # Note: pushq maintains stack alignment movq %rdi, baseAdrs # Copy parameter to 'local' register movq $0, count # Count # elts leaq prompt(%rip), %rdi # load format string to proper register call printf # print it loop: # Read a value leaq prompt2(%rip), %rdi # load format string to proper register call printf # print it # Read the int leaq fmt_in(%rip), %rdi # load format string leaq (baseAdrs,count,4), %rsi# set storage to address of elt on stack call scanf inc count # Counter up cmp $10,count # If equal, time to exit jz endRead # Return if 10 elts read # Did they enter ^D (eotext)? scanf returns #items read, unknown on ^D cmp $1,%rax je loop # If it was 1, go get next value dec count # On ^D didn't read value... must dec count endRead: movq count, %rax # Return the # elts popq baseAdrs # Restore the register popq count # Restore the register popq %rbp ret printList: pushq %rbp # We don't actually have to save these as they weren't in use, but if they were... pushq count # Save any value that might be in register count pushq index # Save any value that might be in register index pushq baseAdrs # Save any value that might be in register baseAdrs movq %rdi, baseAdrs # 1st parameter to 'safe' register movq %rsi, count # 2nd parameter movq $0, index # #elts is in count, %r15 is now counting print: leaq frmto(%rip),%rdi # Output format mov index,%rsi mov (baseAdrs,index,4),%rdx # Load value to print xor %rax,%rax call printf # Are we done? inc index # Inc counter cmp count,index # Equal to # elts? jl print # No? Print next value popq baseAdrs popq index # Restore value popq count # Restore value popq %rbp ret searchList: # Loop, getting search key. Call function to do actual search # Parameters: # Base address in %rdi # Number of records in %rsi # Store search key in local frame. pushq %rbp subq $16,%rsp # Tried allocating on 8 bytes and it crashed # Grab the parameters movq %rdi, baseAdrs movq %rsi, count keyLoop: # Prompt movq $srch, %rdi # load format string to proper register call printf # print it # Read search key leaq fmt_in(%rip), %rdi # load format string leaq (%rsp), %rsi # set storage to address of key in local frame call scanf # Did they enter ^D (eotext)? scanf returns #items read, unknown on ^D cmp $1,%rax jne endFind # If it was 1, get next search key # Pass search key to find function. # Won't pass or save registers (base address, count) that won't change movq (%rsp), srchKey # Load search key from memory call find # Look for it cmp $0,%rax # Check if found jge found # Go report index leaq srchNot(%rip), %rdi # Report failure jmp notFnd found: leaq srchFnd(%rip), %rdi movq %rax,%rdx # Will also print index where found notFnd: movq srchKey, %rsi # Print this no matter what call printf jmp keyLoop endFind: addq $16,%rsp popq %rbp ret find: # Search the array for the search key pushq %rbp movq $-1,index srchLoop: inc index cmp index,count # Did we run out of places to look? je srchFail # Put -1 in %rax and leave movq (baseAdrs,index,4),%rdx # Load array value to compare movq srchKey, %rcx # Same problem with values in upper part cmp %edx,%ecx # ZF if they match jnz srchLoop #This code is only reached if found movq index,%rax popq %rbp ret srchFail: movq $-1,%rax popq %rbp ret .data prompt: .asciz "Enter up to Ten Numbers \n" prompt2:.asciz "Enter Next Value (^d quits): " srch: .asciz "\nEnter Number to Search (^D to stop)>" srchFnd:.asciz "Value %d found in Index %d \n" srchNot:.asciz "Value %d not found \n" fmt_in: .asciz "%d" frmto: .asciz "\narray[%d] = %d"