1. Due Date

Due by 11:59 pm, Tuesday, October 21, 2025

You will work with your assigned partner on this lab: Lab 5 Partners

Please review our guidelines for working with partners: working with partners, etiquette and expectations.

2. Lab 5 Overview and Goals

In this lab we will gain expereince writing assembly code.

2.1. Lab Goals

  • Gain experience translating C code to x86_64 Assembly to enhance your understanding of underlying data structure access, and function calls.

  • Understand in more detail the mechanics of C "pass-by-pointer" style parameters and function calls.

2.2. Overview of Lab Requirements

This lab consists of two parts

  • Part 1: Implement the sum function in Assembly code (in sum.s) and test and debug it by making calls to it from the sum_prog.c C program.

  • Part 2: Implement the compare function in Assembly code (in compare.s) and test it out in the compare_prog.c C program.

3. Lab Starting Point Code

3.1. Getting Your Lab Repo

Both you and your partner should clone your Lab 5 repo into your cs31/Labs subdirectory:

  1. get your Lab 5 ssh-URL from the CS31 GitHub Organization. The repository to clone is named Lab5-userID1-userID2 where the two user names match that of you and your Lab 5 lab partner.

  2. cd into your cs31/Labs subdirectory:

    $ cd ~/cs31/Labs
    $ pwd
  3. clone your repo

    $ git clone [the ssh url to your your repo]
    $ cd Lab5-userID1-userID2

There are more detailed instructions about getting your lab repo from the "Getting Lab Starting Point Code" section of the Using Git for CS31 Labs page. To make changes, follow the directions in the "Sharing Code with your Lab Partner" section of the Using Git for CS31 Labs page.

3.2. Starting Point files

The starting point files for this lab are:

$ ls
Makefile  README.adoc  compare.s compare_prog.c  sum.s  sum_prog.c

