Lab 6: Solutions¶
sum.c¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | /**
* sum.c
*
* Demonstrates how to send an int array and a double array
* to asm files to process.
*
* Return the summation of the values in the array
* double sum_double(double[] array, int length)
* int sum_int(int[] array, int length)
*
*/
#include <stdio.h>
// Prototypes
int sum_int(int *, int);
double sum_double(double *, int);
int main()
{
// result = 210; array_size = 16
int array_int[] = {11, 22, 33, 44, 55, 35, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
// Determine size of the int array
int size_array_int = sizeof(array_int) / sizeof(int);
printf(" int values: ");
// print array values
for (int i = 0; i < size_array_int; i++)
{
printf(" %d,", array_int[i]);
}
int sum_i = sum_int(array_int, size_array_int);
printf("\n size: %d; sum: %i", size_array_int, sum_i);
printf("\n");
//-------------------------------------
// Double sum
// result = 23.331000; array_size = 6
double array_double[] = {1.111, 2.222, 3.333, 4.444, 5.555, 6.666};
// Determine size of the double array
int size_array_double = sizeof(array_double) / sizeof(double);
printf(" double values: ");
// print array values
for (int i = 0; i < size_array_double; i++)
{
printf(" %lf,", array_double[i]);
}
double sum_d = sum_double(array_double, size_array_double);
printf("\n size: %d; sum: %lf", size_array_double, sum_d);
printf("\n");
return 0;
}
|
sum_int.asm¶
; ----------------------------------------------------------------------------
; sum_int.asm
;
; NASM implementation of a function that returns the sum of all the elements
; in an int array. The function has prototype:
;
; int sum_int(int[], int length)
;
; arg1: A pointer to an array of integers
; arg2: A integer value containing the the length of the array.
; ----------------------------------------------------------------------------
global sum_int
segment .data
segment .bss
returnvalue resd 1 ; place in memory for the return value
segment .text
sum_int:
; 1. Initialize stack pointers
push ebp ; save caller's EBP value
mov ebp, esp ; set EBP to current pointer
; sub esp, N ; reserve X=4*N bytes for N local vars
pusha ; save all (including new EBP)
; 2. Get arg data
mov edx, [ebp+8] ; address of argument (array)
mov ecx, [ebp+12] ; length of array
; 3. Do the work!
mov eax, 0 ; initialize the sum and return value
cmp ecx, 0 ; guard against non-positive lengths
jle done ; exit if length <= 0
next:
add eax, [edx] ; [edx] contains the current value in the array add to eax
add edx, 4 ; move to next array element
; 4 == sizeof(int); int data type has a size of 4.
dec ecx ; count down
jnz next ; if not done counting, continue
done:
; 4. Clean up and then exit
mov [returnvalue], eax ; save return value in memory
popa ; restore all (including new EBP)
mov eax, [returnvalue] ; retrieve the saves return value
mov esp, ebp ; remove space for local vars
pop ebp; ; Return caller's EBP value
ret ; return eax (aex contains the value of the stack pointer)
sum_double.asm. Double summation changes are highlighted¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | ; ----------------------------------------------------------------------------
; sum_double.asm
;
; NASM implementation of a function that returns the sum of all the elements
; in a floating-point array. The function has prototype:
;
; double sum_double(double[], int length)
;
; arg1: A pointer to an array of floating points
; arg2: A integer value containing the the length of the array.
; ----------------------------------------------------------------------------
global sum_double
segment .data
segment .bss
; returnvalue resd 1 ; (not needed for storing the double total)
segment .text
sum_double:
; 1. Initialize stack pointers
push ebp ; save caller's EBP value
mov ebp, esp ; set EBP to current pointer
; sub esp, N ; reserve X=4*N bytes for N local vars
pusha ; save all (including new EBP)
; 2. Get arg data
mov edx, [ebp+8] ; address of argument (array)
mov ecx, [ebp+12] ; length of array
; 3. Do the work!
fldz ; initialize ST0 to 0.0
cmp ecx, 0 ; guard against non-positive lengths
jle done ; exit if length <= 0
next:
fadd qword [edx] ; ST0 += [edx]
add edx, 8 ; move to next array element
; 8 == sizeof(double); double data type has a size of 8.
dec ecx ; count down
jnz next ; if not done counting, continue
done:
; 4. Clean up and then exit
; mov [returnvalue], eax ; (not needed for storing the double total)
popa ; restore all (including new EBP)
; mov eax, [returnvalue] ; (not needed for storing the double total)
mov esp, ebp ; remove space for local vars
pop ebp; ; Return caller's EBP value
ret ; return value already in st0
|
Makefile for summation project¶
# compiles the project files (sum.asm)
# Compiles dependencies if they are not up to date
sum: sum_int.o sum_double.o sum.o
@echo "Building sum"
@gcc -m32 sum.o sum_int.o sum_double.o -o sum
./sum
# Build sum_int.asm
sum_int.o:
@nasm -f elf -d ELF_TYPE sum_int.asm -o sum_int.o
# Build sum_double.asm
sum_double.o:
@nasm -f elf -d ELF_TYPE sum_double.asm -o sum_double.o
# Build sum.c
sum.o:
@gcc -m32 -c sum.c -o sum.o
# Clean up and then rebuild all
all: clean sum
# Removes all .o and temporary files
clean:
@echo "Cleaning up..."
@rm -f *.o
@rm -f sum
References: