hw8_ex2.asm

; Jade Yu Cheng
; ICS 312
; Assignment 7 Exercise 2
; April 24, 2009

; driver_ex2.c defines a main function. It takes two command-line arguments,
; both of them are 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 (x). The third argument is a float, which is
; the level of precision at which the derivative should be computed (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.

%include "asm_io.inc"

%define f       dword [ebp + 8]         ; 1st argument the function pointer
%define x       dword [ebp + 12]        ; 2nd argument the value to compute
%define e       dword [ebp + 16]        ; 3rd argument user specified percision
%define fresult dword [ebp - 4]         ; 1st local var stores f(x) value
%define h       dword [ebp - 8]         ; 2nd local var stores h
%define param   dword [ebp - 12]        ; 3rd local var stores x + h
%define two     dword [ebp - 16]        ; 4th local var stores integer 2
%define diff    dword [ebp - 20]        ; 5th local var stores (f(x+h)-f(x))/h
%define tmp     dword [ebp - 24]        ; 6th local var a temp space for diff

segment .text
        global  compute_derivative
compute_derivative:
        push    ebp                     ; setup
        mov     ebp, esp                ; setup
        sub     esp, 24                 ; setup spare space for 6 local vars

        push    x                       ; push x as f's param
        call    f                       ; call f
        add     esp, 4                  ; clean up stack after function call
        fstp    fresult                 ; store f(x) value into fresult

        mov     two, 2                  ; store 2 in a four byte quatity
        mov     h, 2                    ; initialize h, it will be divided by 2
        mov     diff, 0                 ; initialize diff
        fild    h                       ; convert h into a float quantity
        fstp    h
compute_loop:
        fld     h                       ; st0 = h_old
        fidiv   two                     ; st0 = h_old/2
        fst     h                       ; h_new = h_old/2
        fadd    x                       ; st0 = h_new + x
        fstp    param                   ; fp stack is empty at this point
        push    param                   ; call f with h_new + x
        call    f
        add     esp, 4                  ; clean up stack after function call
        fsub    fresult                 ; st0 = f(h_new + x) - f(x)
        fdiv    h                       ; st0 = (f(h_new + x) - f(x))/h
        fabs                            ; |st0 = (f(h_new + x) - f(x))/h|
        fst     tmp                     ; store the diff_new in tmp for now
        fsub    diff                    ; st0 = diff_old - diff_new
        fabs                            ; st0 = |diff_old - diff_new|
        fcomp   e                       ; compare st0 with epsilon
        fstsw   ax
        sahf
        jna     compute_loop_end        ; jmp to terminate if st0 < epsilon
        fld     tmp                     ; otherwise diff_new = tmp
        fstp    diff
        jmp     compute_loop
compute_loop_end:
        fld     tmp                     ; put diff_new as the return value

        add     esp, 24
        mov     esp, ebp                ; clean up
        pop     ebp                     ; clean up
        ret                             ; clean up
Valid HTML 4.01 Valid CSS