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

Write an assembly language program which will call several procedures. The proce

ID: 664601 • Letter: W

Question

Write an assembly language program which will call several procedures. The procedures, their parameters, and their purposes are as follows (shown in C++ format):

void AVGS (int LIST[], int N, int &AVE, int &AVEP, int &AVEN)

LIST is a one dimensional array of signed integers and N is the number of elements in that array. Both of these are input parameters to the procedure. The procedure AVGS must calculate 1) the average of the N integers in LIST and return the result in AVE, 2) the average of the positive numbers (> 0) and return the result in AVEP, and 3) the average of the negative numbers (< 0) and return the result in AVEN.

int LARGE (int LIST[], int N)

LIST and N are as above. The function returns the value of the largest element in the array. Note that the integer result is to be returned in register EAX. Note that this is typical of value returning functions in C++.

In C++, passing the parameters would be done on the stack. However, since we haven’t covered how to do that, you are to use registers to pass them. It is up to you as to which registers you should use. Pay attention as to which parameters are passed by value and which by reference. Note that arrays are always passed by reference. Also, note that int refers to 32 bit values. Do not directly access the parameters via the .data section.

The main program will loop twice, performing the following tasks each time:

1) Read in a set of data

2) Call both of the above procedures

3) Display the data values and the results of the procedures (the average, the positive average, the negative average, and the largest value)

Use the following test data (there are two sets):

A) 4 -30 0 7 42 -20 18 400 -123 -6

B) 2 17 -5 0 20 15 -16 -3 -2 14

-1 12 1 -5 -100 15 22 -5 68 -13

Your program should run both data sets in one execution. DO NOT RUN THE PROGRAM TWICE!

Explanation / Answer

main:  
; initializes the two numbers and the counter. Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
   mov   ax,'00'       ; initialize to all ASCII zeroes
   mov   di,counter       ; including the counter
   mov   cx,digits+cntDigits/2   ; two bytes at a time
   cld           ; initialize from low to high memory
   rep   stosw       ; write the data
   inc   ax       ; make sure ASCII zero is in al
   mov   [num1 + digits - 1],al ; last digit is one
   mov   [num2 + digits - 1],al ;
   mov   [counter + cntDigits - 1],al

   jmp   .bottom       ; done with initialization, so begin

.top
   ; add num1 to num2
   mov   di,num1+digits-1
   mov   si,num2+digits-1
   mov   cx,digits   ;
   call   AddNumbers   ; num2 += num1
   mov   bp,num2       ;
   call   PrintLine   ;
   dec   dword [term]   ; decrement loop counter
   jz   .done       ;

   ; add num2 to num1
   mov   di,num2+digits-1
   mov   si,num1+digits-1
   mov   cx,digits   ;
   call   AddNumbers   ; num1 += num2
.bottom
   mov   bp,num1       ;
   call   PrintLine   ;
   dec   dword [term]   ; decrement loop counter
   jnz   .top       ;
.done
   call   CRLF       ; finish off with CRLF
   mov   ax,4c00h   ; terminate
   int   21h       ;


;****************************************************************************
;
; PrintLine
; prints a single line of output containing one term of the
; Fibonacci sequence. The first few lines look like this:
;
; Fibonacci(1): 1
; Fibonacci(2): 1
; Fibonacci(3): 2
; Fibonacci(4): 3
;
; INPUT: ds:bp ==> number string, cx = max string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx, di
;
;****************************************************************************
PrintLine:
   mov   dx,eol       ; print combined CRLF and msg1
   mov   cx,msg1len+eollen ;
   call   PrintString   ;

   mov   di,counter   ; print counter
   mov   cx,cntDigits   ;
   call   PrintNumericString

   call   IncrementCount   ; also increment the counter

   mov   dx,msg2       ; print msg2
   mov   cx,msg2len   ;
   call   PrintString   ;
  
   mov   di,bp       ; recall address of number
   mov   cx,digits   ;
   ; deliberately fall through to PrintNumericString

