, , , , ,

[SOLVED] Cit593 module 12-dynamic memory and file i/o

$25

File Name: Cit593_module_12_dynamic_memory_and_file_i_o.zip
File Size: 414.48 KB

5/5 - (1 vote)

The LC4 Disassembler: Dynamic Memory and File I/O Instructions

Assignment Overview ………………………………………………………………………………………………….. 3
Learning Objectives …………………………………………………………………………………………………….. 3
Advice ……………………………………………………………………………………………………………………….. 3
Getting Started ……………………………………………………………………………………………………………. 4
Codio Setup ………………………………………………………………………………………………………….. 4
Starter Code ………………………………………………………………………………………………………….. 4
Object File Format Refresher …………………………………………………………………………………… 5
Linked List Structure……………………………………………………………………………………………….. 5
Requirements …………………………………………………………………………………………………………….. 6
General Requirements ……………………………………………………………………………………………. 6
Disassembler ………………………………………………………………………………………………………… 6 lc4_memory.c: add_to_list ………………………………………………………………………………….. 6 lc4_memory.c: search_opcode ……………………………………………………………………………. 7 lc4_memory.c: search_address …………………………………………………………………………… 7 lc4_memory.c: print_list ……………………………………………………………………………………… 7 lc4_memory.c: delete_list …………………………………………………………………………………… 7 lc4.c: main ……………………………………………………………………………………………………….. 8 lc4_loader.c: open_file ……………………………………………………………………………………….. 8 lc4_loader.c: parse_file ………………………………………………………………………………………. 8 lc4_disassembler.c: reverse_assemble ………………………………………………………………… 8
Extra Credit …………………………………………………………………………………………………………… 9
Collaboration …………………………………………………………………………………………………………… 10
Collaboration Options ……………………………………………………………………………………………. 10
Collaboration Requirements …………………………………………………………………………………… 10
Collaboration Tips ………………………………………………………………………………………………… 11 Suggested Approach………………………………………………………………………………………………….. 13
High Level Overview …………………………………………………………………………………………….. 13
Great High Level Overview, but I really need a Slightly More Detailed Overview …………….. 14
Implement the LinkedList ………………………………………………………………………………….. 14
Setup the main Function …………………………………………………………………………………… 14
Implement the LC4 Loader ……………………………………………………………………………….. 15
Implement the Disassembler …………………………………………………………………………….. 17
Putting It All Together ………………………………………………………………………………………. 18
Testing …………………………………………………………………………………………………………………….. 19
Files for Testing ……………………………………………………………………………………………………. 19
Unit Testing …………………………………………………………………………………………………………. 19
GDB for Debugging ………………………………………………………………………………………………. 19
Segmentation Faults Demystified ………………………………………………………………………. 20
Valgrind for Memory Leaks and Memory Management Errors ……………………………………… 21
Submission ………………………………………………………………………………………………………………. 22
README file ……………………………………………………………………………………………………….. 22
Submission Check ……………………………………………………………………………………………….. 22
Consistency Checks ……………………………………………………………………………………………… 22
The Actual Submission ………………………………………………………………………………………….. 22
Grading …………………………………………………………………………………………………………………… 22
Disassembler ………………………………………………………………………………………………………. 23
Makefile …………………………………………………………………………………………………………. 23
Unit Tests ………………………………………………………………………………………………………. 23
Integration Tests ……………………………………………………………………………………………… 23
Valgrind deductions …………………………………………………………………………………………. 23
Extra Credit ……………………………………………………………………………………………………. 24
Flowchart …………………………………………………………………………………………………………………. 25
FAQ ………………………………………………………………………………………………………………………… 26
Quick Hints ………………………………………………………………………………………………………….. 26
Useful Commands ………………………………………………………………………………………………… 26
Programming Tips ………………………………………………………………………………………………… 26
Endianness …………………………………………………………………………………………………………. 27
Resources ………………………………………………………………………………………………………………… 27

Assignment Overview
In the last assignment, you created a .obj object file from a .asm assembly file.
In this assignment, you will write a program that opens and reads a .obj file created by PennSim, parses it, and loads it into a linked list representing the LC4’s program and data memories (similar to what PennSim’s “loader” does). Additionally, you will be able to convert the binary file contents back to the assembly it came from! This is known as reverse assembling or disassembling.

