CompOrg Fall 2005

IA32 Assembly Programming

Due Date: 10/13 (by 11:55PM) Now Due 10/17 by 11:55PM
Submit using WebCT: assignment HW2

Late Penalty: 25% per day. No submissions will be accepted after at 10/21 11:55PM.

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.


integer pow function (computes integer powers-of).

int pow(int x, int y); 

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!


Reversing a string in place

void reverse(char *s); 

You need to write the function reverse that reverses the order of bytes in an ASCII (null terminated) string that starts at the address specified.

Here 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 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 reverse
        .type   reverse, @function
reverse:
        pushl   %ebp
        movl    %esp, %ebp
        pushl	%ebx                    # save ebx
        pushl   %esi                    # save esi
        pushl   %edi                    # save edi
 
        movl   8(%ebp),%eax             # eax is s

... your code goes here ...


reverse_end:
        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.


Searching an array for a specific value

int count_elem(int *a, int n, int x); 

You need to write the function count_elem that returns the number of array elements (in array a) whose value is the same as x. The parameter n is the number of elements in the array (and a is the starting address of the array).

Your function should return 0 if it doesn't find any elements that match x, or if the size of the array (n) is 0.

Keep in mind that each array element is 4 bytes!

Once again, below is some code to get you started:

.globl count_elem
        .type   count_elem, @function
count_elem:
        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),%ebx            # ebx is n
        movl   16(%ebp),%ecx            # ecx is x

... your code goes here ...


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



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>

void reverse(char *);
int pow (int,int);
int count_elem(int*,int,int);

int main() {
  char s[100];
  unsigned int i;
  int a[] = {1,3,2,1,4,0,-3,1,2,4};

  /* Try reverse */
  strcpy(s,"Hello World");
  printf("Reverse(%s) is ",s);
  reverse(s);
  printf("%s\n",s);
  reverse(s);
  printf("Reverse again give %s\n",s);

  /* Try pow */

  for (i=0;i<10;i+=2) {
	printf("pow(3,%d) = %d\n",i,pow(3,i));
  }

  /* Try count_elem */
  printf("Array is [ ");
  for (i=0;i<sizeof(a)/4;i++) 
	printf("%d ",a[i]);
  printf("]\n");
  for (i=0;i<4;i++) 
	printf("number of %ds is %d\n",i,count_elem(a,sizeof(a)/4,i));
  return(0);
}

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

> ./hw2
Reverse(Hello World) is dlroW olleH
Reverse again give Hello World
pow(3,0) = 1
pow(3,2) = 9
pow(3,4) = 81
pow(3,6) = 729
pow(3,8) = 6561
Array is [ 1 3 2 1 4 0 -3 1 2 4 ]
number of 0s is 1
number of 1s is 3
number of 2s is 2
number of 3s is 1
How to submit

Submission of your homework is done using WebCT (webct.rpi.edu). Once you log in to WebCT and access the CompOrg site, you should click on assignments, then select HW2. Upload your hw1.s file to webct. Do not submit a file that includes a main function! (we will write our own test program).

If there is anything special about your code (for example if it doesn't work for all inputs, or only includes one of the two functions), put this information in a file named README and submit this as well. Feel free to put anything else you want in your README file (was this hard? did you learn anything?, etc...).

Don't send compiled code, only send your assembly program!

We will be testing on monica.cs.rpi.edu, make sure your code will work on monica!

Your code must be commented!

Multiple Submissions: You can resubmit as many times as you want, WebCT will make sure we get the last file you submit.

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: