Project #3
This project will combine C++ and assembly programming.
As we’ve done before, we’ll use C-strings (a
ays of chars that mark
the end of the “string” with a 0) rather than C++ string objects. We’ll
incorporate those into a structure data type. We’ll be sending an a
ay
of structures to all the functions, so keep in mind that when you send
an a
ay as a parameter, the function is actually receiving an address.
Open up the Word document Project3 starter code.docx that I included with the project. Please
copy that into your project’s source code, and don’t modify it. Let’s look at the individual
functions:
getData
void getData(Student []);
This function receives an a
ay of Student structures. The data to fill these structures is in a file
named “student_data.txt” which is attached to this assignment. I’m supplying the code for this
function, because it uses an ifstream function that you might not have seen before. It’s
handy, because it reads in a string as a char a
ay (just what we need) and even puts the
terminating zero where it goes! As long as the “student_data.txt” file is in the same folder as
your source code, this function should work as written.
print
void print(Student[], Student);
Please look at the file named “output.txt” that is attached to this assignment. It shows the exact
output that your program should create. Its parameters are the a
ay of structures and a single
structure that holds data for the student with the highest average.
findAverages
void findAverages(Student[]);
This function receives an a
ay of Student structures. It’s task is to get the average of the four
tests for each student, and store that average into the average field in that student’s structure.
Suggestions for this function:
a. Don’t use the lea instruction; instead, mov the parameter into a general-purpose register
. You can declare no more than three local variables: two ints and a float
c. Base-index addressing works well here, like [esi + edx].test1 for example; if you’ve
got esi and edx set up co
ectly, you can address fields as shown here. You could use
other general-purpose registers for the job, also. The C++ compiler creates some problems
for addressing as we would in an all-assembly program. There’s no need to use the PTR
operator.
d. You’re going to be using the FPU to divide. When you store the result, use the fstp
instruction rather than just fst. The fstp instruction means “store result and pop”, and it
cleans up the FPU stack after it stores the result where you tell it to. It will prevent the FPU
stack from getting used up (it only has 8 registers, don’t forget)
Project #3
determinePassing
void determinePassing(Student[]);
This is a void function that receives the a
ay of Student structures. Its job is to determine
whether or not each student is passing, based on his/her average. For this program, if the
average is 60 or higher, the student is passing (in which case, make the passing field true, that
is, 1). For an average of less than 60, the passing field should be false (0).
Suggestions for this function:
a. Pretty much the same as the previous function in terms of addressing, etc.
. You’re going to be using the FPU to compare the float averages to 60. After doing so,
execute this instruction two times: fstp ST(0)
This will clear data off of the FPU stack; you might get some near-impossible-to-track e
ors
if you don’t.
getHighestStudent
void getHighestStudent(Student[], Student &);
This function will probably take you the longest, so you might want to save it for last (after
you’ve gotten the addressing thing down). If you look in main(), you’ll see that I declared an
individual Student structure that will contain the info for the student with the highest average. I
initialized that structure with a name (“Nobody”) and an average of 0.
The function receives the address of that structure (notice that the parameter is a reference
parameter) in addition to the a
ay of Student structures. The idea is to loop through the a
ay,
and do the “King of the Mountain” algorithm with each student’s average.
The trick is, as you find each new “King”, you’ll have to copy its data into the individual structure.
That way, the individual structure will always contain the data for the highest-so-far student.
Suggestions for this function:
a. Pretty much the same as the previous functions in terms of addressing, etc.
. Once more, you’re going to be using the FPU to compare the float averages. After doing so,
execute this instruction two times: fstp ST(0)
c. Warning: it will be really easy to trash out registers in this function, especially the ecx and
the esi (if you’re using it in base-index addressing). Why? You’ll be using both of them to
copy the studentName field from one structure to another.
Additional specs
1. I STRONGLY suggest writing one function at a time. The order of the prototypes is the
suggested order. So, write a function and comment out everything in main() except where
the function is being tested. Get each one working before going on to the next. Writing the
whole program before testing any of it is not the best approach.
2. Please put a program heading at the top of your program; here is the form:
* ------------------------------------------------------------
Programmer : Bill Gates
Date : April 30, 2020
Description : This program performs several functions with
an a
ay of Student records. This program
should work with any size a
ay
------------------------------------------------------------ */
Project #3
3. Please put function headings above all the functions (not the prototypes); here is the form:
* ------------------------------------------------------------
Function name
Description of what it does
Receives: what parameters does it get, and what do they represent?
Returns: what does the return value represent?
Requires: Any preconditions? Anything that must be true for this
XXXXXXXXXXfunction to work?
------------------------------------------------------------ */
void getNums(unsigned int nums[])
{
code here
4. Feel free to use these registers: eax, ebx, ecx, edx, esi, and edi.
5. Figure on the entire program taking 250 or so lines of code counting headings, spacing for
eadability, etc.
6. There will be a forum in Discussions for questions about this project. Any posts should clear
up questions about what the project is supposed to do, things I might have overlooked, etc.
It’s not a place to share solutions.
7. Please copy/paste your source code into a Word document named in this form:
Lastname, Firstname – Project 3.docx
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
using namespace std;
const int ARRAY_SIZE = 12;
there are 12 records in the file
const int NAME_SIZE = 25;
all names are < 25 chars
struct Student
{
char studentName[NAME_SIZE];
unsigned int test1, test2, test3, test4;
float average;
bool passing;
};
void getData(Student[]);
loads the a
ay with data from file
void print(Student[], Student);
show results
void findAverages(Student[]);
gets each student's avg based on 4 tests
void determinePassing(Student[]);
passing is an average >= 60
void getHighestStudent(Student[], Student &);
finds student with highest average
int main()
{
Student theClass[ARRAY_SIZE];
Student highest = { {"Nobody"}, 0,0,0,0,0,0 };
this strucure will hold top student's info
getData(theClass);
findAverages(theClass);
determinePassing(theClass);
getHighestStudent(theClass, highest);
NOTE: highest is a REFERENCE parameter!
print(theClass, highest);
}
void getData(Student theClass [])
{
ifstream infile;
char temp[NAME_SIZE];
temporary a
ay to read in names
infile.open("student_data.txt");
if (infile)
{
XXXXXXXXXXfor (int x = 0; x < ARRAY_SIZE; x++)
{
XXXXXXXXXXinfile.getline(temp, NAME_SIZE);
workaround to read in a
ay of chars
XXXXXXXXXXstrcpy(theClass[x].studentName, temp);
instead of a string
XXXXXXXXXXinfile
theClass[x].test1;
XXXXXXXXXXinfile
theClass[x].test2;
XXXXXXXXXXinfile
theClass[x].test3;
XXXXXXXXXXinfile
theClass[x].test4;
XXXXXXXXXXinfile.ignore();
}
XXXXXXXXXXinfile.close();
}
else