Learning Objectives
This assignment will cover the following topics:
â—Ź Review the LC4 Object File Format
â—Ź Implement a LinkedList in C
â—Ź Read and process binary files
â—Ź Disassemble binary data into a human-readable format
â—Ź Use debugging tools such as GDB and Valgrind
â—Ź (Optionally) Collaborate with another programmer on a complex project

Advice
â—Ź Read this entire document before starting.
â—Ź Read this entire document before starting.
â—Ź Start on this project early.
â—Ź Find a collaboration partner, even if you decide to do the assignment solo.
â—Ź Attend recitation, or watch the recordings.

Getting Started
Codio Setup
Open the Codio assignment via Canvas. This is necessary to link the two systems.
You will see many files; the directory “obj files for student testing” contains a selection of sample object files you can use for testing your program. Do not assume that we will use these exact files for grading (we won’t). You will need to move these to the root directory in order to test with them.

Starter Code
We have provided a basic framework and several function definitions that you must implement.
lc4.c – must contain your main function.
lc4_memory.c – must contain your linked list helper functions.
lc4_memory.h – must contain the declaration of your row_of_memory structure
– must contain the declarations of your linked list helper functions
lc4_loader.h – must contain your loader function declarations
lc4_loader.c – must contain your .obj parsing function
lc4_disassembler.h – must contain your disassembler function declarations
lc4_disassembler.c – must contain your disassembling function
Makefile – must contain the targets:
lc4_memory.o lc4_loader.o lc4_disassembler.o lc4 all, clean, and clobber

Object File Format Refresher
The following is the format for the binary .obj files created by PennSim from your .asm files. It represents the contents of memory (both program and data) for your assembled LC-4 Assembly programs. In a .obj file, there are 3 basic sections indicated by 3 header “types” = Code , Data, and Symbol:
â—Ź Code: 3-word header (xCADE, <address>, <n>), n-word body comprising the instructions. â—‹ This corresponds to the .CODE directive in assembly.

â—Ź Data: 3-word header (xDADA, <address>, <n>), n-word body comprising the initial data values.
â—‹ This corresponds to the .DATA directive in assembly.

● Symbol: 3-word header (xC3B7, <address>, <n>), n-character body comprising the symbol string. These are generated when you create labels (such as “END”) in assembly. Each symbol is its own section.
â—‹ Each character in the file is 1 byte, not 2 bytes.
â—‹ There is no NULL terminator.

Linked List Structure
In the file lc4_memory.h, you’ll see the following structure defined:

Because you will not know the number of instructions in advance, you will create a Linked List of row_of_memory nodes, each node representing a single row of memory.

Requirements
General Requirements
â—Ź You MUST NOT change the filenames of any file provided to you in the starter code.
â—Ź You MUST NOT change the function or struct declarations of any function or struct provided to you in the starter code.
â—‹ You MUST NOT to not add any additional .c source or .h header files â—Ź Your program MUST compile when running the command make.
â—Ź You MUST NOT have any compile-time errors or warnings.
â—Ź You MUST test your code with Valgrind before submission. Valgrind MUST report 0 errors and 0 memory leaks. See the details in the Valgrind section for required details.
â—Ź You MUST remove or comment out all debugging or error message print statements before submitting.
â—Ź You MUST follow the requirements in the Collaboration section, even if working alone.
â—Ź You MUST NOT use externs or global variables.
â—Ź Your program MUST be able to handle .obj files produced by PennSim.
â—Ź You SHOULD comment your code since this is a programming best practice. â—Ź You MUST follow the individual requirements for the functions (below).

Disassembler
You MUST follow the requirements in the source files provided as starter code.
lc4_memory.c: add_to_list
This function adds a new row_of_memory node to the LinkedList.
â—Ź If a node with the specified address already exists in the LinkedList, this function
MUST update the contents field and take no other action
â—Ź Otherwise, this function MUST
â—‹ allocate space for a new node,
â—‹ set the address and contents fields based on the function arguments,
â—‹ set the label and assembly fields to NULL,
â—‹ not allocate memory for the label or assembly fields
â—Ź If the head pointer is NULL, this function MUST set the newly created node as the head of the LinkedList.
â—Ź Otherwise, this function MUST insert the newly created node into the LinkedList based on the address field in ascending order
â—Ź This function MUST return 0 for success, and SHOULD -1 if malloc fails