Details:

  1. README.adoc contains some instructions to you.

  2. sum.s, sum_prog.c: Part 1 files are

  3. compare.s, compare_prog.c

  4. Makefile: A Makefile simplifies the process of compiling your program. You do not need to edit this file. We’ll look at these in more detail later in the course, if you are interested, take a look at Section 7 for more information about make` and makefiles.

4. Part 1: Sum Function

For this part, you will implement a sum function in x86_64 in sum.s, which has the starting point of this function. Then sum.s is compiled into a program (sum_prog) that you can use test your code.

The starting point handles the stack set-up and function return. As a result, you just need to implement the x86_64 translation of the function body. See the comments in sum.s about where on the stack there is space for local variables, and where the parameter n is located.

The C function you will implement in x86_64 is:

/* computes the sum of the values 1-n
 * n: an int value
 * returns: the sum of values from 1-n, or -1 if n is not positive
 */
long sum(long n) {

  long i, res;

  if( n <= 0 ) {
     return -1;
  }
  res = 0;
  for(i=1; i <= n; i++) {
    res = res + i; 
  }
  return res;
}

The program sum_prog.c makes a call to this sum function (do not modify sum_prog.c, but you can open it in vim to see what it is doing).

4.1. Compiling and Running

The files for This part are:

  • The sum.s file contains the starting point x86_64 code for the sum function that you will complete for Part 1. Your solution should be implemented in this file.

  • sum_prog.c: a main program for testing your sum implementation, Do not modify this program.

The Makefile is set up to compile both the x86_64 sum.s and sum_prog.c files into an executable named sum_prog that you can use to run and test your x86_64 implementation.

$ make     # compiles sum_prog from sum.s and sum_prog.c
$ ./sum_prog

4.2. Sample Output

When run, the sum_prog reads in user input for the value n, that is passed as a parameter to your sum function, and then prints out the result (you can see this main control flow in the sum_prog.c file’s main function, which you should not modify). Some sample inputs and outputs of the program are provided below:

$ ./prog
This program computes the sum of 1-N
Enter an value for n: 10
The sum of 1 to 10 is 55

$ ./prog
This program computes the sum of 1-N
Enter an value for n: 50
The sum of 1 to 50 is 1275

4.3. Requirements

  • Your x86_64 implementation of the sum function should be added to the sum.s starting point file.

  • Your code should be well-commented.

  • Do not edit sum_prog.c, but looking at it in vim might help you understand how your sum function is being called.

  • Your solution must include a loop. It is well known that the sum of the first n positive integers is n*(n+1)/2, but you can not use that in your answer.

4.4. Tips

  • Write C goto versions of the sum function, the if and for loop parts in particular, to help you with the translations of those parts.

  • Remeber that instructions can access at most one memory location and one register in x86_64, e.g., mov -8(%rbp), %rax is allowed but mov -8(%rbp), -16(%rbp) is not allowed. If you need to do something with two memory locations, you will need to move one of them into a register first.

  • Try adding a little bit of x86_64 code to sum.s at a time, then compile and test it out by running prog, and add some more. Parts of that you test out do not even have to be parts of the solution, for example:

    1. First see if you can just return the value of n.

    2. Next, see if you can initialize res to 0 and return the value of res.

    3. Next, try the if statement, and test passing positive and negative values to see if your function returns -1 when n is not positive.

    4. Then try implementing the for loop.

  • To help debug, trace through the instructions on paper, drawing memory contents and register contents as you go.

  • You can also test out some code snippets using the assembly visualization tool to check if your logic is correct without having to compile and run your entire program.

  • Use Ctrl-C to kill a running program stuck in an infinite loop.

5. Part 2: Compare Function

For this part, you will implement a compare function in x86_64 in compare.s, that conditionally changes the value pointed to by x. Then compare.s is compiled into a program (compare_prog) that you can use test.

The starting point code handles the stack set-up and function return. As a result, you just need to implement the x86_64 translation of the function body. See the comments in compare.s about where on the stack there is space for local variables, and where the parameters *x and y are located.

/*
 * This function compares two values, and sets the first
 * to the value of the second if the value of the second
 * is less than the first.  It uses "pass by pointer"
 * to modify the argument's value in this case.
 *
 *   x: pointer to long value that may change
 *   y: long value to compare to the value that x points to
 *   returns: no return value (pointer param might modify argument)
 */
void compare(long *x, long y);

This function takes one long int pointer, x, passed by pointer (the parameter points to the storage location of its argument), and one long int, y, passed by value.

If the <value pointed to by x> is greater than <y>, set the <value pointed by x> to be <y>. Otherwise, it should be unchanged by the call.

The program compare_prog.c makes a call to this sum function (do not modify compare_prog.c, but you can open it in vim to see what it is doing).

To write compare.s, you will have to write out the function definition for compare() in C, then write its go-to equivalent, followed by the x86_64 Assembly version.

5.1. Compiling and Running

The files for this part are:

  • The compare.s file contains the starting point x86_64 code for the compare function that you will complete for Part 2. Your solution should be implemented in this file.

  • compare_ prog.c: a main program for testing your compare implementation, Do not modify this program.

The Makefile is set up to compile both the x86_64 compare.s and compare_prog.c files into an executable named compare_prog that you can use to run and test your x86_64 implementation.

$ make     # compiles compare_prog from compare.s and compare_prog.c
$ ./compare_prog <num1> <num2>

5.2. Sample Output

When run, the compare_prog takes in two numbers from the command line (<num1> and <num2>). They are passed as parameters to the compare function, <num1> is passed by pointer and <num2> is passed by value. The program then prints out the values of <num1> and <num2> before and after the call to compare (you can see this main control flow in the compare_prog.c file’s main function, which you should not modify). Some sample inputs and outputs of the program are provided below:

$ ./compare_prog -10 1
Before compare(): a = -10, b =   1
After compare(): a = -10, b =   1

$ ./compare_prog 200 199
Before compare(): a = 200, b = 199
After compare(): a = 199, b = 199

$ ./compare_prog 650 777
Before compare(): a = 650, b = 777
After compare(): a = 650, b = 777

5.3. Requirements

  • Your x86_64 implementation of the compare function should be added to compare.s starting point file.

  • Your code should be well-commented.

  • Do not edit compare_prog.c, but looking at it in vim might help you understand how your compare function is being called.

  • Your solution must include any one of the conditional or unconditional jump instructions, as needed.

5.4. Tips

  • Write C goto versions of the compare function first to help you with the translations of those parts.

  • The parameter values of x and y are on stored in the registers, x is in %rdi and y is in %rsi. Note that x is a long int pointer and y is a %long int.

  • Remeber that instructions can access at most one memory location and one register in x86_64, e.g., mov -8(%rbp), %rax is allowed but mov -8(%rbp), -16(%rbp) is not allowed. If you need to do something with two memory locations, you will need to move one of them into a register first.

  • Draw a picture of the registers, including where parameter and argument values are and trace through the instruction execution to help you determine what x86_64 instructions you need to use to implement compare.

  • To help debug, trace through the instructions on paper, drawing memory contents and register contents as you go.

  • You can also test out some code snippets using the assembly visualization tool to check if your logic is correct without having to compile and run your entire program.

  • Use Ctrl-C to kill a running program stuck in an infinite loop.

6. Submit

Please remove any debugging output prior to submitting.

To submit your code, commit your changes locally using git add and git commit. Then run git push while in your lab directory. Only one partner needs to run the final git push, but make sure both partners have pulled and merged each others changes.

Also, it is good practice to run make clean before doing a git add and commit: you do not want to add to the repo any files that are built by gcc (e.g. executable files). Included in your lab git repo is a .gitignore file telling git to ignore these files, so you likely won’t add these types of files by accident. However, if you have other gcc generated binaries in your repo, please be careful about this.

Here are the commands to submit your solution in the sorter.c file (from one of you or your partner’s ~/cs31/Labs/Lab5-userID1-userID2 subdirectory):

$ make clean
$ git add compare_prog.c sum_prog.c compare.s sum.s
$ git commit -m "correct and well commented Lab5 solution"
$ git push

You could also use this git add shorthand to add all .c and .s:

$ git add *.s *.c

Verify that the results appear (e.g., by viewing the the repository on CS31-f25). You will receive deductions for submitting code that does not run or repos with merge conflicts. Also note that the time stamp of your final submission is used to verify you submitted by the due date, or by the number of late days that you used on this lab, so please do not update your repo after you submit your final version for grading.

If you have difficulty pushing your changes, see the "Troubleshooting" section and "can’t push" sections at the end of the Using Git for CS31 Labs page. And for more information and help with using git, see the git help page.

At this point, you should submit the required TBA[Lab 5 Questionnaire] (each lab partner must do this).

Lab 5 Survey

After submitting your complete Lab 5 solution, you should submit the required TBA[Lab 5 Questionnaire] (each lab partner must do this). Note this link is typically live a day or two before the due date through several days after the due date. Please submit within one week of the lab due date.

7. Handy Resources

General Lab Resources

Assembly Resource