//---------------------------------------------------------------- // distance.s // // This program uses Pentium floating-point instructions to // compute the distance between two points in 3-dimensional // space. It shows the result as a 5-place decimal number. // // assemble using: $ as distance.s -o distance.o // and link using: $ ld distance.o -o distance // // programmer: ALLAN CRUSE // written on: 24 MAR 2006 //---------------------------------------------------------------- # manifest constants .equ PLACES, 5 # count of decimal-places .equ STDOUT, 1 # deviceID for the screen .equ sysWRITE, 4 # serviceID for 'write' .equ sysEXIT, 1 # serviceID for 'exit' .section .data point1: .float 2, 3, 4 # three coordinates for point #1 point2: .float 5, 6, 7 # three coordinates for point #2 ten: .long 10 # radix for the decimal system msg: .ascii "distance = " # legend for the numeric output buf: .ascii " \n" # buffer for the decimal digits len: .int . - msg # length of the output message .section .bss dist: .space 4 # holds a single-precision value idist: .space 4 # holds a long integer value .section .text _start: # sum the squares of the three coordinate-differences xor %ebx, %ebx # initialize the array-index mov $3, %ecx # setup the coordinate-count finit # initialize the coprocessor fldz # load zero as initial total nxcoord: flds point1(,%ebx,4) # load coordinate of point1 flds point2(,%ebx,4) # and coordinate of point2 fsubp # compute their difference fmul %st(0), %st # square this difference faddp # add result to current sum inc %ebx # increment our array-index loop nxcoord # and handle next coodinate # store the sum's square-root as 'dist' fsqrt # compute square-root of %st fstps dist # store %st as 'dist' # convert 'dist' to a suitable long integer value flds dist # load the distance as %st mov $PLACES, %ecx # setup decimal-place count nxmul: fimull ten # multiply %st by ten loop nxmul # to shift the decimal-point fistl idist # store result as an integer fwait # wait until store completes # format the distance-value for display mov idist, %eax # load integer into EAX lea buf, %edi # point EDI to output buffer mov %ecx, %ecx # initialize digit-counter nxdiv: xor %edx, %edx # extend dividend to 64-bits divl ten # perform division by ten push %edx # push remainder onto stack inc %ecx # and count this remainder or %eax, %eax # check: quotient was zero? jnz nxdiv # no, do another division nxdgt: pop %edx # recover prior remainder or $'0', %dl # convert it to a numeral mov %dl, (%edi) # put numeral into buffer inc %edi # advance buffer-pointer loop nxdgt # again for other digits movb $'.', (%edi) # append a decimal-point # shift decimal-point to its appropriate position mov $PLACES, %ecx # number of decimal places nxrot: dec %edi # back up buffer-pointer rolw $8, (%edi) # swap the character-pair loop nxrot # again for other places # now display the message mov $sysWRITE, %eax # ID for 'write' mov $STDOUT, %ebx # ID for screen lea msg, %ecx # message-address mov len, %edx # message-length int $0x80 # invoke kernel # and terminate this program mov $sysEXIT, %eax # ID for 'exit' mov $0, %ebx # exit-code int $0x80 # invoke kernel .global _start # make entry-point visible .end # nothing more to assemble