lc4_memory.c: search_opcode
This function searches the LinkedList until it finds a node where the opcode field matches the opcode argument AND the assembly field is NULL.
â—Ź For this function, the opcode to check for is the four least significant bits of the opcode argument and ranges from 0 to 15 inclusive.
â—Ź This function MUST traverse the LinkedList starting from the head.
â—Ź If it finds a node where the opcode to check for matches the four most significant bits of the opcode field AND the assembly field is NULL, then it MUST return a pointer to this node.
â—Ź This function MUST return NULL if no matching node is found in the LinkedList.
â—Ź This function MUST return NULL if the LinkedList is empty.
lc4_memory.c: search_address
This function searches the LinkedList until it finds a node where the address field matches the address argument.
â—Ź This function MUST traverse the LinkedList starting from the head.
â—Ź If it finds a node where the address to check for matches the address field, then it MUST return a pointer to this node.
â—Ź This function MUST return NULL if no matching node is found in the LinkedList.
â—Ź This function MUST return NULL if the LinkedList is empty.
lc4_memory.c: print_list
This function prints the LinkedList in a specific format.
â—Ź If the head pointer is NULL, this function MUST take no action
â—Ź This function MUST print a column title; see the Putting It All Together section for an example header.
â—Ź This function MUST print a single line for each node.
â—Ź If attempting the extra credit, it MUST NOT print the assembly field for nodes where the opcode of the contents is not 0001.
â—Ź It MUST print the address and contents fields in hexadecimal with leading zeroes (4 characters wide).
â—Ź It MUST print ONLY the memory list.
â—Ź The registers in assembly instructions SHOULD be separated by a comma
â—‹ e.g. ADD R1, R2, R3
â—Ź If the contents of a node are 0, it MUST print them as 0 or 0000.
â—Ź If the assembly of a node is NULL, it MUST print the assembly as (null) or leave it blank
â—Ź It MUST print the label when one exists, otherwise it MUST leave the section blank.

lc4_memory.c: delete_list
This function deletes the LinkedList node by node.
â—Ź This function MUST correctly free all allocated memory for each node â—Ź This function MUST set the head pointer to NULL upon deletion

lc4.c: main
The main function MUST follow the steps outlined in the starter code.
â—Ź It MUST hold the row_of_memory* memory (do not modify this line).
â—Ź It MUST NOT call malloc at any point.

lc4_loader.c: open_file
This function opens a file for reading.
â—Ź It MUST attempt to open the file file_name.
â—‹ If the file exists, it MUST open the file and return a FILE* to the opened file. â—‹ Otherwise, it MUST return NULL.
â—Ź You MUST NOT attempt to append .obj to the provided file_name

lc4_loader.c: parse_file
This function parses a LC4 .obj file.
â—Ź It MUST correctly handle endianness. That is, it MUST adjust for reading 16-bit words from the file. It MUST handle the .obj files that PennSim produces.
â—Ź For each 3-word header in the file, it MUST
â—‹ read the 3-word header,
â—‹ parse the <directive>, <address>, and <n> words and correctly determine the type of header and memory to allocate,
â—‹ read the remaining <n> words or bytes,
â—‹ create a new row_of_memory node,
â—‹ add the new node to the LinkedList (using the lc4_memory functions) â—Ź After reading the file, it MUST
â—‹ close the file
â—‹ return 0

lc4_disassembler.c: reverse_assemble
This function disassembles each node to generate a value for the assembly field.
â—Ź It MUST search every node in the LinkedList.
● If the node’s address is in a CODE region, then it MUST do the following:
â—‹ If the opcode is 0001, it MUST
â–  translate the contents field into the human-readable instruction mnemonic,
â–  allocate space to hold the instruction string, and
â–  store the string into the assembly field
● If the node’s address is not in a CODE region, then it MUST NOT attempt disassembly
â—Ź It MUST provide an actual label when translating a Branch or Jump instruction into assembly language, not an immediate value. So JMP END, NOT JUMP #18.
â—‹ Note that this only applies for extra credit attempts.
â—Ź After checking all nodes, it MUST return 0.

