/******************************************************* * File: ArrayFnsGnu.m * Date: Nov. 12, 2021 * Author: DSS * Computer: KUNET suns * Execute: ArrayFnsGnu * Purpose: to demonstrate using functions to read 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 integer 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 .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, %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 done: addq $48, %rsp # Deallocate the array (not critical) 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 loop: # Read a value leaq prompt(%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, -1 on ^D cmp $1,%rax je loop # If it was 1, go get next value dec count endRead: movq count, %rax # Return the # elts popq baseAdrs popq count # Restore value popq %rbx ret printList: 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 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 %rbx ret .data prompt: .asciz "enter up to ten numbers (^D quits): " fmt_in: .asciz "%d" frmto: .asciz "\narray[%d] = %d"