$ cd cso-labs/ $ git commit -am "commits for previous lab" $ git pullSince occasionally we need to modify lab files, please remember to ensure that your lab files are up to date with the class repository. We will explicitly inform you to do "git pull" via Piazza when we update the repository. As a precaution, you should also "git pull" periodically.
$ objdump -d objs/ex1_sol.o
There is a caveat: we do not tell you the signature of ex1. Therefore, it would be hard to write your own C code to correctly invoke ex1. How can you run ex1 then? It turns out that you can utilize the test harness code that we have given you to run ex1 and observe how it executes.
To run the test with the given ex1 function, you need to link the test object file objs/tester.o together with the given objs/ex*-sol.o files. We have made this step easy by including appropriate Makefile rules. When you type make, you will see that there are two binary executables being generated, tester, and tester-sol. The executable file tester links our tester file with your object files ex*.o which are generated from your ex*.c files. The executable file tester-sol links our tester file with the given object file objs/ex*-sol.o. Thus, when you run ./tester-sol, the tester invokes the given functions, and needless to say, all tests should pass.
Run gdb tester-sol. Stop the execution when the function ex1 is invoked. Dissemble the function. Execute the instructions one by one. Form some hypothesis on what the function signature is and what it does. Verify your hypothesis during execution by examining register values and memory contents.
Note: It is not the right approach to try to match the object code of your C function to that contained in ex*-sol.o. Doing so is painful and not necessary. Minor changes in how a set of C code is written will result in different object code, although they do not affect the code's semantics. Therefore, trying to find a C function that generates the same object code is frustracting and likely futile.
$ make $ ./tester Testing Ex1... Ex1: your implementation passes the test Testing Ex2... Ex2: your implementation passes the test Testing Ex3... Ex3: your implementation passes the test Testing Ex4... Ex4: your implementation passes the test Testing Ex5... Ex5: your implementation passes the testThe above ouput ocurrs when all your ex* functions pass the test.
To test multiple times, run ./tester -r with the -r option. This runs the tester using a new seed for its random number generator.
Some of you might want to skip around and implement the five ex* functions in arbitary order. This is a good strategy if you are stuck on some function. To test just ex2, type ./tester -t 2. Ditto with other functions.
Note: Passing the test does not guarantee that you will get a perfect grade (i.e. your implementation is not necessarily correct). During grading, we may use a slightly different test or manually examine your source code to determine its correctness.
For this lab, you need to review the lecture notes and textbook to refresh your understanding of x86 assembly. Below are some additional information not covered in the lecture notes that are helpful for this lab as well.
register : name to refer its lower-order portion %rax : %eax(lower-32 bit), %ax(lower-16-bit), %al(lower-8-bit). %rcx : %ecx(lower-32 bit), %cx(lower-16-bit), %cl(lower-8-bit). %rdx : %edx(lower-32 bit), %dx(lower-16-bit), %dl(lower-8-bit). %rbx : %ebx(lower-32 bit), %bx(lower-16-bit), %bl(lower-8-bit). %r8 : %r8d(lower-32 bit), %r8w(lower-16-bit),%r8b(lower-8-bit). ... %r15 :%r15d(lower-32 bit),%r15w(lower-16-bit),%r15b(lower-8-bit).Note: For some reason, gdb does not recognize %r8b as a valid register name. Please just print register %r8 and manually find out its lower-8-bit to obtain the value for %r8b.
For those of you who want to go out in the world to explore other object files, you will find the official Intel instruction set manual useful. Note that in the Intel manual, the source and destination operands are reversed in an instruction (i.e. destination operand first, source operand last). In the lecture notes and gdb/objdump's disassembled output, the destination operand appears last in an instruction. These differences are due to two assembly syntaxes, AT&T syntax and Intel syntax. The GNU software (gcc, gdb etc) and lecture notes use AT&T syntax which puts the destination operand last and Intel manual (of course) uses Intel syntax which puts the destination operand first.
make handinSubmit here