CompOrg Spring 2004 Lab

Lab #5 - Subroutines, strings and arrays

2/18/2004

This lab involves making changes to IA32 assembly language programs, compiling, testing and debugging the resulting code.

Exercise 1: factorial subroutine

Write an assembly language factorial subroutine. Here is C code and the corresponding assembly to get you started:


p1.s p1.c
	.file	"p1.c"
	.text
.globl factorial
	.type	factorial,@function
factorial:
	pushl	%ebp
	movl	%esp, %ebp
	movl	$0, %eax
	leave
	ret
.Lfe1:
	.size	factorial,.Lfe1-factorial
	.section	.rodata
.LC0:
	.string	"%d! = %d\n"
	.align 32
.LC1:
	.string	"You have to give me a number!\n"
	.text
.globl main
	.type	main,@function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	andl	$-16, %esp
	movl	$0, %eax
	subl	%eax, %esp
	cmpl	$1, 8(%ebp)
	jle	.L3
	subl	$12, %esp
	movl	12(%ebp), %eax
	addl	$4, %eax
	pushl	(%eax)
	call	atoi
	addl	$16, %esp
	movl	%eax, -4(%ebp)
	subl	$4, %esp
	subl	$8, %esp
	pushl	-4(%ebp)
	call	factorial
	addl	$12, %esp
	pushl	%eax
	pushl	-4(%ebp)
	pushl	$.LC0
	call	printf
	addl	$16, %esp
	jmp	.L4
.L3:
	subl	$12, %esp
	pushl	$.LC1
	call	printf
	addl	$16, %esp
.L4:
	movl	$1, %eax
	leave
	ret
.Lfe2:
	.size	main,.Lfe2-main

#include <stdio.h>

int factorial(int x) {
  return(0);  /* This needs to be written in assembly! */
}


int main(int argc, char **argv) {
  int num;
  if (argc>1) {
	num = atoi(argv[1]);
	printf("%d! = %d\n",num,factorial(num));
  } else {
	printf("You have to give me a number!\n");
  }
  return(1);
}

Exercise 2: Strings and a strlen subroutine

Write an assembly language subroutine that returns the length of a string. Some issues:

Below is some C code that might help you test your code (gcc -S to generate assembly):

p2.c
#include <stdio.h>

int mystrlen(char *s) {
  return(0); /* you need to write this in assembly */
}

int main(int argc, char **argv) {
  int num;
  if (argc>1) {
	printf("length is %d\n",mystrlen(argv[1]));
  } else {
	printf("You have to give me something!\n");
  }
  return(1);
}


Exercise 3: Arrays

Write an assembly language subroutine that returns the sum of all integers in an array of int. Some issues:

Below is some C code that might help you test your code (gcc -S to generate assembly):

p3.c
#include <stdio.h>

int asum(int *p,int len) {
  return(0); /* you need to write this in assembly */
}

int main(int argc, char **argv) {
  int nums[] = { 1,2,3,4,3,2,1 };
  printf("Sum  is %d\n",asum(nums,sizeof(nums) / sizeof(int)));
  return(1);
}


Exercise 4: Speed and code size

Write an assembly language subroutine that reverses an array of ints. Prizes awarded in two categories: speed and code size. Code size is measured as the number of instructions in the reverse subroutine (including all standard subroutine overhead).

Below is some test code. The numbers to beat (using the below test code on monte) are:

Code size:13 lines
User time:0.730 seconds (on monte)
p4.c
#include <stdio.h>

void reverse(int *p,int len) {
  /* write this in assembly */
}

#define SIZE 1000
#define LOOPS 1000000
  
/* expects either a 't or 'l' on the command line
   t runs a test (prints the array before and after)
   l runs a measureable loop 
*/
                   
int main(int argc, char **argv) {
  int nums[SIZE];
  int i;

  for (i=0;i<SIZE;i++) nums[i]=i;

  if (*argv[1] == 't') {
  	printf("Before: ");
	for (i=0;i<SIZE;i++)  printf("%d ",nums[i]);
	printf("\n");

	reverse(nums,SIZE);

	printf("After: ");
	for (i=0;i<SIZE;i++)  printf("%d ",nums[i]);
	printf("\n");
  } else if (*argv[1] == 'l') {
	for (i=0;i<LOOPS;i++) {
	  reverse(nums,SIZE);
	}
  } else {
	printf(" use t to test, l to loop\n");
  }
  return(1);
}