Extra Credit
For optional extra credit, build the complete LC4 Disassembler. Your program MUST fulfill these additional requirements, while still fulfilling all the requirements for the rest of the assignment: â—Ź finish the disassembler to translate all instructions in the ISA.
â—Ź create a new output file <user_input>.asm, where <user_input> is the name of the object file without the extension (i.e. create a new file with the .obj extension)
â—Ź write the equivalent LC4 assembly of the object file to this new output file
â—Ź PennSim MUST be able to assemble this file
â—Ź PennSim MUST be able to load this file into memory
â—Ź PennSim MUST show that the loaded contents your assembled file and the original object file are equivalent

Collaboration
You are not required to have a teammate. Points will not be deducted if you choose to work alone. If you would like to work as a team, you MUST only have one teammate. Groups of 3 or more are not permitted.
Collaboration Options
You have three Options for collaboration:
1. No collaboration
Complete the assignment independently. You must include a README file that states you worked completely alone.

2. Collaboration and submit the same code
After each teammate completes their LinkedList functions, you are free to split up the remainder of the work as you see fit. You can work on everything together or each team member can work on part of the project. Both partners turn in the same code and will receive the same grade. You must include a README file indicating you are submitting the same code, identifying both students, and detailing how you chose to divide up the work (e.g. who contributed what for each function).

3. Collaboration and submit different code
Collaboration Requirements
If you choose to work as a team, each team member MUST follow these additional assignment requirements:
1. Each team member must complete all 5 functions supporting the LinkedList data structure independently.

You will likely find that you need to make changes to your lc4_memory.c source file as a result of tests conducted by you and your partner. Implementing the LinkedList functions on your own is an invaluable learning experience, but once you have completed the functions, you are free to discuss them with your partner and refine the final version for submission.

3. Each function MUST include a comment at the top with the name of the person who authored it.
If there is anything more you think we should know about your submission, it should be included in your README file.

4. Each team must submit a brief README file that describes which Collaboration Option you chose and your division of labor.
If you are doing Option 1, you MUST indicate that you worked alone.
If you are doing Option 2, you MUST include both your and your teammate’s names and specify who wrote each function.
If you are doing Option 3, you MUST to include both your and your teammate’s name and a brief (a few sentences max) description of how you worked together.

The README should not be more than one page in length.

We strongly recommend that you and your teammate work together to test, debug, and fix memory leaks in your code.
Collaboration Tips
Here are some suggestions to discuss with your partner before starting. These are ideas that other students have found helpful but they are not required.
â—Ź Discuss your preferred communication platforms.
Do you like to use Slack? Email? Text messages? Regular video calls on Slack or Zoom? Pick something you will be able to check daily to help your collaborator with debugging challenges as they arise.

â—Ź Most people appreciate updates about when you plan to work on the assignment. Letting your teammate know that you plan to do most of your work over the weekend, for example, demonstrates a commitment to the work and helps set expectations for people with different working schedules. If you prefer to leave work until the last minute, your teammate deserves to know this (we recommend starting as early as possible).

â—Ź Assign roles as soon as possible.
It should be clear who is responsible for writing which sections of the code before you start the project. Consider writing the README first and updating it if necessary.

â—Ź Review the assignment instructions (again).
Consider which parts you think will be the most challenging and which parts you feel the most confident in. Try to split up the work so that each person has at least one challenging section and one section they feel confident in. This allows each person to contribute their individual skills while also having opportunities to learn new things.

â—Ź Plan to check in multiple times.
This is a large project and it won’t be done in a few hours and probably not in a few days.

â—Ź Plan at least one day to debug and fix memory leaks before turning in the assignment.
While you will be primarily graded on functionality, it is important that you learn to use malloc and free correctly and that you learn to use Valgrind to find and eliminate any memory leaks. Code that contains memory leaks will not receive full credit.

â—Ź Whenever possible, try to explain your work to your teammate in your own words. Explaining your code to someone else is a great learning tool for both people!

