Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The purpose of this assignment is to explore methods to represent, access, and p

ID: 3580388 • Letter: T

Question

The purpose of this assignment is to explore methods to represent, access, and process arrays in Pentium Assembler. Briefly, you are going to define an array, initialize it with random values, and determine the sum, average, minimum, and maximum of the values in the array. For this assignment, you should use a new program skeleton called utilities.asm which is available on the software course web page.

Declare a symbol called N with a value of 10 to indicate the table size; declare a table called T of size Nwhere each entry in T is 32 bits.

In addition to dump, utilities.asm also contains a function called rand8 which returns a random number in eax in the range [0..255]. Write a function called init that uses rand8 to initialize T to random values. Do not pass any arguments to init; init can refer to N and T directly. This function should not permanently modify any registers.*

Write a function that calculates the sum of the contents of T. Pass the address of T to the function in eax; pass N in ebx. Return the sum in eax. Do not modify any other registers.*

Write a function that calculates the minimum and maximum of the contents of T. Pass (the address of) T and (the value of) N by pushing them on the stack. Return the min in eax and the max in ebx. Do not modify any other registers.*

Extra credit. Write a function that calculates the average (using integer arithmetic) of the contents of T. Pass arguments by passing the address of a parameter block in eax. The parameter block should contain the address of T, the value of N, followed by space for the average. Do not modify any registers.*

Call dump (one last time) with the values of sum in eax, min in ebx, max in ecx, and avg in edx. (An easy way to do this is to define sum, etc. as variables and save the values as they are calculated.)

Demonstrate that your program works for 10 values. Make sure that your program can be easily changed to accommodate other values (such as 100000) for N.

Email a copy of your .asm file(s), as well as a file containing the output messages from your program(s).

MY FIle SO FAR (error message on line 209 I have no idea why):

;======================================================================
   TITLE   Program Utilities
;======================================================================
; File:       utilities.asm
;
; Date:       12/23/2004
; Description:
; This file contains a simple console program and includes the following
; functions:
; call dump     ;show the contents of registers
; call rand8   ;return a random number in eax in the range [0..255]
;   call resetTime   ;sets elapsed time timer back to zero
;   call reportTime   ;reports elapsed time in milliseconds
; Build:
; See build.bat for a command line oriented way to assemble and link
; this program. Simply type the following to create an executable:
; masm32inml /c /coff /Cp /nologo /Zd /Zi /Fl /Fm /FR /DDebug utilities.asm
; masm32inlink /nologo /map /debug /subsystem:console utilities.obj
; or
; build utilities
;======================================================================
; (this should not require any changes)
   .nolist           ;turn off listing
   .686           ;instructions for Pentium Pro (or better)
   .model   flat, stdcall   ;no crazy segments!
   option   casemap:none   ;case sensitive
;----------------------------------------------------------------------
; (insert needed external definitions here)
   include       masm32includewindows.inc
   include       masm32includemasm32.inc
   include       masm32includekernel32.inc
   include       masm32macrosmacros.asm

   includelib   masm32libmasm32.lib
   includelib   masm32libuser32.lib
   includelib   masm32libkernel32.lib
;----------------------------------------------------------------------
   .list       ;turn on listing
   .data       ;insert variables below
prompt   equ   ""   ;prompt string
;----------------------------------------------------------------------
   align   4
   .code       ;insert executable instructions below
main   PROC       ;program execution begins here
   mov   eax, 1   ;set regs values
   mov   ebx, 2
   mov   ecx, 3
   mov   edx, 4
   mov   esi, 5
   mov   edi, 6
  
  
  
   call   dump   ;show contents of regs
   mov   eax, input(prompt)   ;prompt the user
   exit       ;end of program
main   ENDP
;----------------------------------------------------------------------
;insert additional procedures/functions here

   .data
szTemp   byte   16 dup (?)   ;buffer for messages
szPrime   byte   "%08lx", 0   ;message format string

   .code
;32-bit windows calling conventions:
;   EBX, ESI, and EDI are preserved.
;   EAX, ECX, and EDX can be freely modified.

CR   =   13   ;carriage return
LF   =   10   ;linefeed

