Chapter3

CISC [optimized for compact code size]

Size of Data Type in IA32

C declarationIntel data typeAssembly-code suffixSize (bytes)
Byte
Word
Double word
Quad word
Quad word
Single precision
Double precision

Register

Operands

  • Immediate

  • Register

  • Memory Reference Immediate & Base Register & Index Register & Scale Factor (1,2,4,8)

TypeFormOperator ValueName
ImmediateImmediate
RegisterRegister
MemoryScaled Indexed
MemoryAbsolute
MemoryIndirect
MemoryBase + Displacement
MemoryIndexed
MemoryIndexed
MemoryScale Indexed
MemoryScale Indexed
MemoryScale Indexed

Operation code

  • Movement

    • [movb, movw, movl, movq, movabsq]

      Source operand (Immedita, Register, Memory); Destination operand (Register, Memory)

      Two operands of a move instruction cannot both be memory references. (It is necessary to first move the source memory reference into a register, and then move it to the destination memory reference.)

      movl writes 32 bits of data to the lower half and then automatically zero-extends the value into the upper 32 bits. (In x86-64, any instruction that generates a 32-bit result for a register will set the upper 32 bits of that register to zero.)

      movq can only be 32 bits (sign-extended to 64 bits), whereas movabsq can be 64-bit but the destination must be a register.

    • [movzbw, movzbl, movzwl, movzbq, movzwq]

      movzlq does not exist because of movl instruction.

    • [movsbw, movsbl, movswl, movsbq, movswq, movslq, cltq]

      cltq same as movslq %eax, %rax

  • Stack

    let a quad number be the example

    • subq $8 %rsp
      movq %rbq,(%rsp)
      
    • movq (%rsq),%rax
      addq $8, %rsp
      

Load Effective Address

Computes effective address and stores it in destination register

Unary Operations

InstructionsEffect
inc D
dec D
neg D
not D

Binary Operations

InstructionsEffect
add S D
sub S D
imul S D
xor S D
or S D
and S D

Shift Operations

InstructionsEffect
sal D
shl D
sar D Arithmetic Right Shift
shr D Logical Right Shift

Shift instructions can shift by an immediate value, or by a value placed in the single-byte register %cl.

Condition Code

  • Carry Flag [check for overflow in unsigned operations]

  • Zero Flag

  • Sign Flag

  • Overflow Flag

  • Similar to sub, but it only sets the condition codes without changing the value of the destination register.

    When S == D, .

    It will set the condition codes based on the result of .

  • Similar to and, but it only sets the condition codes without changing the value of the destination register.

    When S & D == 0, .

Set Instructions

InstructionEffectDescription
sete D
setne D
sets Dnegative
setns Dnonnegative
setg DSigned
setge DSigned
setl DSigned
setle DSigned
seta DUnsigned
setae DUnsigned
setb DUnsigned
setbe DUnsigned

Jump Instructions

InstructionJump ConditionDescription
jmp LabelDirect Jump
jmp *OperandIndirect Jump
je Label
jne Label
js LabelNegative
jns LabelNonnegative
jg LabelSigned
jge LabelSigned
jl LabelSigned
jle LabelSigned
ja LabelUnsigned
jae LabelUnsigned
jb LabelUnsigned
jbe LabelUnsigned

Conditional Move Instructions

InstructionMove ConditionDescription
cmove S, R
cmovne S, R
cmovs S, RNegative
cmovns S, RNonnegative
cmovg S, RSigned
cmovge S, RSigned
cmovl S, RSigned
cmovle S, RSigned
cmova S, RUnsigned
cmovae S, RUnsigned
cmovb S, RUnsigned
cmovbe S, RUnsigned

Loop

do-while, while, and for loops can be implemented by combining conditional tests and jumps.

Switch

switch is compiled into a jump table. The execution time of the switch statement is irrelevant to the number of cases.

Transfer Control

InstructionDescription
call LabelProcedure Call (Direct)
call *OperandProcedure Call (Indirect)
retReturn from Procedure Call

Data Transfer

The registers' names depend on the size of the data type being passed.

If a function has more than 6 integer parameters, the additional arguments must be passed on the stack. Note that the argument 7 is located at the top of the stack. All stack-passed arguments are aligned to multiples of 8 bytes.

Pointer

ExpressionTypeValueAssembly Code
Eint*movq %rdx, %rax
E[i]intmovl (%rdx, %rcx, 4), %eax
&E[i]int*leaq 8(%rdx, %rcx, 4), %rax
&E[i] - Elongmovq %rcx, %rax

Notes:

  1. &E[i] - E yields type long (specifically ptrdiff_t) because pointer subtraction returns the number of elements between them as a signed integer.

  2. int* uses movq (not movl) because pointers are 64-bit addresses in x86-64.

Nested Arrays

T D[R][C] , is the size of data type T in bytes.

Struture & Union

Structure

Types

Notes:

  1. The address of any K-byte basic object must be a multiple of .

  2. The offset of the first member is always 0 in a structure.

  3. The compilers probably add some bytes at the end of a structure to ensure that each element in an array of structures could satisfy its alignment requirements.

Union

The total size of a union equals the size of its largest field.

Application

Buffer Overflow

Three protection mechanisms to thwart buffer overflow attacks:

  • Stack Randomization Address-Space Layout Randomization (ASLR)

  • Stack Corruption Detection Place a random canary value between local buffers and critical stack data to detect buffer overflows.

  • Limiting Executable Code Regions

