ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Computer Organization and Assembly Language
    COMP3137
    Progress0 / 73 topics
    Topics
    1. Introduction to Computer Organization2. Assembly Language3. Comparison of Low-Level and High-Level Languages4. Register Types (16-bit): General Purpose and Special Purpose Registers5. Introduction and Usage of RAM6. Processor7. Registers8. System Bus9. Instruction Execution Cycle10. Assembly and Machine Language11. Assembler12. Linker and Link Libraries13. Programmer's View of a Computer System14. RISC and CISC Architecture15. Physical Address Calculation16. Basic Memory Organization17. CPU Organization18. Top Level View of Computer Function and Interconnection19. Assembler Instruction Cycle20. Execute Cycle21. Interrupts22. Interrupt Cycle23. Memory Connection24. Input/Output Connection25. CPU Connection26. MASM27. MIPS28. Defining Data in MASM Assembler29. Elements of Assembly Language30. Integer Constants31. Integer Expressions32. Real Number Constants33. Character Constants34. String Constants35. Reserved Words36. Identifiers37. Directives38. Instructions39. The NOP (No Operation) Instruction40. Adding and Subtracting Integer41. INC and DEC Instructions42. NEG Instruction43. How to Move Integer Number in Register44. Adding and Subtracting Numbers in Registers45. Declaration and Initialization of Variables46. Moving Data from Variable to Register47. Data Definition Statement48. BYTE and SBYTE Data49. WORD and SWORD Data50. Defining DWORD and SDWORD Data51. Knowledge about Different Data Types52. Operations, Array & Loops53. Division and Multiplication in Assembly54. Jumps Based on Specific Flags55. Jumps Based on Equality56. Simple Jump Statements57. Jumps Based on Specific Condition58. Code Examples59. Practice on MASM60. Procedures61. File Operations Procedures62. Labels in Procedures63. Stack64. Runtime Stack65. Conditional Control Flow Directives66. Compound Expressions67. Data Representation & Conversion68. Architecture69. Data Path70. Control Unit71. Critical Path72. General Principles of Pipelining73. Pipelined Y86 Implementations
    COMP3137›Runtime Stack
    Computer Organization and Assembly LanguageTopic 64 of 73

    Runtime Stack

    8 minread
    1,324words
    Intermediatelevel

    Runtime Stack

    The runtime stack, often simply called the stack, is a critical part of a computer’s memory management system used by the CPU during the execution of programs. It stores information such as local variables, function parameters, return addresses, and information about the function calls themselves. The runtime stack is used during function calls and returns, and it helps manage the flow of execution in a program.

    Let’s break down the concepts and importance of the runtime stack, and how it functions in the context of program execution.


    Structure of the Runtime Stack

    The runtime stack is organized as a last-in, first-out (LIFO) data structure. This means that the last item pushed onto the stack is the first one to be popped off. This organization is particularly suited for managing function calls and returns.

    The runtime stack typically consists of the following components:

    1. Function Call Frame (Stack Frame)
    2. Return Address
    3. Local Variables
    4. Function Arguments/Parameters
    5. Saved Registers
    6. Stack Pointer (SP)

    Components of the Runtime Stack

    1. Function Call Frame (Stack Frame)

    Each time a function is called, a new stack frame is created on the stack. This stack frame contains all the data needed to manage the function’s execution, such as the function's parameters, local variables, and the return address.

    A stack frame typically contains:

    • Return Address: The address to return to once the function finishes executing. This is stored in the stack frame by the call instruction when a function is called.
    • Function Arguments: The values passed to the function when it is called. These are typically pushed onto the stack by the calling function.
    • Local Variables: The variables that are declared within the function. Each function gets its own space for local variables in the stack frame.
    • Saved Registers: Some registers are saved to the stack so that their values can be restored after a function call (to preserve state).

    2. Return Address

    When a function is called, the address to which the program should return after the function finishes is stored on the stack. This is important for ensuring that control can return to the correct place in the program once the function has completed its execution.

    3. Local Variables

    Local variables are those declared within the function. These are stored in the stack frame of the function and are removed when the function returns. Since the stack is LIFO, each function gets a fresh space on the stack for its local variables, and these variables are discarded when the function exits.

    4. Function Arguments/Parameters

    The arguments (or parameters) passed to a function are also stored on the stack, either before or after the function’s stack frame. In many calling conventions, the arguments are pushed onto the stack in reverse order (right to left).

    5. Saved Registers

    Before calling a function, the calling function may save the values of certain registers (such as the base pointer, or BP) to the stack to ensure that they can be restored when the function finishes executing. This is part of the function prologue (the set of instructions executed when a function is entered).


    How the Runtime Stack Works

    The operation of the runtime stack is best understood by looking at the sequence of events during function calls and returns:

    1. Function Call

    • When a function is called, the return address (the point to continue execution after the function completes) is pushed onto the stack.
    • The arguments to the function are pushed onto the stack, either by the calling function or directly as part of the function call.
    • A new stack frame is created for the called function. This contains the space for local variables, saved registers, and other necessary data.
    • The program control then jumps to the called function, which begins execution.

    2. Function Execution

    • Inside the function, local variables are allocated space within the function’s stack frame.
    • The function executes its instructions and manipulates local variables and registers.
    • If the function makes any other function calls, similar steps occur: a new stack frame is pushed for the called function, and the return address and arguments are stored.

    3. Function Return

    • When the function completes its execution, it needs to return control to the calling function.
    • The return value (if any) is often placed in a specific register (such as EAX in x86), and the stack frame for the function is cleaned up.
    • The return address (stored in the stack frame) is popped from the stack, and the program counter (PC) is updated to this address.
    • The saved registers are restored, and the stack pointer is adjusted to remove the current stack frame.
    • Control returns to the calling function, and the calling function continues execution from the point after the function call.

    Example of Stack Usage: Function Call and Return

    Let’s consider a simple example of function calls using the runtime stack in a pseudo-assembly language.

    1. Main Program (Calling function):

      push 5           ; Push argument for funcA
      call funcA       ; Call function funcA
      ; Execution continues here after funcA returns
      
    2. Function A:

      funcA:
      push ebp         ; Save the base pointer (if necessary)
      mov ebp, esp     ; Set up stack frame (save current stack pointer)
      push dword [ebp+8] ; Push argument passed to funcA (parameter 5)
      ; Function A does something with the argument...
      pop ebp          ; Restore the base pointer
      ret              ; Return control to the calling function
      

    Flow of execution:

    • Main Program pushes the argument 5 onto the stack and then calls funcA.
    • The call funcA instruction pushes the return address (the location where execution should continue after the function returns) onto the stack.
    • funcA pushes the base pointer (ebp) onto the stack to save the current frame, then sets up its own stack frame.
    • funcA accesses the argument (stored at [ebp+8]) and performs its task.
    • Upon completing execution, funcA pops the stack pointer (restoring the base pointer) and returns control to the Main Program by using the ret instruction, which pops the return address from the stack and jumps back to the calling code.

    Stack Overflow and Stack Underflow

    • Stack Overflow: Occurs when the program uses more space on the stack than is available, often due to excessive function calls (e.g., infinite recursion). This leads to overwriting data and crashes the program.

    • Stack Underflow: Happens when a function attempts to return or pop data from the stack that hasn’t been pushed onto the stack. This can occur when the stack pointer is incorrectly manipulated or when a function tries to pop more data than was pushed.

    Both stack overflow and stack underflow can cause serious program errors and crashes.


    Stack in Recursion

    The stack is crucial for managing recursion, where a function calls itself. Each recursive call pushes a new stack frame, allowing the program to maintain separate local variables and return addresses for each recursive call. The stack unwinds when the base case is reached, and control is returned from each recursive function in reverse order.

    For example, consider a simple recursive function to compute the factorial of a number:

    int factorial(int n) {
        if (n == 0) return 1;
        return n * factorial(n - 1);
    }
    

    Each call to factorial() pushes a new frame onto the stack. When factorial(5) is called, the stack will look like this:

    • factorial(5) — frame 1
    • factorial(4) — frame 2
    • factorial(3) — frame 3
    • factorial(2) — frame 4
    • factorial(1) — frame 5
    • factorial(0) — base case

    Once the base case is reached, the stack begins to unwind, returning control to each previous call and ultimately computing the result.


    Conclusion

    The runtime stack is a fundamental part of program execution, managing function calls and returns, local variables, and function arguments. It allows for proper function nesting, recursion, and state preservation across function calls. By understanding how the stack works, you gain insights into the inner workings of program execution and the flow of data within a computer's memory.

    Previous topic 63
    Stack
    Next topic 65
    Conditional Control Flow Directives

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time8 min
      Word count1,324
      Code examples0
      DifficultyIntermediate