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: 3577589 • 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.

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.

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).

;======================================================================
   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   "<hit return>"   ;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
   ;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

   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
;======================================================================