;this macro outputs a newline (cr,lf)
newline   MACRO
   print   SADD(CR,LF)
   ENDM
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
show   MACRO   caption, value
;note:   'value' must not be in eax, ecx, or edx (because they may be
;   modified by the first call).
   print   SADD(caption)
   mov   eax, value
   invoke   wsprintf, offset szTemp, offset szPrime, eax
   print   offset szTemp
   ENDM
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;(some of the) eflags bits:
;   ID-bit 21, OF-bit 11, SF-bit 7, ZF-bit 6, AF-bit 4, CF-bit 0
CF   equ   1b   ;carry flag bit
ZF   equ   1000000b   ;zero flag bit
SF   equ   10000000b   ;sign flag bit
OF   equ   100000000000b   ;overflow flag bit

;this function dumps the contents of the registers to the console.
;all of the caller's registers are preserved.
dump   PROC


   pushfd   ;save eflags
   pushad   ;save registers (order is: eax, ecx, edx, ebx,
       ; esp, ebp, esi, and edi)
   newline               ;end line
   ;output registers
   show   " eax:", [esp+28]   ;output eax
   show   " ebx:", [esp+16]   ;output ebx
   show   " ecx:", [esp+24]   ;output ecx
   show   " edx:", [esp+20]   ;output edx
   newline               ;end line
   show   " esp:", [esp+12]   ;output esp
   show   " ebp:", [esp+8]   ;output ebp
   show   " esi:", [esp+4]   ;output esi
   show   " edi:", [esp]       ;output edi
   show   " eip:", [esp+36]   ;output addr of next instruction
   newline               ;end line
   show   " Table:", [T]       ;output edi
   newline               ;end line
   ;output flags
   show   " eflags:", [esp+32]   ;output eflags
   mov   ebx, [esp+32]       ;fetch contents of saved eflags
   ;CF flag
   test   ebx, CF           ;carry set?
   jz   cf0           ;jump if 0
   print   SADD(" CF:1")       ;flag is on
   jmp   @f           ;skip over else part
cf0:
   print   SADD(" CF:0")       ;flag is off
@@:
   ;ZF flag
   test   ebx, ZF           ;zero set?
   jz   zf0           ;jump if 0
   print   SADD(" ZF:1")       ;flag is on
   jmp   @f           ;skip over else part
zf0:
   print   SADD(" ZF:0")       ;flag is off
@@:
   ;SF flag
   test   ebx, SF           ;sign set?
   jz   sf0           ;jump if 0
   print   SADD(" SF:1")       ;flag is on
   jmp   @f           ;skip over else part
sf0:
   print   SADD(" SF:0")       ;flag is off
@@:
   ;OF flag
   test   ebx, OF           ;overflow set?
   jz   of0           ;jump if 0
   print   SADD(" OF:1")       ;flag is on
   jmp   @f           ;skip over else part
of0:
   print   SADD(" OF:0")       ;flag is off
@@:
   newline               ;end line
   newline               ;end line
   ;project: add code to show contents of stack here
   popad               ;restore pushed registers
   popfd               ;restore eflags
   ret               ;return to caller
