| CompOrg Spring 2008 |
|   CompOrg Home   |   Assignment   |   pow()   |   fib()   |   upcase()   |   Sample Test Code   |   Grading   |   Hints |
| 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.)
|
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.
|
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.
|
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 |
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:
Use gcc -S main.c to generate
main.s, then put this in the same file as the assembly
code for your functions.
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
|
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: |
Feel free to write C code to get started (it might be good to develop algorithms in C before converting to assembly). You can certainly ask gcc to convert your C to assembly so you can look at some assembly code, but you must write the code you submit! Keep in mind that gcc will produce a lot more code than is necessary, and that we can easily detect gcc produced code.
Start simple - write assembly subroutines that do something simple like just return the value 10:
pow:
pushl %ebp
movl %esp, %ebp
movl $10,%eax
leave
ret
Once this is working (when called from your C test code), start to add the actual code needed.
Use gdb! It is somewhat painful to add calls to printf in assembly language, so rather than debugging via printf, use gdb to trace the execution of your functions.