DEV Community

Krinskumar Vaghasia
Krinskumar Vaghasia

Posted on

SPO Week 4 - CPUs

This week we had no lab, but the week was packed with a lot of new information so that we can transition from 6502 to "the assembly". We started this week off by understanding the CPUs and architectures. We discussed the differences between RISC (Reduced Instruction Set Computing) and CISC (Complex Instruction Set Computing) architectures, and how these principles have influenced modern processors like x86_64 and ARM64.

1. RISC vs. CISC

Historically, there have been two primary types of CPU architectures:

  • RISC (Reduced Instruction Set Computing):

    • Designed around a small set of simple instructions that can be executed very quickly.
    • The idea is to use fewer gates on the CPU for instruction decoding, leaving more room for other performance-enhancing features like registers or caches.
    • Example: ARM64 processors.
  • CISC (Complex Instruction Set Computing):

    • Developed to make programming easier by including complex, multifunctional instructions that reduce the amount of code a programmer writes.
    • These architectures dedicate more CPU resources to decoding complex instructions, which can perform multiple tasks in a single step.
    • Example: x86 processors.

Over the years, modern CPU designs have merged concepts from both architectures. For instance, x86 CPUs now break down complex instructions into smaller micro-operations, much like a RISC approach, while RISC processors have adopted more sophisticated features typically seen in CISC designs.

2. Register Layout and Usage

Registers are a fundamental aspect of any CPU architecture, acting as temporary storage for data that the CPU processes. The way these registers are organized and used varies between x86_64 and ARM64:

x86_64 Registers

  • General Purpose Registers:

    • There are 16 general-purpose registers (RAX, RBX, RCX, RDX, etc.).
    • Originally, these registers had different names and were smaller (e.g., AX, BX for 16-bit). Over time, they were expanded to 32-bit (EAX, EBX) and now 64-bit (RAX, RBX).
    • Some registers have special functions, like the stack pointer (RSP) or base pointer (RBP).
  • Segment Registers and Flags:

    • Registers like RDI and RSI are often used for specific tasks, such as indexing memory during string operations.
    • Registers can be accessed at different widths (8-bit, 16-bit, 32-bit, 64-bit) using suffixes like L, X, E, or R.

ARM64 Registers

  • General Purpose Registers:

    • ARM64 has 31 general-purpose registers (R0 - R30), which are generally simpler to work with than x86_64.
    • The stack pointer and a zero register (RZR) have special roles. The zero register, for example, always reads as 0 and discards any value written to it.
    • Unlike x86_64, ARM64 uses numbered registers, making it easier to understand how data is passed and manipulated.
  • Parameter Passing:

    • On ARM64, parameters for functions are passed through registers R0 - R7, and return values are placed in R0.
    • This contrasts with x86_64, which uses a more complex setup (RDI, RSI, RDX, RCX, etc.).

3. Calling Conventions: Procedure and System Calls

Understanding how functions are called, and how parameters are passed, is crucial for assembly programming.

Procedure Calls

  • x86_64:

    • Uses registers like RDI, RSI, RDX, RCX to pass parameters to functions. Up to six parameters can be passed this way, with additional ones placed on the stack.
    • The RAX register is used to hold return values.
  • ARM64:

    • Uses a simpler, sequential approach where R0 - R7 are used to pass the first eight parameters.
    • This architecture supports a clearer and more consistent way of handling multiple parameters compared to x86_64.

System Calls

System calls are how programs request services from the operating system. This involves switching the CPU into a privileged mode (kernel mode).

  • x86_64:

    • The RAX register is used to specify the system call number, while other registers hold parameters.
    • Additional setup may be required to handle the transition between user mode and kernel mode.
  • ARM64:

    • The system call number is stored in R8, and other parameters are passed using R0 - R7.
    • ARM64 simplifies this process by standardizing the way parameters are passed, making system calls faster to set up.

4. Instruction Length and Code Density

One of the more intriguing aspects of modern CPUs is how they handle instruction length:

  • x86_64:

    • Instructions can vary in length, from one byte up to 15 bytes, allowing for flexibility. However, this can lead to inefficiencies as more time might be spent decoding instructions of varying lengths.
    • Longer instructions can pack more complex operations, potentially reducing the number of lines of code.
  • ARM64:

    • Instructions are fixed at 32 bits in size, which simplifies the CPU design and makes decoding faster.
    • This predictability can sometimes mean needing multiple instructions to perform a task that would take fewer, longer instructions on x86_64. However, the streamlined design often makes up for this with speed and simplicity.

5. Merging Concepts: How RISC and CISC Have Converged

Although RISC and CISC began as different philosophies, modern processors have incorporated features of both:

  • Micro-Operations:
    • Complex instructions on x86_64 CPUs are broken down into simpler, RISC-like micro-operations (micro-ops) for processing. This allows the CPU to handle tasks in parallel, improving performance.
  • Pipeline and Out-of-Order Execution:
    • Both RISC and CISC processors now feature sophisticated methods of handling multiple instructions simultaneously. For instance, CPUs can predict the order of operations and execute them out of order to keep the processor busy even while waiting for slow operations to complete.

Conclusion

Next week's lab will want us to tweak real assembly code, so stay tuned for that blog!!!!

Top comments (0)