CompOrg Spring 2008

IA32 Assembly Programming

Due Date: 2/28 by 11:59PM

You may not share code with anyone else, you must work alone!
Feel free to discuss the project with anyone, just make sure you don't share code in any form! You are expected to write all the code you submit (do not submit code generated by gcc!).

Assignment

This assignment involves the creation of some IA32 subroutines. You are given a description of the C interface to each subroutine (as a C function prototype) and you need to write IA32 assembly code. Feel free to look at code generated by gcc, but don't submit IA32 code generated by gcc! (You need to write these subroutines!).

You are to write IA32 assembly code (that can be compiled with gcc running on the CS BSD machines) for the C functions described below. It is essential that your functions follow the names and arguments described below (we will write code that calls your functions!).

Your function definitions will be linked with our main code, so you just need to write the code for the three functions listed below. Feel free to write other functions as well, the only requirement is that you include the functions listed below.

int pow(int x, int y): pow function (computes integer powers-of)

You need to write the function pow that returns the integer value of x raised to the yth power (xy). Both x and y are 32 bit integers.

Your function must return the correct value for any x, y for which the correct answer is representable as a 32 bit signed int. The parameter x may be negative, but y will always be a non-negative integer.

Below is the IA32 assembly framework for your function (feel free to use this as a starting point). This code includes the subroutine setup and termination code, and also gets the value of x and put's it in register %eax, and the value of y is put into register %edx.

NOTE: The code below saves and restores registers ebx, esi and edi, this means that you can use these registers for anything you want in your function. (According to the gcc register usage conventions, you can always use %eax, %ecx and %edx for anything you want.)

        .text
.globl pow
        .type   pow, @function
pow:
        pushl   %ebp
        movl    %esp, %ebp
        pushl	%ebx                    # save ebx
        pushl   %esi                    # save esi
        pushl   %edi                    # save edi
        movl	8(%ebp),%eax            # eax now holds x
        movl	12(%ebp),%edx           # edx now holds y

... your code goes here ...
... set eax to the return value before reaching leave ...

        popl    %edi                    # restore edi
        popl    %esi                    # restore esi
        popl    %ebx                    # restore ebx
        leave
        ret

We won't call your pow function with parameter values that result in a number that can't be represented in a 32 bit int, and we won't call with a negative value for y, so you do not need to include code that makes sure x and y are within any range of values. A value of 0 for x or y is possible!

void fib(int *a, int n): Creating a sequence of fibonacci numbers

You need to write the function fib that fills an array (a) with the first n fibonacci numbers. Each fibonacci numbers is defined as follows:

fib1 = 1

fib2 = 1

fibi = fibi-1 + fibi-2

Your function should put fib1 in a[0]. For example, the fist 7 fibbonaci numbers are: 1, 1, 2, 3, 5, 8, 13. Your function is passed a pointer (a) to the beginning of an array of ints, and a number n, the function should fill in the first n array elements with fibonacci numbers. You don't know ahead of time how many fibonacci numbers you are to generate. The memory for the array has already been allocated, so a is the address of an array of at least n*4 bytes (4 bytes for each int). Your function must not use any array elements beyond the nth (you have no idea if the array is any larger than n elements!).

Here is the IA32 function beginning and end, once again feel free to start with this. The code below puts a in register %eax and n in %edx. Note that the function has no return value, so it doesn't matter what is in %eax when the function returns - the function modifies the array.

NOTE: The code below saves and restores registers ebx, esi and edi, this means that you can use these registers for anything you want in your function.

.globl fib
        .type   fib, @function
fib:
        pushl   %ebp
        movl    %esp, %ebp
	pushl	%ebx                    # save ebx
	pushl   %esi			# save esi
	pushl   %edi                    # save edi
 
        movl   8(%ebp),%eax             # eax is a
        movl   12(%ebp),%edx            # edx is n

... your code goes here ...


fib_end:
        popl    %edi                    # restore edi
	popl    %esi                    # restore esi
	popl    %ebx			# restore ebx
	leave
        ret
void upcase(char *s): String to upper case

You need to write the function upcase that converts a C string to all upper case letters. The function is passed the address of a null terminated string and returns nothing, your function should modify the string itself. Your function should make sure that any alphabetic character in the string is converted to the upper-case alphabetic, so for example given the string "comporg 345", the function should convert it to "COMPORG 345".

Below is the IA32 function beginning and end, once again feel free to start with this. The code below puts s in register %eax. Note that the function has no return value, so it doesn't matter what is in %eax when the function returns - the function modifies the string in place.

NOTE: The code below saves and restores registers ebx, esi and edi, this means that you can use these registers for anything you want in your function.

        .text
.globl upcase
    .type   upcase, @function

upcase:
        pushl   %ebp
        movl    %esp, %ebp
	pushl	%ebx                    # save ebx
	pushl   %esi			# save esi
	pushl   %edi                    # save edi
        movl	8(%ebp),%eax            # eax now holds s

... your code goes here ...

        popl    %edi                    # restore edi
	popl    %esi                    # restore esi
	popl    %ebx			# restore ebx
        leave
        ret

NOTE: Keep in mind that when dealing with bytes (C char), you can use byte registers like %bl, %bh, %al, %ah, but remember that register %al is part of %eax.

Sample Test Code

Sample Test Code

We will be using our own main to test your functions, so you must not include a main in the assembly file you submit. Below is a sample main written in C that you can use as a starting point for testing your code. To combine this with your assembly code you can either:

  1. Use gcc -S main.c to generate main.s, then put this in the same file as the assembly code for your functions.

  2. If your three functions are defined in the file hw2.s, you can tell the compiler to build an executable like this:

    gcc -o hw2 hw2.s main.c
/* Sample main for testing hw2 functions */
#include <stdio.h>
#include <string.h>
 
/* prototypes so gcc can compile main properly */
 
int pow(int x, int y);
void fib(int *a, int n);
void upcase(char *s);
 
int main() {
  int i;
  char s[100];
  int arr[20];
 
  /* try calling the pow function */
  printf("Trying pow(3,4)\n");
  i = pow(3,4);
  printf("pow(3,4) is %d\n",i);
 
  /* now try calling fib */
  printf("Trying fib(10)\n");
  fib(arr,10);
  printf("fib(10) created the sequence ");
  for (i=0;i<9;i++) {
        printf("%d,",arr[i]);
  }
  printf("%d\n",arr[i]);
 
  /* testing upcase */
  strcpy(s,"Hello World");
  printf("Trying upcase(%s)\n",s);
  upcase(s);
  printf("Result is now %s\n",s);
   
  return(0);
}

The output produces by the above main code should look like this:

> ./hw2
Trying pow(3,4)
pow(3,4) is 81
Trying fib(10)
fib(10) created the sequence 1,1,2,3,5,8,13,21,34,55
Trying upcase(Hello World)
Result is now HELLO WORLD
Grading

Grades will be determined by testing your functions with various parameter values. We will only test your functions with reasonable parameter values so you don't need to include code in your functions that validates the parameters.

Each function is worth 1/3 of the grade.

HINTS/Suggestions: