ICS312 - Spring 2009 - Homework #8 -

Work alone
You are expected to do your own work on all homework assignments. You may (and are encouraged to) engage in general discussions with your classmates regarding the assignments, but specific details of a solution, including the solution itself, must always be your own work. (See the statement of Academic Dishonesty on the course's syllabus.)

What to turn in?
Turn it you NASM file(s), driver.c, asm_io.inc, and asm_io.asm, along with a makefile that compiles all your executables as part of an archive via a single e-mail to henric@hawaii.edu with a subject line like "ICS312: HW#7" before midnight on the day the assignment is due.


Helpful hint #1: Remember to use the dump_math macro for debugging, as explained in the lecture notes.
Helpful hint #2: When implementing a function with several arguments and local variables, it gets really annoying to keep seeing things like [ebp+8], [ebp-4], etc. all over the code. One convenient way to get around this problem is to use the "%define" clause. See this example program that uses %define for declaring a function with 4 arguments and 4 local variables.

Exercise #1: Computing the exp function (30 pts)

For this exercise I provide you with a C program, driver_ex1.c, which defines the main function. This program takes one command-line argument, which should be a floating point number. The program then calls a function called compute_exp that computes the exponential function. You have to implement this function in assembly in a file called hw8_ex1.asm (your makefile creates executable hw8_ex1.)

Here is an example interaction with the program:

% ./hw8_ex1 1.0
Exp(1.00000) = 2.718281984
% ./hw8_ex1 10.3
Exp(10.30000) = 29732.628906250

There is no assembly instruction to compute the exponential function, so you have to compute it using its infinite series:

In the above, the ! symbols denote factorial. You must compute the first 40 terms of the above series in a view to obtaining a decent approximation of the function's value.

Exercise #2: Computing Derivatives (20 pts)

For this exercise I provide you with a C program, driver_ex2.c, which defines the main function. This program takes two command-line arguments, both of them floating point numbers. The program defines a function, f, which takes as argument a float and returns a float. In the program as it is written this function is the f(x) = x2 + 10/x function. The program calls a function called compute_derivative. This function takes three arguments. The first argument is a "function pointer", that is the address of a function. The second argument is a float, which is the point at which the function's derivative should be computed (let's call it x). The third argument is a float, which is the level of precision at which the derivative should be computed (let's call it epsilon). You can see in the program that the function passed to compute_derivative is function f, that the value of x comes from the first command-line argument, and that the value of epsilon comes from the second command-line argument. You must write function compute_derivative in assembly, in a file called hw8_ex2.asm (your makefile creates executable hw8_ex2.)

Here is an example interaction with the program, with the original driver:

% ./hw8_ex2 2.0 0.1
Derivative of function f at point 2.000000 is 1.56970
% ./hw8_ex2 2.0 0.01
Derivative of function f at point 2.000000 is 1.50879
% ./hw8_ex2 2.0 0.001
Derivative of function f at point 2.000000 is 1.50195
The above output makes sense. Indeed, the derivative of f(x) = x2 + 10/x is f'(x) = 2x - 10/x2, which at point x=2.0 has value 1.5. The accuracy of the program increases with a lower epsilon. Note that the code can compute the derivative of any function. For instance, if you replace x*x + 10.0/x in the code of function f by, say, sin(x) (not forgetting to link to the math library with a -lm flag), you get the following interaction:
% ./hw8_ex2 2.5 0.1
Derivative of function f at point 2.500000 is -0.86724
% ./hw8_ex2 2.5 0.001
Derivative of function f at point 2.500000 is -0.80173
% ./hw8_ex2 2.5 0.0001
Derivative of function f at point 2.500000 is -0.80078
And indeed, you can check that cos(2.5) ~ -0.8011436155 (and yes, the derivative of sin is cos!). You should be able to see the limits of (single precision) floating point arithmetic with this code, as decreasing epsilon does not yield better results (once you've implemented the compute_derivative function, that is).

The question now is: how does one compute a derivative??? To have a computer compute the derivative you have to go back to its definition:

So, function compute_derivative should compute consecutive values of the above ratio for h starting at a large value, say 1.0, and with h getting twice as small at every iteration. So, at first the function should compute (f(x+1) - f(x))/1, then (f(x+0.5 - f(x))/0.5, then (f(x+0.25) - f(x))/0.25, etc. The function should stop when the absolute value of the difference between two consecutive ratios is less than epsilon. Let's look at a full example for f(x)=x2 + 10/x, for x=2.0 and epsilon=0.1.

h (f(x+h)-f(x)) / hdifference with previous ratio
1.00000 3.3333N/A
0.50000 2.50000.8333
0.250002.02780.4722
0.12500 1.77210.2557
0.06250 1.63830.1338
0.03125 1.56970.0685    STOP!

And thus the program would output 1.5697, which is what we saw above.


Exercise #3: Computing the natural logarithm (10 pts) [EXTRA CREDIT]

For this exercise I provide you with a C program, driver_ex3.c, which defines the main function. This program takes one command-line argument, which should be a floating point number strictly larger than .5. The program then calls a function called compute_ln that computes the natural logarithm function. You have to implement this function in assembly in a file called hw8_ex2.asm (your makefile creates a program called hw8_ex3.)

Here is an example interaction with the program:

% ./hw8_ex3 1.0
Ln(1.00000) = 0.000000
% ./hw8_ex3 5.6
Ln(10.30000) = 1.72277
% ./hw8_ex3 5.6
Ln(10.30000) = 1.72277
% ./hw8_ex3 2500.0
Ln(2500.00000) = 7.77515

There is no assembly instruction to compute the natural logarithm function, so you have to compute it using its infinite series:

You must compute the first 5000 terms of the above series in a view to obtaining a decent approximation of the function's value (this series converges slower than the series in Exercise #1).


henric@hawaii.edu