;****************************************************************************
;
; PrintNumericString
; prints the numeric string at DS:DI, suppressing leading zeroes
; max length is CX
;
; INPUT: ds:di ==> number string, cx = max string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx, di
;
;****************************************************************************
PrintNumericString:
   ; first scan for the first non-zero byte
   mov   al,'0'       ; look for ASCII zero
   cld           ; scan from MSD to LSD
   repe   scasb       ;
   mov   dx,di       ; points to one byte after
   dec   dx       ; back up one character
   inc   cx       ;
   ; deliberately fall through to PrintString

;****************************************************************************
;
; PrintString
; prints the string at DS:DX with length CX to stdout
;
; INPUT: ds:dx ==> string, cx = string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx
;
;****************************************************************************
PrintString:
   mov   bx, 1       ; write to stdout
   mov ah, 040h ; write to file handle
   int   21h       ; ignore return value
   ret           ;

;****************************************************************************
;
; AddNumbers
; add number 2 at ds:si to number 1 at es:di of width cx
;
;
; INPUT: es:di ==> number1, ds:si ==> number2, cx= max width
; OUTPUT: CF set on overflow
; DESTROYED: ax, si, di
;
;****************************************************************************
AddNumbers:
   std           ; go from LSB to MSB
   clc           ;
   pushf           ; save carry flag
.top
   mov   ax,0f0fh   ; convert from ASCII BCD to BCD
   and     al,[si]       ; get next digit of number2 in al
   and   ah,[di]       ; get next digit of number1 in ah
   popf           ; recall carry flag
   adc   al,ah       ; add these digits
   aaa           ; convert to BCD
   pushf           ;
   add   al,'0'       ; convert back to ASCII BCD digit
   stosb           ; save it and increment both counters
   dec   si       ;
   loop   .top       ; keep going until we've got them all
   popf           ; recall carry flag
   ret           ;

;****************************************************************************
;
; IncrementCount
; increments a multidigit term counter by one
;
; INPUT: none
; OUTPUT: CF set on overflow
; DESTROYED: ax, cx, di
;
;****************************************************************************
IncrementCount:
   mov   cx,cntDigits   ;
   mov   di,counter+cntDigits-1
   std           ; go from LSB to MSB
   stc           ; this is our increment
   pushf           ; save carry flag
.top
   mov   ax,000fh   ; convert from ASCII BCD to BCD
   and   al,[di]       ; get next digit of counter in al
   popf           ; recall carry flag
   adc   al,ah       ; add these digits
   aaa           ; convert to BCD
   pushf           ;
   add   al,'0'       ; convert back to ASCII BCD digit
   stosb           ; save and increment counter
   loop   .top       ;
   popf           ; recall carry flag
   ret           ;
  
;****************************************************************************
;
; CRLF
; prints carriage return, line feed pair to stdout
;
; INPUT: none
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx
;
;****************************************************************************
CRLF:   mov   dx,eol       ;
   mov   cx,eollen   ;
   jmp   PrintString   ;

;****************************************************************************
; static data
;****************************************************************************
eol   db 13,10       ; DOS-style end of line
eollen   equ $ - eol

msg1   db 'Fibonacci('   ;
msg1len   equ $ - msg1

msg2   db '): '       ;
msg2len   equ $ - msg2
;****************************************************************************
; initialized data
;****************************************************************************
term dd maxTerms       ;
;****************************************************************************
; unallocated data
;
; A better way to do this would be to actually ask for a memory
; allocation and use that memory space, but this is a DOS COM file
; and so we are given the entire 64K of space. Technically, this
; could fail since we *might* be running on a machine which doesn't
; have 64K free. If you're running on such a memory poor machine,
; my advice would be to not run this program.
;
;****************************************************************************
; static data
counter:           ;
num1 equ counter+cntDigits   ;
num2 equ num1+digits       ;
      

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote