Your cart is currently empty!
Important Information about CSE 220 Homework Assignments Read the entire homework documents twice before starting. Questions posted on Piazza whose answers are clearly stated in the documents will be given lowest priority by the course staff. When writing assembly code, try to stay consistent with your formatting and to comment as much as…
Important Information about CSE 220 Homework Assignments
How Your CSE 220 Assignments Will Be Graded
With minor exceptions, all aspects of your homework submissions will be graded entirely through automated means. Grading scripts will execute your code with input values (e.g., command-line arguments, function ar- guments) and will check for expected results (e.g., print-outs, return values, etc.) For Homework Assignments
#2 and later you will be writing functions in assembly language. The functions will be tested independently of each other. This is very important to note, as you must take care that no function you write ever has side-effects or requires that other functions be called before the function in question is called. Both of these are generally considered bad practice in programming.
Some other items you should be aware of:
ming. This maximum instruction count will be increased in cases where a complicated algorithm might be necessary, or a large data structure must be traversed.
Assignment Objectives
The primary objectives of this homework assignment are to continue mastering array processing in MIPS, to be able to write functions in MIPS, and to apply MIPS register conventions.
Register Conventions
You must follow the register conventions taught in lecture and reviewed in recitation. Failure to follow them will result in loss of credit when we grade your work. Here is a brief summary of the register conventions and how your use of them will impact grading:
The following practices will result in loss of credit:
Getting Started
Visit Piazza and download the file hw2.zip. Decompress the file and then open hw2.zip. Fill in the following information at the top of hw2.asm:
Having this information at the top of the file helps us locate your work. If you forget to include this information but don’t remember until after the deadline has passed, don’t worry about it – we will track down your submission.
Inside hw2.asm you will find several function stubs that consist simply of jr $ra instructions. Your job in this assignment is implement all the functions as specified below. Do not change the function names, as the grading scripts will be looking for functions of the given names. However, you may implement additional helper functions of your own, but they must be saved in hw2.asm.
If you are having difficulty implementing these functions, write out pseudocode or implement the functions in a higher-level language first. Once you understand the algorithm and what steps to perform, then translate the logic to MIPS assembly code.
Be sure to initialize all of your values (e.g., registers) within your functions. Never assume registers or memory will hold any particular values (e.g., zero). MARS initializes all of the registers and bytes of main memory to zeroes. The grading scripts will fill the registers and/or main memory with random values before calling your functions.
Finally, do not define a .data section in your hw2.asm file. A submission that contains a .data section will receive a score of zero.
Preliminaries
In this assignment, you will familiarize yourself with a feature of the C programming language known as structs. A struct is a composite data type that is used to group variables under one name in a contiguous block of memory. You will be reading and writing arrays of structs that represents cars and car repairs. The * notation used in the struct definitions below is known as a pointer in C. A pointer is simply a memory address. The data type associated with the pointer identifies how the data should be accessed at the memory location that is specified by the pointer. For example, int * would signify the address of an integer located somewhere in memory.
The car Data Type
The car struct stores information about a particular car, identified by its 17-character VIN (vehicle identification number):
struct car {
string vin; // 4 bytes string make; // 4 bytes string model; // 4 bytes short year; // 2 bytes
byte features; // 1-byte bit vector
byte padding; // 1 byte of zero-padding
};
The meaning of each field:
◦ bit 0: is it a convertible (1) or not (0)?
◦ bit 1: is it hybrid (1) or not (0)
◦ bit 2: are the windows tinted (1) or not (0)?
◦ bit 3: is GPS built-in (1) or not (0)?
◦ bits 4-7 are unused
Note that the car struct contains 16 bytes, including 1 byte of zero-padding. Here is what a car struct might look like in MIPS:
# Data declarations from elsewhere in data.asm:
vin_03: .asciiz “1G1AK15F967719757” make_E: .asciiz “Mersaydeez” model_D: .asciiz “Road Hog”
# The car struct itself starts at label car_03:
car_03: .word vin_03 # vin_03 is the starting address of “1G1AK15F967719757” car_03_make_addr: .word make_E # make_E is the starting address of “Mersaydeez” car_03_model_addr: .word model_D # model_D is the starting address of “Road Hog” car_03_year: .byte 175, 7 # the year of manufacture: 175 + 7*256 = 1967 car_03_features: .byte 10 # a bit-vector of features (binary 1010_2)
.byte 0 # one byte of zero-padding
See the included data.asm file for sample car structs.
While working on the homework you might find it helpful to write a function that prints the contents of a car
struct to give you a human-readable form of the data structure.
The repair Data Type
struct repair {
car* car_ptr; // 4 bytes string desc; // 4 bytes short cost; // 2 bytes
short padding; // 2 bytes of zero-padding
}
The notation * indicates that the field is a pointer, i.e., the address of a car struct. The meaning of each field:
Note that the repair struct contains 12 bytes of data, including 2 bytes of zero-padding. Here is what a repair struct might look like in MIPS:
# A data declaration from elsewhere in data.asm:
repair_desc_A: .asciiz “fix cracked windshield”
# The car struct itself starts at label repair_05_car:
repair_05_car: .word car_03 # starting addr. of repaired car struct repair_05_desc_addr: .word repair_desc_A # address of repair string repair_05_cost: .byte 156, 1 # cost to repair the car: 156 + 1*256 = 412
.byte 0, 0 # two bytes of zero-padding
See the included data.asm file for sample repair structs.
How to Test Your Functions
Numerous .asm files have been provided to you for this assignment to help you test your work. However, note the following:
Using the provided main files is pretty simple. For example, suppose you wanted to test your index of car function from Part I of the assignment. First, make sure that in the Settings menu in MARS the option Initialize Program Counter to global ‘main’ if defined is checked. Then, open index of car main.asm, assemble it, and then run it. The main file will load the contents of your hw2.asm file and call your implemen-
tation of the index of car function.
The main files will provide some basic output, but it is your responsibility to dig deeper into the function outputs to make sure your implementations are correct. These main files will not be used in grading, and you should not submit them for grading. Submit only your hw2.asm file to Blackboard.
Finally, make sure that all code required for implementing your functions is included only in the hw2.asm file. To make sure that your code is self-contained, try assembling your hw2.asm file by itself in Mars. If you get any errors (such as a missing label), this means that you need to refactor (reorganize) your code, possibly by moving labels you inadvertently defined in a main file (e.g., a helper function) to hw2.asm.
Part I: Search for a Car by Year
int index of car(car[] cars, int length, int start index, int year)
This function searches an array of car structs starting at index start index and returns the index of the first car it finds that was manufactured in the given year. (That is, when multiple cars of the given year are found, the lowest index ≥ start index is returned.) Recall that each car struct is 16 bytes in size. Therefore, the starting addresses of consecutive structs are 16 bytes apart. As an example, suppose that cars[] starts at address 0x00100000. cars[0] begins at 0x00100000, cars[1] begins at 0x00100010, cars[2] begins at 0x00100020, etc.
The function takes the following arguments, in this order:
Returns in $v0:
Returns -1 in $v0 for error in any of the following cases:
Examples:
For the examples below, the cars argument is the all cars array provided in the data.asm file distributed with the homework. Refer to that file for the particular contents of the array. Be sure to test your function with different arguments ($a1, $a2, $a3) by modifying the index of car main.asm file.
Function Call | Return Value | Explanation |
index of car(all cars, 6, 0, 2017)
index of car(all cars, 6, 2, 2017) index of car(all cars, 6, 3, 2017) index of car(all cars, 6, 0, 1950) index of car(all cars, 6, -2, 2017) index of car(all cars, 0, 1, 2017) index of car(all cars, 6, 0, 1800) |
2
2 -1 -1 -1 -1 -1 |
car found
car found at/after start index car not found at/after start index no car found for given year invalid start index invalid length invalid year |
Part II: Compare Two Strings
int strcmp(string str1, string str2)
This function takes two null-terminated strings as arguments and returns an integer that indicates the lexicographic ordering of the strings. The function begins by comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached. Note that the strings can be of different lengths.
The function takes the following arguments, in this order:
Returns in $v0:
is the index of the first mismatch
Additional requirements:
Examples:
Function Call | Return Value | Explanation |
strcmp(“ABCD”, “ABCGG”) | -3 | First string is smaller; mismatch in middle |
strcmp(“WHOOP!”, “WHOA”) | 14 | First string is larger; mismatch in middle |
strcmp(“Intel”, “pentium”) | -39 | First string is smaller; mismatch at start |
strcmp(“STONY”, “BROOK”) | 17 | First string is larger; mismatch at start |
strcmp(“”, “mouse”) | -5 | First string is empty |
strcmp(“lonely guy”, “”) | 10 | Second string is empty |
strcmp(“Wolfie”, “Wolfie”) | 0 | Identical non-empty strings |
strcmp(“”, “”) | 0 | Two empty strings |
strcmp(“happy”, “Z”) | 14 | One argument is very short |
strcmp(“WOLF”, “WOLFIE”) | -73 | First string is substring of second string |
strcmp(“StonyBrook”, “Stony”) | 66 | Second string is substring of first string |
Part III: Copy a Memory Buffer
int memcpy(byte *src, byte *dest, int n)
The memcpy() function copies n bytes of data from address src to address dest. We may assume that the
dest buffer is at least n bytes in size.
The function takes the following arguments, in this order:
Returns -1 in $v0 for error in any of the following cases:
Additional requirements:
Examples:
Function Call | Return Value | Updated dest |
memcpy(“ABCDEFGHIJ”, “XXXXXXX”, 3)
memcpy(“ABCDEFGHIJ”, “XXXXXXX”, 7) memcpy(“ABCDEFGHIJ”, “XXXXXXX”, -3) memcpy(“ABCDEFGHIJ”, “XXXXXXX”, 0) |
0
0 -1 -1 |
“ABCXXXX”
“ABCDEFG” “XXXXXXX” “XXXXXXX” |
Part IV: Insert a car Struct into an Array
int insert car(car[] cars, int length, car new car, int index)
The insert car function inserts a new 16-byte car struct at index index of array cars, shifting the existing car at index index and all other cars 16 bytes to the right.
The function takes the following arguments, in this order:
Returns:
Additional requirements:
Examples:
Providing extensive examples in this document is not practical due to the nature of the array being manipu- lated, so only return values are given in the table below. You are strongly urged to use (and modify!) the insert car main.asm file provided with the homework materials to test your work. You will note that one complete test case is given in that file. The array after insertion is called expected all cars. Use your strcmp function from earlier in the assignment to compare the contents of all cars (from data.asm) with expected all cars after the insert car() function has been called.
Function Call | Return Value | Explanation |
insert car(cars array, 6, new car, 3)
insert car(cars array, 6, new car, 0) insert car(cars array, 6, new car, 6) insert car(cars array, -1, new car, 3) insert car(cars array, 6, new car, -1) insert car(cars array, 6, new car, 8) |
0
0 0 -1 -1 -1 |
new car inserted at index 3
new car inserted at start of array new car appended to array invalid array length invalid insertion index insertion index too large |
Part V: Find the Most Damaged Car
(int, int) most damaged(car[] cars, repair[] repairs, int cars length, int repairs length)
The most damaged() function finds the car in cars that has the highest total repair cost, returning both the index of that car in cars and its total repair cost. If there are multiple cars with the same total repair cost, the function returns the lowest of the indices.
The function takes the following arguments, in this order:
Returns:
The following are error cases:
Additional requirements:
Examples:
For the contents of the all cars array from data.asm, the returned index in $v0 should be 4 and the returned total repair cost in $v1 should be 587. You are strongly encouraged to modify the all repairs array to make additional examples yourself. This is very easy to do – simply change the cost of particular repair objects. Some examples to consider making: what if the array of repairs has only one item? what if two or more cars have the same total repair cost? what if all the cars have the same repair cost?
Part VI: Sort an Array of car Structs
int sort(car[] cars, int length)
The sort() function sorts an array of cars by year. The function must implement odd-even sort (which is a stable sorting algorithm) according to the following pseudocode:
def sort(cars): sorted = False while !sorted:
sorted = True
for(i = 1; i < cars.length – 1; i += 2):
if cars[i] > cars[i + 1]:
swap cars[i] and cars[i + 1]
sorted = False
for(i = 0; i < cars.length – 1; i += 2):
if cars[i] > cars[i + 1]:
swap cars[i] and cars[i + 1]
sorted = False
The function must use the stack for temporary space when swapping cars in the array. Again, you must use the
stack for temporary space – do not add a .data section to your hw2.asm file. The following pseudocode can be used to swap cars at indices i and j using the stack:
$sp -= 16 // make space on the stack for 1 car memcpy(cars[i], $sp, 16) // copy cars[i] onto the stack memcpy(cars[j], cars[i], 16) // copy cars[j] to cars[i]
memcpy($sp, cars[j], 16) // copy the temp car on the stack to cars[j]
$sp += 16
The function takes the following arguments, in this order:
Returns:
Additional requirements:
Example:
The all cars array given in sort data.asm contains the following cars, shown here in a more easily- readable form:
JTDKN3DU0D5614628 Fjord Wolfie-Z 2017 1000 <—-
2FMDK4JC5DBC37904 Hunday X27 2018 1000
1B4HR28N51F502695 Fjord Escapade 2017 1100 <—-
1G1AK15F967719757 Mersaydeez Road Hog 2018 1010
1HGEM1159YL037618 Fjord Elantris 2019 0101
5N1AR2MM2EC648945 Toyoter Raoden 2019 1010
1NKDX90X1WR777109 Honder Sazed 2019 0000
3FAHP0HA5CR371712 Fjord Scadrial 2017 1100 <—-
5J6TF2H55AL005521 Fjord Metalborn 2019 1010
1G4GC5G34FF231147 Fjord Terris Roadster 2018 0001
1B7HF16Z0XS322729 Honder Allomancer 2018 0100
1G1PC5SHXC7276485 Toyoter Stormlight 2019 1101
After sorting with the even-odd sorting algorithm, the cars will be in this order (given as sorted all cars in
data.asm):
JTDKN3DU0D5614628 Fjord Wolfie-Z 2017 1000 <—-
1B4HR28N51F502695 Fjord Escapade 2017 1100 <—-
3FAHP0HA5CR371712 Fjord Scadrial 2017 1100 <—-
2FMDK4JC5DBC37904 Hunday X27 2018 1000
1G1AK15F967719757 Mersaydeez Road Hog 2018 1010
1G4GC5G34FF231147 Fjord Terris Roadster 2018 0001
1B7HF16Z0XS322729 Honder Allomancer 2018 0100
1HGEM1159YL037618 Fjord Elantris 2019 0101
5N1AR2MM2EC648945 Toyoter Raoden 2019 1010
1NKDX90X1WR777109 Honder Sazed 2019 0000
5J6TF2H55AL005521 Fjord Metalborn 2019 1010
1G1PC5SHXC7276485 Toyoter Stormlight 2019 1101
Since the even-odd sorting algorithm is stable, cars with equal years in the original array appear in the same order in the sorted array. We have put an arrow next to the cars manufactured in 2017 to help illustrate the idea.
Part VII: Find the Most Popular Car Feature
int most popular feature(car[] cars, int length, nibble features)
The most popular feature() function determines the most popular feature amongst the ones defined in features. features is a bit vector specifying which of the features to consider when calculating the most popular feature (1 means consider, 0 means do not consider). The bit positions in the features argument are assigned these meanings, which correspond with those of the car structs:
Bit Position | What a 1 in This Bit Position Means |
0
1 2 3 |
Count the # cars that are convertibles
Count the # cars that are hybrids Count the # of car that have tinted windows Count the # of cars that have GPS built-in |
The function takes the following arguments, in this order:
Returns:
Returns -1 for error in any of the following cases:
that are being considered). Additional requirements:
Examples:
Consider the following function call: most popular feature(all cars, 6, 7). The third argument,
01112 in binary, indicates that we will count how many cars are convertibles (bit 0 is 1), how many cars are hybrid (bit 1 is 1), and how many cars have tinted windows (bit 2 is 1). We will not count cars that have a GPS because bit 3 is 0. When we call the function with these arguments for the cars in data.asm, the return value is 4, 01002 in binary. Bit 2 is associated with tinted windows. This means either that (1) of the three features we considered, tinted windows was the most popular feature, or, (2) there was a tie in the counts for tinted windows and some other feature, but we reported tinted windows as the “winner” because it has higher precedence than hybrid engines or a convertible roof.
As another example, suppose we performed a search with 00112 as the feature vector, but no cars are hybrids or have convertible roofs. In this case, both of those counts are zeroes, and so the function returns -1 to indicate an error.
So to summarize, there are only 5 valid return values: -1, 1, 2, 4 or 8. Do you see why?
Function Call | Return Value |
most popular feature(all cars, 6, 15)
most popular feature(all cars, 6, 7) most popular feature(all cars, 6, 3) most popular feature(all cars, 6, 5) most popular feature(all cars, 6, 1) most popular feature(all cars, 6, 0) most popular feature(all cars, -1, 14) |
8
4 2 4 1 -1 -1 |
Part VIII: Compute a VIN’s Check Digit
char compute check digit(string vin, string map, string weights, string transliterate str)
The compute check digit() function computes the check digit for a valid VIN according to the following pseudocode:
def transliterate(ch, transliterate_str):
return transliterate_str.index_of(ch) % 10
def compute_check_digit(vin, map, weights, transliterate_str):
sum = 0
for (i = 0; i < 17; i++):
sum += transliterate(vin.charAt(i), transliterate_str) *
map.index_of(weights.char_at(i))
return map.char_at(sum % 11)
Implementing separate functions for transliterate, char at, and index of is not required, but is rec- ommended to make your code easier to debug.
The function takes the following arguments, in this order:
Returns:
Additional requirements:
Examples:
In the table below, transliterate str has been abbreviated trs to save space.
Function Call | Return Value |
compute check digit(“JTDKN3DU0D5614628”, map, weights, trs) | 0 |
compute check digit(“1B4HR28N01F502695”, map, weights, trs) | 5 |
compute check digit(“1HGEM1150YL037618”, map, weights, trs) | 9 |
compute check digit(“1FTDF15N0KNB73611”, map, weights, trs) | 3 |
compute check digit(“1M2P198C0JW002996”, map, weights, trs) | 5 |
Academic Honesty Policy
Academic honesty is taken very seriously in this course. By submitting your work to Blackboard you indicate your understanding of, and agreement with, the following Academic Honesty Statement:
How to Submit Your Work for Grading
To submit your hw2.asm file for grading:
Oops, I messed up and I need to resubmit a file!
No worries! Just follow steps 4–6 again. We will grade only your last submission.