â—Ź Back up your work to Codio frequently.

â—Ź Check in with your teammate before making changes to code your teammate has written.

â—Ź Communicate when asking for an extension.

Suggested Approach
This is a suggested approach. You are not required to follow this approach as long as you follow all of the other requirements.
High Level Overview
Follow these high-level steps and debug thoroughly before moving on to the next.
1. Create a pointer-based framework in C to hold a LinkedList by writing the following functions:
a. A function to create a new node in the LinkedList. If this is the first node in the list, this function will create a new list. If there is already an identical node in the list, this function will update the contents of that pre-existing node.

b. A function to search the LinkedList for a node with a specific memory address value.

d. A function to print the elements of the list in the specified format.

e. A function to delete the entire list and free the memory it was using.

2. Write the open_file function to open a .OBJ file specified by the user via the command line.

3. Write the parse_file function to extract information from the open file, place the information into your LinkedList, and close the file.

4. Write the reverse_assemble function to update each node in your LinkedList with the assembly language equivalent of the binary strings extracted by parse_file.

5. Print your LinkedList.

6. Debug and resolve any lingering memory leaks and other memory management errors.

Great High Level Overview, but I really need a Slightly More Detailed Overview
Okay, I guess we can give some more details.
Implement the LinkedList
The first thing to do is to get the LinkedList working, that is, create the list, place new nodes into the correct position, etc.
The first files to view in the helper file are lc4_memory.h and lc4_memory.c. In these files you will notice the structure that represents a row_of_memory as referenced in the LinkedList section. You will also see several helper functions that will serve to manage a LinkedList of rows_of_memory nodes.
Your job is to implement these LinkedList helper functions using your knowledge from the last assignment. You must implement everything described by the comments in the starter code
If you wish to implement additional helper functions, feel free to add them to any .c source file but remember to add the function prototypes to the appropriate .h header file.

Setup the main Function
Accept arguments and pass them to the functions. Set up the general flow of high-level functions.
Switch to modifying the file called lc4.c. This serves as the main function for the entire program.
The head of the linked list must be stored in main. Notice that a pointer named memory will do just that.
main then extracts the name of the .obj file the user has passed in when they ran your
program (this is in the argv[] parameter).
Next, it calls lc4_loader.c’s open_file function and holds a pointer to the open file.
Then, it calls lc4_loader.c’s parse_file function to read and interpret the .obj file.
Lastly, it disassembles the file, prints the LinkedList to the terminal, deletes the LinkedList, and finally terminates the program.
All of these functions are described in greater detail in later subsections.

We have provided the order of the function calls and their purpose as shown in comments in the lc4.c. Once you have properly implemented lc4.c and have it accept input from the
command line, a user should be able to run your program as follows:

./lc4 <my_file>.obj
where <my_file> can be replaced with any file name the user desires as long as it is a valid .obj file that was created by PennSim. If no file is passed in, your program should generate an error telling the user what went wrong, like this:

error1: usage: ./lc4 <object_file>.obj

Implement the LC4 Loader
The loader is responsible for reading a file, parsing each line, and creating/modifying nodes. Most of the work of your program will take place in the file: called lc4_loader.c.
In this file, start by implementing the function open_file to take in the name of the file the user of your program has specified on the command line (see lc4_loader.h for the definition of open_file). If the file exists, the function should return a handle to that open file, otherwise a NULL should be returned.
As shown in the Flowchart, have the function read in the 3-word header from the file. You’ll notice that all of the LC4 .obj file headers consist of 3 fields: <type>, <address>, and <n>. As you read in the first header in the file, store the address and the <n> field into local variables. Then determine the type of header you have read in: CODE, DATA, or SYMBOL. The CODE header
The body of the CODE section is <n>-words long. This is a sample CODE section:
CA DE 00 00 00 0C 90 00 D1 40 92 00 94 0A 25 00 0C 0C 66 00
48 01 72 00 10 21 14 BF 0F F8

Notice the field for <n> is 0x000C, or decimal 12. Because each instruction in LC4 is 1 word long, this indicates that the next 12 words in the .obj file are 12 LC4 instructions.
The first LC4 instruction in the 12-word body is: 0x9000 which is a CONST assembly instruction if you convert to binary.
Allocate memory for a new node in your linked list to correspond to the first instruction. As it is the first instruction in the body, and the address has been listed as 0x0000, you would populate the row_of_memory structure as follows:

