Question
Using the previous in-class assignment as reference, create a procedure that calculates the average grade using an array of grades and returns the letter grade
Using the previous in-class assignment as reference, create a procedure that calculates the average grade using an array of grades and returns the letter grade in eax. The function should take 2 parameters, the address to an array and the size of that array. Rules: Main should only be used to set the parameters and call your procedure You cannot use memory operands (by name) inside of the procedure, they must be passed as parameters.
In assembly language using MASM Visual Studio
This is my code so far. Please help me fix it.
My Code:
.386 .MODEL FLAT, stdcall .STACK 4096 ExitProcess PROTO, dwExitCode:DWORD
.data array WORD 100,90,60,80,70,100 lenA EQU [$-array]/2 letterGrade DB 0
.code _main PROC
; Calculate the average of the grades use a loop mov edx, lenA push edx, size of array lea esi, [array] push esi; address of array call GetLetterGrade add esp, 8 mov letterGrade, al
GetLetterGrade PROC push ebp mov ebp, esp mov ecx, [ebp + 12] dec ecx mov edx, 0 mov esi, [ebp + 8]
L1: mov ax, WORDPTR [esi + ecx * 2] add dx, ax dec ecx cmp ecx, 0 jge L1
movzx eax, dx cdq mov ebx, [ebp + 12] div ebx
; Determine if the average is an A, B, C, D or F ; Use a series of cmp + jump instructions to build your if else statements
COMMENT ! IN C++ this if-else statements would look like
if (avg >= 90) letterGrade = 'A'; else if (avg >= 80) letterGrade = 'B'; else if (avg >= 70) letterGrade = 'C'; else if (avg >= 60) letterGrade = 'D'; else letterGrade = 'F'; !
; avg is in eax cond1: cmp eax, 90 ; if (avg >= 90) letterGrade = 'A'; JL cond2 mov eax, 'A' jmp next
cond2: cmp eax, 80 jl cond3 mov eax, 'B' jmp next
cond3: cmp eax, 70 JL cond4 mov eax, 'C' jmp next
cond4: cmp eax, 60 JL cond5 mov eax, 'D' jmp next
cond5: mov eax, 'F'
next: pop ebp ret
GetLetterGrade ENDP
INVOKE ExitProcess, 0 _main ENDP END
Sol20:
There are a few issues with the provided code. Here are some changes that should fix the issues:
- In the GetLetterGrade procedure, the division should be done by the size of each element (in this case, 2 bytes), not the size of the array. So, instead of mov ebx, [ebp + 12], use mov ebx, 2.
- Instead of using mov letterGrade, al, use movzx eax, al to zero-extend the result of the procedure to a 32-bit register.
- In the GetLetterGrade procedure, change the order of the push instructions so that the address of the array is pushed last. This is because the first argument is pushed last in the CDECL calling convention.
- In the GetLetterGrade procedure, add the prologue and epilogue macros to set up and clean up the stack frame.
Here is the modified code:
.386
.MODEL FLAT, C
.STACK 4096
ExitProcess PROTO, dwExitCode:DWORD
.DATA
array WORD 100, 90, 60, 80, 70, 100
lenA EQU ($ - array) / 2
letterGrade DB 0
.CODE
GetLetterGrade PROC, pArray:PTR WORD, arraySize:DWORD
prologue
push ebx
push esi
push edi
mov ecx, arraySize
dec ecx
mov edx, 0
mov esi, pArray
L1:
mov ax, [esi + ecx * 2]
add dx, ax
dec ecx
cmp ecx, 0
jge L1
mov ebx, 2 ; size of each element
cdq
idiv ebx ; divide the sum by the number of elements
cmp eax, 90 ; determine letter grade based on the average
jl cond2
mov eax, 'A'
jmp next
cond2:
cmp eax, 80
jl cond3
mov eax, 'B'
jmp next
cond3:
cmp eax, 70
jl cond4
mov eax, 'C'
jmp next
cond4:
cmp eax, 60
jl cond5
mov eax, 'D'
jmp next
cond5:
mov eax, 'F'
next:
pop edi
pop esi
pop ebx
ret
GetLetterGrade ENDP
main PROC
push lenA
lea esi, array
push esi ; address of array
call GetLetterGrade
add esp, 8
movzx eax, al ; zero-extend to 32 bits
mov letterGrade, al
INVOKE ExitProcess, 0
main ENDP
END
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started