dump   ENDP
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   .data
seed   dword   11       ;random number generator seed (can't be 0)
;part1      
N equ 10 ;declare symbol N with value 10
T dword N dup(?) ;declare table T of size N =10
Min dword 0
Max dword 0

   .code
rand   PROC
   push   ecx       ;save modified registers
   push   edx
   ;Park Miller random number algorithm.
   ;Written by Jaymeson Trudgen (NaN)
   ;Optimized by Rickey Bowers Jr. (bitRAKE)
   ;
   ;this code is not commented because the original author did not
   ;comment it (not a good idea).
   ;
   mov   eax, seed
   xor   edx, edx
   mov   ecx, 127773
   div   ecx
   mov   ecx, eax
   mov   eax, 16807
   mul   edx
   mov   edx, ecx
   mov   ecx, eax
   mov   eax, 2836
   mul   edx
   sub   ecx, eax
   xor   edx, edx
   mov   eax, ecx
   mov   seed, ecx

   pop   edx       ;restore modified registers
   pop   ecx
   ret           ;return to caller
rand   ENDP

;GLOBAL rand8 ;declare rand8 as global
rand8   PROC
   call   rand       ;eax will contain a 32-bit random number
   and   eax, 0ffh   ;to yield a value in [0..255]
   ret           ;return to caller
rand8   ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;part2
.code
init PROC
push eax ;save reg used
push ebx ;save reg used
push ecx ;save reg used

mov ebx, offset T ;get starting address of table
mov ecx, N ;get number of entries
lp:
cmp ecx, 0 ;all done?
jle lpDone ;jump if finished
call rand8 ;generate a random number
mov [ebx], eax ;save the random number in the table
add ebx, 4 ;point to the next table entry
dec ecx ;update the counter
jmp lp ;do the next one
lpDone:
pop ecx ;restore reg used
pop ebx ;restore reg used
pop eax ;restore reg used
ret ;return to caller
init ENDP

;part3
SumT PROC ;sums up the content of T, we may use a loop here, research more on that
push eax ;save reg used
push ebx ;save reg used
push ecx
  
   mov eax, offset T ;eax points to the first table entry
   mov ebx, [eax] ;ebx contains the first table entry
   mov ecx, N
lp1:
   ;add eax, 4 ;eax now points to next table entry
   CMP ecx, 0
   jge done
   add ebx, [eax] ;sum the second entry
   add ebx, 4 ;point to the next table entry
dec ecx
   mov eax, ebx
   jmp lp1
done:
pop ecx ;restore reg used
pop ebx ;restore reg used
pop eax ;restore reg used
ret ;return to caller
;call dump
SumT ENDP

;part4
Min PROC ;cal min max by pushing into stack
push eax ;save reg used
push ebx ;save reg used
push ecx
  
mov eax, offset T
   mov ebx, [eax] ;ebx contains the first table entry
   mov Min, ebx
   mov ecx, N
lp1:

CMP ecx, 0
jge done1
   add ebx, [eax] ;sum the second entry
   CMP ebx, Min
   jge donemin
   add ebx, 4 ;point to the next table entry
dec ecx
   mov ebx, Min

jmp lp1
donemin:
done1:
pop eax ;restore reg used
pop ebx ;restore reg used
pop ecx ;restore reg used
ret ;return to caller

Min ENDP

;part4
Max PROC ;cal min max by pushing into stack
push eax ;save reg used
push ebx ;save reg used
push ecx
   push edx
  
mov eax, offset T
   mov ebx, [eax] ;ebx contains the first table entry
   mov Max, ebx
   mov ecx, N
lpm:

CMP ecx, 0
jle donem
   add ebx, [eax] ;sum the next entry
   CMP ebx, Max
   jle donemax
   add ebx, 4 ;point to the next table entry
dec ecx
   mov ecx, Min
jmp lpm

donemax:
donem:
pop eax ;restore reg used
pop ebx ;restore reg used
pop ecx ;restore reg used
pop edx ;restore reg used
ret ;return to caller

Max ENDP

;part5
Avg PROC
   push eax ;save reg used
push ebx ;save reg used
push ecx
   push edx
  
   mov eax, offset T ;eax points to the first table entry
   mov ecx, N ;ebx contains the first table entry
   mov ebx, [eax] ;ebx contains the first table entry
lp2:
   cmp ecx, 0
;add eax, 4 ;eax now points to next table entry
;CMP ebx, N
   jge done3

   add ebx, [eax] ;sum the second entry
   add ebx, 4 ;point to the next table entry
dec ecx
mov eax, ebx
   mov edx, 0
jmp lp2
done3:
idiv ecx ;divide by N
   mov edx, eax
pop ecx ;restore reg used
pop ebx ;restore reg used
pop eax ;restore reg used
ret ;return to caller

Avg ENDP

   .data
startTicks   dword   0
   .code
resetTime   PROC
   pushad           ;save registers
   call   GetTickCount   ;get starting time
   mov   startTicks, eax   ;save start time
   popad           ;restore pushed registers
   ret           ;return to caller
resetTime   ENDP

   .data
timeMessage       byte   "elapsed time: %lu milliseconds", CR, LF, 0
timeMessageBuffer   byte   256 dup (0)
   .code
reportTime   PROC
   pushad           ;save registers
   call   GetTickCount   ;get ending time
   sub   eax, startTicks   ;calculate elapsed time
   invoke   wsprintf, offset timeMessageBuffer, offset timeMessage, eax
               ;create message
   print   offset timeMessageBuffer   ;output message

   popad           ;restore pushed registers
   ret           ;return to caller
reportTime   ENDP

   END   main
;======================================================================

Explanation / Answer

Description:

; This file contains a simple console program and includes the following

; functions:

; call dump     ;show the contents of registers

; call rand8   ;return a random number in eax in the range [0..255]

;   call resetTime   ;sets elapsed time timer back to zero

;   call reportTime   ;reports elapsed time in milliseconds

;   call dumpXmm64   ;shows xmm registers as pairs of 64 bit fp numbers

;   call dumpX87   ;shows contents of st(0)...st(7) fp registers

; Build:

; masm32inml /c /coff /Cp /nologo /Zd /Zi /Fl /Fm /FR /DDebug utilities.asm

;======================================================================

; (this should not require any changes)

   .nolist           ;turn off listing

   .686           ;instructions for Pentium Pro (or better)

   .xmm           ;allow simd instructions

   .model   flat, stdcall   ;no crazy segments!

   option   casemap:none   ;case sensitive

;----------------------------------------------------------------------

; (insert needed external definitions here)

   include       masm32includewindows.inc

   include       masm32includemasm32.inc

   include       masm32includekernel32.inc

   include       masm32macrosmacros.asm

   includelib   masm32libmasm32.lib

   includelib   masm32libuser32.lib

   includelib   masm32libkernel32.lib

;----------------------------------------------------------------------

   .list           ;turn listing on

;beware of the 32-bit windows calling conventions:

;   EBX, ESI, and EDI are preserved.

;   EAX, ECX, and EDX can be freely modified.

   .data

szTemp   byte   256 dup (?)   ;buffer for messages

szPrime   byte   "%08lx", 0   ;message format string

   .code

   align   4

CR   =   13   ;carriage return

LF   =   10   ;linefeed

;this macro outputs a newline (cr,lf)

newline   MACRO

   print   SADD(CR,LF)

ENDM

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

show   MACRO   caption, value

;note:   'value' must not be in eax, ecx, or edx (because they may be

;   modified by the first call).

   print   SADD(caption)

   mov   eax, value

   invoke   wsprintf, offset szTemp, offset szPrime, eax

   print   offset szTemp

ENDM

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

;(some of the) eflags bits:

;   ID-bit 21, OF-bit 11, SF-bit 7, ZF-bit 6, AF-bit 4, CF-bit 0

CF   equ   1b   ;carry flag bit

ZF   equ   1000000b   ;zero flag bit

SF   equ   10000000b ;sign flag bit

OF   equ   100000000000b   ;overflow flag bit

;this function dumps the contents of the registers to the console.

;all of the caller's registers are preserved.

dump   PROC

   pushfd   ;save eflags

   pushad   ;save registers

           ; order is: eax, ecx, edx, ebx, esp, ebp, esi, and edi

   newline                       ;end line

   ;output registers

   show   " eax:", [esp+28]   ;output eax

   show   " ebx:", [esp+16]   ;output ebx

   show   " ecx:", [esp+24]   ;output ecx

   show   " edx:", [esp+20]   ;output edx

   newline               ;end line

   show   " esp:", [esp+12]   ;output esp

   show   " ebp:", [esp+8]   ;output ebp

   show   " esi:", [esp+4]   ;output esi

   show   " edi:", [esp]       ;output edi

   show   " eip:", [esp+36]   ;output addr of next instruction

   newline               ;end line

   ;output flags

   show   " eflags:", [esp+32]   ;output eflags

   mov   ebx, [esp+32]       ;fetch contents of saved eflags

   ;CF flag

   test   ebx, CF           ;carry set?

   jz   cf0           ;jump if 0

   print   SADD(" CF:1")       ;flag is on

   jmp   @f           ;skip over else part

cf0:

   print   SADD(" CF:0")       ;flag is off

@@:

   ;ZF flag

   test   ebx, ZF           ;zero set?

   jz   zf0          ;jump if 0

   print   SADD(" ZF:1")       ;flag is on

   jmp   @f           ;skip over else part

zf0:

   print   SADD(" ZF:0")       ;flag is off

@@:

   ;SF flag

   test   ebx, SF           ;sign set?

   jz   sf0           ;jump if 0

   print   SADD(" SF:1")       ;flag is on

   jmp   @f           ;skip over else part

sf0:

   print   SADD(" SF:0")       ;flag is off

@@:

   ;OF flag

   test   ebx, OF           ;overflow set?

   jz   of0           ;jump if 0

   print   SADD(" OF:1")       ;flag is on

   jmp   @f           ;skip over else part

of0:

   print   SADD(" OF:0")       ;flag is off

@@:

   newline               ;end line

   newline               ;end line

   ;project: add code to show contents of stack here

   popad               ;restore pushed registers

   popfd               ;restore eflags

   ret               ;return to caller

dump   ENDP

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   .data

seed   dword   11       ;random number generator seed (can't be 0)

   .code

rand   PROC

   push   ecx       ;save modified registers

   push   edx

   ;Park Miller random number algorithm.

   ;Written by Jaymeson Trudgen (NaN)

   ;Optimized by Rickey Bowers Jr. (bitRAKE)

   ;

   ;this code is not commented because the original author did not

   ;comment it (not a good idea).

   ;

   mov   eax, seed

   xor   edx, edx

   mov   ecx, 127773

   div   ecx

   mov   ecx, eax

   mov   eax, 16807

   mul   edx

   mov   edx, ecx

   mov   ecx, eax

   mov   eax, 2836

   mul   edx

   sub   ecx, eax

   xor   edx, edx

   mov   eax, ecx

   mov   seed, ecx

   pop   edx       ;restore modified registers

   pop   ecx

   ret           ;return to caller

rand   ENDP

rand8   PROC

   call   rand       ;eax will contain a 32-bit random number

   and   eax, 0ffh   ;to yield a value in [0..255]

   ret           ;return to caller

rand8   ENDP

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   .data

startTicks   dword   0

   .code

resetTime   PROC

   pushad           ;save registers

   call   GetTickCount   ;get starting time

   mov   startTicks, eax   ;save start time

   popad           ;restore pushed registers

   ret           ;return to caller

resetTime   ENDP

   .data

timeMessage       byte   "elapsed time: %lu milliseconds", CR, LF, 0

timeMessageBuffer   byte   256 dup (0)

   .code

reportTime   PROC

   pushad           ;save registers

   call   GetTickCount   ;get ending time

   sub   eax, startTicks   ;calculate elapsed time

   invoke   wsprintf, offset timeMessageBuffer, offset timeMessage, eax

               ;create message

   print   offset timeMessageBuffer   ;output message

   popad           ;restore pushed registers

   ret           ;return to caller

reportTime   ENDP

;======================================================================

   .data

   align   8

var       real8   0.0       ;temp storage for 64-bit fp values

fpStatus   dword   0       ;to save mxcsr

fpFormat   byte   "%-20s", 0   ;message format string

fpTemp       byte   256 dup (0)   ;buffer for messages

;define masks for (some of the) mxcsr register bits: ZM-bit 2

ZM   equ   100b   ;carry flag bit

OM   equ   1000b   ;overflow flag bit

UM   equ   10000b   ;underflow flag bit

RC1M   equ   10000000000000b   ;rounding control 1 flag bit

RC2M   equ   100000000000000b   ;rounding control 2 flag bit

   .code

;this macro prints a caption string and the fp contents of one of the

; xmm registers. each xmm reg contains 2 fp numbers.

;note:   'xmReg' must be xmm0..xmm7

showXmm64   MACRO   caption, xmReg

   print   SADD(" ")       ;print space

   print   SADD(caption)       ;print the caption string

   print   SADD(" ")       ;print space

   movhpd   var, xmReg       ;save the hi 64 bits

   invoke   FloatToStr, var, addr szTemp   ;convert to float

   mov   eax, offset szTemp

   invoke   wsprintf, offset fpTemp, offset fpFormat, eax

   print   offset fpTemp       ;print float value

   print   SADD(" ")       ;print space

   movlpd   var, xmReg       ;save the lo 64 bits

   invoke   FloatToStr, var, addr szTemp   ;convert to float

   print   offset szTemp       ;print float value

   newline               ;end line

ENDM

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

;this function dumps the contents of the xmm0..xmm7 registers to the console.

;all of the caller's registers are preserved.

dumpXmm64   PROC

   stmxcsr   fpStatus       ;save the fp status reg

   pushfd               ;save eflags

   pushad               ;save registers

   newline               ;end line

   ;

   showXmm64   "xmm0:", xmm0   ;show fp contents of xmm0

   showXmm64   "xmm1:", xmm1   ;show fp contents of xmm1

   showXmm64   "xmm2:", xmm2   ;show fp contents of xmm2

   showXmm64   "xmm3:", xmm3   ;show fp contents of xmm3

   showXmm64   "xmm4:", xmm4   ;show fp contents of xmm4

   showXmm64   "xmm5:", xmm5   ;show fp contents of xmm5

   showXmm64   "xmm6:", xmm6   ;show fp contents of xmm6

   showXmm64   "xmm7:", xmm7   ;show fp contents of xmm7

;

   show   " mxcsr:", fpStatus   ;output eflags

   ;RC field (2 bits)

   test   fpStatus, RC2M       ;check the high order bit first

   jz   rc20

   print   SADD(" RC:0")

   jmp   @f

rc20:

   print   SADD(" RC:1")

@@:

   test   fpStatus, RC1M       ;check the low order bit first

   jz   rc10

   print   SADD("0")

   jmp   @f

rc10:

   print   SADD("1")

@@:

   ;UM flag

   test   fpStatus, UM       ;underflow set?

   jz   um0           ;jump if 0

   print   SADD(" UM:1")      ;flag is on

   jmp   @f           ;skip over else part

um0:

   print   SADD(" UM:0")       ;flag is off

@@:

   ;OM flag

   test   fpStatus, OM       ;overflow set?

   jz   om0           ;jump if 0

   print   SADD(" OM:1")       ;flag is on

   jmp   @f           ;skip over else part

om0:

   print   SADD(" OM:0")       ;flag is off

@@:

   ;ZM flag

   test   fpStatus, ZM       ;divide-by-zero set?

   jz   zm0           ;jump if 0

   print   SADD(" ZM:1")       ;flag is on

   jmp   @f           ;skip over else part

zm0:

   print   SADD(" ZM:0")       ;flag is off

@@:

   newline               ;end line

   ;

   popad               ;restore pushed registers

   popfd               ;restore eflags

   ldmxcsr       fpStatus   ;restore the fp status reg

   ret               ;return to caller

dumpXmm64   ENDP

;======================================================================

   .data

;the following table must be this size and this order

fpState   dword   7 dup(0)

fpR0   real10 0.0

fpR1   real10   0.0

fpR2   real10   0.0

fpR3   real10   0.0

fpR4   real10   0.0

fpR5   real10   0.0

fpR6   real10   0.0

fpR7   real10   0.0

;check the table size

fpSize   =   $ - fpState

   if   fpSize ne 108

   echo   invalid table size

   .err

   endif

   .code

;this macro prints a caption string and the fp contents of one of the

; x87 registers.

showFP64   MACRO   caption, fpReg

   print   SADD(" ")       ;print space

   print   SADD(caption)       ;print the caption string

   print   SADD(" ")       ;print space

   fld   fpReg           ;load 80 bit fp reg val

   fstp   var           ;store and pop as 64 bit fp val

   invoke   FloatToStr, var, addr szTemp   ;convert to float

   print   offset szTemp       ;print float value

   newline               ;end line

ENDM

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

dumpX87   proc

   pushfd               ;save eflags

   pushad               ;save registers

   fsave   fpState           ;save x87 fp state

   ;

   newline               ;end line

   ;output all of the x87 fp register stack

   showFP64   "st(0): ", fpR0

   showFP64   "st(1): ", fpR1

   showFP64   "st(2): ", fpR2

   showFP64   "st(3): ", fpR3

   showFP64   "st(4): ", fpR4

   showFP64   "st(5): ", fpR5

   showFP64   "st(6): ", fpR6

   showFP64   "st(7): ", fpR7

   ;

   frstor   fpState           ;restore x87 fp state

   popad               ;restore pushed registers

   popfd               ;restore eflags

   ret               ;return to caller

dumpX87   endp

;======================================================================

   end

;======================================================================