address 0000
label NULL
contents 9000
assembly NULL
next NULL
In a loop, read in the remaining instructions from the .obj file; allocate memory for a corresponding row_of_memory node for each instruction. As you create each row_of_memory, add these nodes to your linked list, ordering the list by address (you should use the functions you’ve created in lc4_memory.c to help you with this).
For the first 3 instructions listed in the sample above, your linked list would look like this:

The DATA Header
The procedure for reading in the DATA sections is identical to reading in the CODE sections. These would become part of the same linked list since PROGRAM and DATA are all in one memory on the LC4; they are partitioned by address.

The SYMBOL Header
For the following SYMBOL header/body:

C3 B7 00 00 00 04 49 4E 49
54

The address field is: 0x0000. The symbol field itself is 0x0004 bytes long. The next 4 bytes 0x49 0x4E 0x49 0x54 are ASCII for INIT. This means that the label for address: 0000 is INIT. Your program must search the LinkedList nodes, find the appropriate address that this label is referring to, and populate the label field for the node. Note: <n> tells us exactly how much memory to malloc to hold the string, however, you must add a byte to hold the NULL terminator. For INIT, this means you need to allocate 5 bytes. For the example above, the node 0000 in your LinkedList, would be updated as follows:

address 0000
label INIT
contents 9000
assembly NULL
next

It is possible that an address has two labels in the .obj file. In this case, use the last one that appears in the .obj file.
Once you have read the entire file, created and added the corresponding nodes to your LinkedList by address order, close the file and return to main. If you encounter an error in closing the file, print an error, free all the memory associated with the LinkedList, and then exit the program.

Implement the Disassembler
Go through the row of memory nodes and update the assembly field based on the contents.
In lc4_disassembler.c, write a third function reverse_assemble that will take as input memory the head of the LinkedList populated in the previous section. reverse_assemble must translate the hexadecimal representation of selected instructions into their assembly equivalent. Refer to the LC4 ISA Instruction document for details.
To simplify this problem a little, do not translate every single instruction into its assembly equivalent. Only translate instructions with the opcode of 0001, that is, ADD REG, MUL, SUB, DIV, and ADD IMM.
The immediate value MUST be prefixed with #, x, or X, (as appropriate), for example ADD R1, R1, #10 == ADD R1, R1, xF == ADD R1, R1, XF
Do not translate data stored at an address in the DATA section.
As shown in the flowchart, this function will call your linked list’s search_opcode helper function. Your search_opcode function should take as input a 4-bit value representing the opcode to search for and return the first node in the LinkedList that matches the opcode and also has a NULL assembly field.
For example, here’s the definition of an ADD instruction from the ISA:
0001 ddds ss00 0ttt
When searching for an opcode instruction with opcode == 0001, the opcode parameter passed to search_opcode must be:
0000 0000 0000 0001
So you will need to use the C-bitwise operators to line these two values up before comparing them.
search_opcode finds the first instruction in the LinkedList where these two 4-bit fields match with that additional constraint that rows_of_memory that already have the assembly instruction filled in doesn’t count as a match.
When/if a node in your linked list is returned, you’ll need to examine the contents field of the node and translate the instruction into its assembly equivalent. Once you have done that, allocate memory for the ASCII string and store this string in the assembly field of the node. Repeat this process until all the nodes in the LinkedList with an opcode == 0001 have their assembly fields properly translated.
As an example, the figure below shows a node on your list that has been “found” and returned when the search_opcode function was called.

From the contents field, we can see that the hexadecimal value 0x128B which is 0001 001 010 001 011 in binary. From the ISA, we realize the sub-opcode reveals that this is actually a MUL instruction. We can then generate the string “MUL R1, R2, R3” and store it back in the node in the assembly field. For this work, we strongly encourage you to investigate the switch statement in C (any good book on C will help you understand how this works and why it is more practical than multiple if/else/else/else statements).

