CO Lab Manual
Course Page
  • Course Information
    • Welcome
    • Introduction
    • Your Contributions
    • Lab Sessions and Etiquette
    • Team Setup
    • Assumed Prior Knowledge
  • Setup Guides
    • GitHub Repository Setup
    • Technical Setup
      • Windows
      • Linux
      • macOS
    • GitHub SSH Setup
    • Framework Setup
  • Reference Documentation
    • Introduction to the Documentation
    • A Brief History Lesson
    • Syntax (Intel vs. AT&T)
      • Section Exercises
    • Memory
      • Memory Management
      • Section Exercises
    • Registers
      • Section Exercises
    • Instructions
    • Subroutines
      • Calling Subroutines
      • Writing Subroutines
      • Section Exercises
    • Input/Output
      • Printing to the Terminal
      • Reading from the Terminal
      • Section Exercises
    • Programming Constructs
    • Assembler Directives
    • C/C++ vs Assembly
    • Building and Running Programs
    • Address Sanitization
    • A0: A Running Example
  • Assignments
    • Introduction to the Assignments
    • Mandatory Assignments
      • A1: Subroutines and I/O
      • A2: Recursion
    • Extra Assignments
      • A3-a: Fibonacci Calculator
      • A3-b: Fibonacci REPL
      • A4: Diff
      • A5: Printf
      • A6: HPC
      • A7: Bitmap
      • A8: Game
  • Appendix
    • Acknowledgments
    • Rules and Regulations
    • Frequently Asked Questions
    • How to use a Debugger
Powered by GitBook
On this page
  • True or False:
  • Multiple Choice
  1. Reference Documentation
  2. Subroutines

Section Exercises

True or False:

The content of a callee-saved register does not remain the same after a subroutine is called.

False!

The value of a callee-saved registered is saved by the subroutine that is called. So if in a callee-saved register, we have a value x and then we call a subroutine foo, even though we use the callee saved register in the execution of foo, when the subroutine returns, the callee-saved register still has the value x.

The value of a caller-saved register remains the same after a subroutine is called.

False!

The value of a caller-saved register can be changed by a subroutine call, so, in order to reuse the initial value of such a register, you need to store it either on the stack or in a callee-saved register.

rbx, rsp, and rbp are callee-saved registers.

True!

rax is a callee-saved register.

False!

rax is a caller-saved register, so its value has to be stored somewhere else.

Hint: remember that the value returned by a subroutine will be found in rax. meaning that the content of rax is overwritten with every subroutine execution.

rdi, rsi, rdx, and rcx are caller-saved registers.

True!

Stack (mis)alignment was the most common cause of a subroutine call crash in Computer Organization 2024.

True!

Keep in mind that before calling a subroutine, your stack should be 16-byte aligned.

The term stack frame refers to the entire stack.

False!

The stack frame refers to the area of the stack that is used by a subroutine.

rsp is indicates the base of the current stack frame.

False!

rsp, the stack pointer, indicates the top of the current stack frame and it moves with every push or pop instruction. rbp is the base pointer which indicates the base of the current stack frame.

A prolog is used to set up the stack frame of a subroutine.

True!

The epilog refers to the action of restoring the previous stack frame before a subroutine returns.

True!

It is advised to store local variables in registers.

False!

Although, in theory, you could, it is not advisable because storing the local variables in registers has some drawbacks such as limiting the number of local variables (there is a limited number of registers, hence a limited number of local variables) and you risk to have their value changed if the register is used in a subroutine.

To make space for the local values, you can push them on the stack after the prologue.

True!

As an alternative, you can subtract the needed space from the stack pointer if the local variables are uninitialized.

Multiple Choice

Why is it or is it not the stack misaligned in the following cases?

main: 
     ...
     subq $16, %rsp 
     movq $10, %rdi 
     pushq %rdi 
     call foo

The stack is misaligned.

It can be seen in the code associated with this answer option that we first reserve 16 bytes of space on the stack for two variables by subtracting 16. Before calling foo, rdi is pushed on the stack, meaning that we add another 8 bytes on the stack. As a result, there were 24 bytes added to the stack instead of a number of bytes equal to a multiple of 16.

main:  
     ... 
     subq $8, %rsp 
     movq %rsp, %rdi 
     subq $8, %rsp 
     call foo

The stack is aligned.

Although we only need space on the stack for a value, by subtracting only 8 bytes, the calling convention is broken. To make the stack 16 aligned, another 8 bytes are subtracted before foo is called.

main: 
     ...
     pushq $4 
     subq $16, %rsp 
      movq $10, %rdi 
      pushq %rdi 
      call foo

The stack is aligned.

By pushing 4 on the stack (8 bytes) and then subtracting 16 and then pushing rdi (8 bytes), we reserve 32 bytes on the stack, which is a multiple of 16.

main: 
     ...
     subq $16, %rsp
     pushq $4 
     movq $10, %rsi 
     pushq %rsi 
     popq %rdi 
     call foo

The stack is misaligned.

In the above code example, we observe that 16 bytes are allocated on the stack and that 4 and rsi are pushed on the stack, meaning that we reserve 32 bytes on the stack. By popping the top of the stack in rdi, we reduce the stack size by 8 bytes, resulting in only 24 bytes being reserved on the stack.

PreviousWriting SubroutinesNextInput/Output

Last updated 3 months ago