Dynamic Stack Frame

%rbp is base pointer/frame pointer dynamic stack frame

Floating-point Code

Chapter 4 Processor Architecture

Logic Design and Hardware Control Language (HCL)

Logic Gate

CMOS

Process

For Y86-84 :

  1. Fetch

    • Read instruction bytes from memory using PC:
      • icode:ifun (instruction specifier)
      • rA, rB (register specifiers)
      • valC (8-byte constant)
    • Compute next instruction address → valP
  2. Decode

    • Read up to two operands from registers
    • rA, rBvalA, valB
    • For popq, pushq, call, ret: also read from %rsp
  3. Execute

    • Compute (ALU/address/stack) → valE
    • Set condition codes
    • Conditional moves: check CC, update dest register
    • Jumps: decide branch
  4. Memory

    • Write to memory
    • Read from memory → valM
  5. Write Back

    • Write up to two results to registers
  6. Update

    • Set PC to next instruction address

Pipelining

  • Throughput the number of instructions in one second.

    GIPS: Giga-Instructions Per Second

  • Circuit Retiming

    Repositions registers within a design to optimize performance or area, without altering the system’s input/output behavior. It changes the state encoding by moving delays (registers) across combinational logic elements.

Hazards

The dependency between instructions may lead to incorrect computation results.

Data Hazards

  • Stalling

    Stalling prevents data hazards by pausing the pipeline until required operands are ready. This approach is simple but reduces performance.

  • Data Forwarding (Bypassing)

    Data forwarding allows a result computed in a later pipeline stage to be passed directly to an earlier stage as a source operand.

  • Load/Use Hazards

    A load/use hazards occurs when an instruction requires a value that is still being loaded from memory by the previous instruction. Since the memory read completes late in the pipeline, forwarding cannot resolve the dependency in time, causing a stall.

Control Hazards

Control hazards occur when the processor cannot determine the next instruction's address during the fetch stage. In a pipelined processor, this typically happens for ret instructions and mispredicted conditional jumps.

  • ret Inserting bubbles to wait for the return address to be determined.

  • Conditional Jump Branch mispredictions are handled by cancelling the erroneously fetched instructions through the insertion of pipeline bubbles (or via instruction squashing) in the decode and execute stages.

Pipelined Y86-64 Implementations

Fetch Stage

  1. Sequential Execution

halt, nop, rrmovq, irmovq , mrmovq, Opq, pushq, popq, covXX, addq

  1. Jump Execution

call, jxx (The Select PC mechanism is employed to correct branch mispredictions.)

  1. ret

Decode Stage

The selection logic chooses between the merged valA/valP signals and one of five forwarding sources (e_valE, m_valM, M_valE, W_valM, or W_valE) based on the instruction type and hazard detection. If no forwarding is triggered, d_rvalA (the register file read) is used as the default value.

Pipeline Control Logic

  • Stall

    Keep the state of the pipeline registers unchanged. When the stall signal is set to 1, the register will retain its previous state.

  • Insert Bubbles

    Setting the state of the pipeline registers to a value equivalent to a nop instruction. When the bubble signal is set to 1, the state of the register will be set to a fixed reset configuration.

Load/Use Data

A one-cycle pipeline stall is required between an instruction that reads a memory value in the execute stage and a subsequent instruction that uses that value in the decode stage.

Mispredicted Branches

When a branch is mispredicted as taken, the pipeline must squash the incorrectly fetched instructions from the target path and redirect fetching to the correct fall-through address.

Processing ret

The pipeline must stall until the ret instruction reaches the write-back stage.

Exception Handling

When an instruction triggers an exception, all subsequent instructions must be prevented from updating programmer-visible state, and execution must halt once the exception-causing instruction reaches the write-back stage.

ConditionFDEMW
Handling retStallBubbleNormalNormalNormal
Load/Use HazardStallStallBubbleNormalNormal
Mispredicted BranchNormalBubbleBubbleNormalNormal

Chapter 5 Optimizing Program Performance

Capabilities and Limitations of Optimizing Compilers

Memory Aliasing

The two pointers probably reference the same memory address.

Function Calls

Performance

CPE: Cycles Per Element.

Understanding Modern Processors

Instruction Control Unit (ICU) & Execution Unit (EU)

The ICU reads instructions from the instruction cache and uses branch prediction to speculatively fetch and decode future instructions in advance. This speculative execution mechanism allows the processor to start executing operations along the predicted program path before the actual branch outcome is known. If the prediction is incorrect, all speculative results are discarded and execution restarts from the correct branch target.

Decoded instructions are broken down into micro-operations, which are then sent to the EU for execution. The EU includes arithmetic units and dedicated load/store units, each with address calculation logic, to perform memory operations via the data cache.

All along, the retirement unit tracks instruction progress to ensure sequential program semantics are preserved. Instructions remain in a queue until their results are ready and all relevant branch predictions are verified. Only then are results committed to the architectural registers. If a branch was mispredicted, the affected instructions are flushed and their results discarded, preventing any erroneous state change in the program.

Register renaming allows out-of-order execution by assigning unique tags to instruction results. When a later instruction needs a register value, it uses the tag to get the result directly once ready, avoiding waits for register writes and enabling speculative execution.

Each operation is characterized by the following metrics:

  • latency It represents the total time required to complete the operation.

  • Issue time It indicates the minimum number of clock cycles needed between two consecutive operations of the same type.

  • Capacity It refers to the number of functional units capable of executing that operation.