Putting It All Together
One last thing to do in main is to call a function to print the contents of your LinkedList to the screen. So call the print_list function in lc4_memory.c. You will need to implement the printing helper function to display the contents of your lc4’s memory list like this:

<label> <address> <contents> <assembly>
INIT 0000 9000
0001 D140
0002 9200
…
0009 128B MUL R1, R2, R3
END 000A 0
(and so on…)

Testing
Files for Testing
In the last assignment, you created a .obj file. Try loading that file into the Codio workspace for this assignment and use your lc4 program on it. You know exactly how that program should disassemble.
To test further, bring up PennSim, write a simple program in it, output a .obj from PennSim, then read into your program and see if you can disassemble it. You can create a bunch of test cases very easily with PennSim.
You should test your lc4 program on a variety of .obj files, not just simple examples. We have provided a selection of .obj files in the “obj files for student testing” folder in the Codio workspace. Additionally, this directory contains .sol solution file which are the expected output. You can compare the expected output to your output to see if you are getting the expected results.
From the default home workspace directory (when the terminal prompts ends with ~, you will need to use cd submit to change the directory to the submit directory.

Unit Testing
When writing such a large program, it is a good strategy to “unit test.” This means, as you create a small bit of working code, compile it, and create a simple test for it.
As an example, once you create your very first function: add_to_list, write a simple main and test it out. Call it, print out your “test” list, and see if this function even works. Run valgrind on the code, see if it leaks memory or accesses uninitialized memory locations. Once you are certain it works, and doesn’t leak memory, go on to the next function search_address, implement that, and test it out.
DO NOT write the entire program, compile it, and then start testing it. You will never resolve all of your errors this way. You need to unit test your program as you go along or it will be impossible to debug.

GDB for Debugging
gdb allows you to inspect the actual contents of memory which is an advantage over print statements because print statements only print ASCII characters. Further, you can see the actual contents of memory of any variable at any time, while print statements only print when you call the print statement during the execution of your program.
Segmentation Faults Demystified
Segmentation faults are VERY common failures in C programs. They can be hard to pin down. First we should understand why they happen:
1. Case 1: trying to dereference a NULL pointer. This often happens when calling a function that returns a pointer or NULL in case of error. If you don’t check the return value from the function and then proceed to dereference the pointer, you will get a segmentation fault.

2. Case 2: an incorrect assumption that memory on the stack (and heap) is initialized to zero. This is NOT the case. If you want the memory to be initialized to zero, you need to do this explicitly, possibly using the memset function. You might have code that checks to see if the memory is 0 or NULL and then take some action based on this. If the memory is not initialized to zero, it will have random, unpredictable contents. This is often referred to as (X) or “don’t care” in the lectures.

So, how do you figure out where the segmentation fault is occurring? The simplest way to find out is using GDB. After compiling using the -g option and running the program, run the program with arguments (the gdb commands start and run allow you to specify the command line arguments), and you should go right to the segmentation fault. You can then use the gdb where command which will tell you the line number in your program where the failure occurs.

For example:
gdb -q -tui –args ./lc4 test1.obj
(gdb) run

runs gdb on your lc4 program with argv[1] set to test1.obj

Valgrind for Memory Leaks and Memory Management Errors
Prior to exiting your program, you MUST properly free any memory that you allocated. We will be using a memory-checking program known as valgrind to ensure your code properly releases all memory allocated on the heap. Simply run your program, lc4, as follows:
valgrind –leak-check=full –track-origins=yes ./lc4 test1.obj
where valgrind is the name of the program to run,
–leak-check=full is a Valgrind option to perform the full memory leak analysis,
–track-origins=yes is a Valgrind option to show you where some errors originate from,
./lc4 is the name of the program that Valgrind will analyze, and test1.obj is the argument to your lc4 program, i.e. the name of the .obj file you want to disassemble.

â—Ź Valgrind will find errors related to accessing uninitialized memory locations (invalid read/write errors). This typically results from assuming that malloc zeroes out the memory it returns. malloc DOES NOT do this.

Submission
README file

Submission Check
There is a single “submission check” test that runs once you upload your code to Gradescope. This test checks that you have submitted all required files and also that your program compiles and any autograder code compiles successfully. It does not run your program or provide any feedback on whether it works or not. This check just ensures that all the required components exist. This test is performed after uploading to Gradescope.

Consistency Checks

The Actual Submission
You will submit this assignment to Gradescope in the assignment entitled Assignment 12: The LC4 Disassembler.
Download the required .c source and .h header files (as well as any additional helper files required) as well as your Makefile and README from Codio to your computer, then upload all of these files to the Gradescope assignment. Do not not submit intermediate files (anything .o).
We will only grade the last submission uploaded.
If you are working with a partner, you MUST also click the “View or edit group” link in the upper right of the submission page to add your partner. We will adjust these based on the README content, but give your partner peace of mind by including them at submission time.
Do not mark your Codio workspace complete. Only the submission in Gradescope will be used for grading purposes.

Grading
We will only grade the last submission, regardless of the results of any previous submission.
We will not be providing partial credit for autograder tests.
Disassembler
We will only use valid, disassemblable .obj files. We will not test your program with deliberately faulty .obj files.
Makefile
05 points
As part of the submission check, the autograder will ensure that you have submitted all the required files and that makefile correctly creates the final executable.
Unit Tests
50 points
The autograder will test your open_file, add_to_list, delete_list, search_address, search_opcode, and reverse_assemble functions by providing inputs directly to these functions. The autograder will deduct points if they do not produce the correct output.
Integration Tests
45 points
Valgrind deductions

Extra Credit
The Extra Credit is worth 15 percentage points so the highest grade on the assignment is 115%.
Your extra credit MUST NOT break functionality for the non-extra credit requirements. Make a backup of your finalized program before attempting the extra credit. If your program fails to meet the basic requirements, you will end up losing more points than the extra credit would gain.
There is no partial credit. It must work completely for any credit.
We will not give guidance on how to do this since it is designed to be capstone challenge problem.

Flowchart

FAQ
Quick Hints
â—Ź You can assume that the maximum length of an assembly instruction is 100, the maximum length of a label is 70 and the maximum length of a file_name is 100. â—Ź Make sure all of your loops that traverse the memory list look at the first and last element of the memory list. This is a VERY common mistake.
â—Ź You do not have to check that the addresses in the .obj file are valid. That is, addresses for CODE memory will always be after a .CODE directive, and addresses for DATA memory will always be after a .DATA directive. Essentially, all test files will be valid LC4 object files.
Useful Commands
â—Ź The hexdump -C command displays an .obj file one byte at a time rather than one word at a time. The first column displayed by hexdump is the byte offset.
Programming Tips
â—Ź There are many possible errors and we will not check them. But you should as part of debugging and ensuring your program does have the correct output. Some example errors:
○ the input file isn’t validly formatted
○ malloc can’t find sufficient memory
â—‹ etc
It is a best practice to print an error message and exit if any of those things happen but the autograder will not be testing those sort of edge cases.
â—Ź While we want your program to have no memory leaks, it is more important that your program actually runs. Get the program working, then go back and fix memory leaks.
â—Ź You must allocate memory for strings before calling strcpy.
● add_to_list must keep the memory list in sorted order by address. CODE vs. DATA isn’t relevant.
will be FALSE. This means that you need to check all of your calls to fread or fgetc to make sure they didn’t hit the end of the file.
Endianness
● The x86 (the processor used by Codio) has a different endianness than the LC4. When doing fread’s of 2 byte words, swapping occurs to adjust for this. That same swapping doesn’t occur with the fgetc or fread’s with size 1.
● If you read the .obj file into memory one word at a time using fread, you will need to swap for endianness. In contrast, if you choose to read the .obj file into memory one byte at a time with fgetc, the endianness doesn’t need to be adjusted. However, you will have to combine two bytes into a word using bitwise operators.

Resources
â—Ź Valgrind documentation
https://www.valgrind.org/docs/manual/quick-start.html#quick-start.interpret
â—Ź Checking end of file https://faq.cprogramming.com/cgibin/smartfaq.cgi?id=1043284351&answer=1046476070
â—Ź C Bitwise Operators in Canvas
[no link since this changes every semester]

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] Cit593 module 12-dynamic memory and file i/o[SOLVED] Cit593 module 12-dynamic memory and file i/o
$25