Chapter 1 A Tour of Computer System
Compilation System
Take C language as an example linux > gcc hello.c -o hello.
-
Pre-processor (cpp)
Handles include/define, strips off comments and conditional compilation #ifdef
-
Compiler (cc1)
Scan/parse/semantic check/code gen/opt
-
Assembler (as)
From assembly to machine code
-
Linker (ld)
Relocation & reference resolution [重定位 & 引用解析]
Hardware Organization of a System
DMA (Direct Memory Access) is usually used for high-spped and bulk data transfers, controlled by system programmers.
-
System Bus
Transfer data in fixed-size blocks called words (4/8 bytes on a 32/64 bit system)
Memory Hierarchy
The localities of cache: Temporal Locality & Spatial Locality.
Abstractions in Computer Systems (Virtualization)
Virtualization is often related to multiplicity, fake versions, and sharing.
-
Process & Thread
Multiple processes can run concurrently on the same system, and each process appears to have exclusive use of the hardware.
Context switching with OS Kernel.
A process can actually consist of multiple execution units, called threads. Threads shares the same code and global data.
-
Virtual Memory
Program Code & Data, Shared Libraries, Heap, Stack, Kernel Virtual Memory from bottom to top.
-
Virtual address space canve greater than the physical memory.
-
Memory serves as a cache for virtaul memory.
-
Support multiprogramming.
-
Allow multiple processes to share data.
-
-
File
Import Themes
Amdahl's Law (Quantifying the performance improvement ceiling)
Concurrency and Parallelism
-
Concurrency It refers to the general concept of a system having multiple, simultaneous activities, which do not necessarily execute at the same time, but may interleave in time to create the logical impression of simultaneity.
-
Parallelism It refers to the use of concureency to make a system run faster.
ILP and DLP
-
Instruction-Level e.g. Parallelism pipelining, superscalar, out-of-order execution.
-
Data-Level Parallelism e.g. Single Insruction Multiple Data (SIMD), Vector instructions.
Chapter 2 Representing and Manipulating Information
Information Storage
-
Words
word size virtual address space
-
Addressing and Byte Ordering Big endian & Little endian
-
ABI Application Binary Interface
It is based on three key components : the computer ISA, the OS, and the calling convention. ABI incompatibility will occur due to differences between operating systems.
Integer Representaions
Sizes of Data Type in C/C++
| Signed | Unsigned | 32-bit (Bytes) | 64-bit (Bytes) |
|---|---|---|---|
| 1 | 1 | ||
| 2 | 2 | ||
| 4 | 4 | ||
| 4 | 4 | ||
| 8 | 8 | ||
| — | |||
| — | 4 | 4 | |
| — | 8 | 8 |
Unsigned Encodings
Suppose a vector , then
Two's Complement Encodings
Inverse form (1's Complement) For a negative number, keep the signed the same and invert the rest.
two zero exits & end-round carry out issues (hte end carry-out bit needs to add back to the LSB)
2's Complement For a negative number, keep the sign the same, invert the rest and add 1.
Suppose a vector , then
Conversions between Signed and Unsigned
For a -bit 2's complemetn signed binary numeral system:
- Minimum , corresponding to binary (A special case that does not satisfy the invert bits and add 1 rule used for other negative numbers).
- Maximum , corresponding to binary .
Sign Extension
Small to Big
-
Zero extension of unsigned numbers
-
Sign extension of two's complement numbers
Since , by induction, we can proof it.
Big to Small
Integer Arithmetic
Addition
Additive Inverse
-
For two numbers A, B, the overflow occurs when
(NOT (sign_A XOR sign_B)) AND (sign_A XOR new_sign) == 1. (Two operands have the same sign but the result has a different sign.) -
One Bit Full Adder
-
Carry Lookahead Adder
Multipilication
Division (by a power of 2)
Unsigned numbers use logical shift, while two's complement numbers use arithmetic shift to achieve sign-preserving extension.
Right shift performs integer division by powers of two :
Floating Point
Floating-Point Representation
s (sign) : The number is positive () or negative ().
M (fraction) : A binary fraction.
E (exponent) : weight.
()
| Category | Exponent | Fraction | Value Formula |
|---|---|---|---|
| Normalized | any | ||
| Denormalized | |||
| Zero | |||
| Infinity | |||
| NaN (Not a Number) | NaN |
Comparison (postive number)
| Format | Minimum | Maximum |
|---|---|---|
| Single Precision Normalized | | |
| Single Precision Denormalized | | |
Rounding
| Round-down | Round-up | Round-toward-zero | Round-to-even |
|---|---|---|---|
Non-midpoint round to the nearest representable value Midpoint choose the one |
Floating Point Operations
Lack of Associativity & Lack of Distributivity
Example Questions
Let are of type int, float, double (Their values are arbitrary, except that neither nor equals , , or .). Then:
x == (int)(double) xTruex == (int)(float) xFalse (e.g. )d == (double)(float) dFalse (e.g. )f == (float)(double) fTrued*d >= 0.0True
Precision (IEEE 754-2008 Standard Formats)
| Format | Sign Bits | Exponent Bits | Mantissa Bits |
|---|---|---|---|
| Quad precision | 1 | 15 | 112 |
| Double precision | 1 | 11 | 52 |
| Single precision (FP32) | 1 | 8 | 23 |
| Half precision (FP16) | 1 | 5 | 10 |
bfloat16
- Format: 1 sign, 8 exponent, 7 mantissa bits
- Same exponent range as FP32 (faster computation, lower power, reduces memory footprint, enables larger models)
- Reduced precision acceptable for AI (AI/LLM is based on predictions – approximation does not require high precision)
FMA/FMAC
Fused Multiply and Add (FMA) or Fused Multiply and Accumulate (FMAC) combines multiply and add in one instruction ().
- Partial Product Generation
- Partial Product Reduction
- Final add together with the last step of reduction
- Normalization & Rounding
Use -mfma -ffp-contract=fast to enable FMA.
Chapter 3 Machine-Level Representation of Programs
Machine-Level Representation of Programs
RISC
Principles
- Simplicity favors regularity
- Smaller is faster
- Make common cases fast
- Good design demands good compromises
[RSA should be scalable, flexible, and extensible.]
Instruction Types in RV32I


| Types | Instructions |
|---|---|
| ALU | add, sub, and, or, xor, slt, sltu, sll, srl, sra, and all with immediate (No subi in RV32I) |
| Control Instructions | beq, bne, blt, bge, bltu, bgeu, jal, jalr |
| Memory Instructions | lw (No lwu in RV32I), lh, lb, sw, sh, sb, lbu, lhu |
| Privileged Instructions | Interrupt, Memory Management, System Calls, Control and Status Registers (CSR), Mode Change |
| Format | Name | Instructions |
|---|---|---|
| R-type | Register | add, sub, sll, srl, sra, xor, or, and |
| I-type | Immediate | addi, slli, srli, srai, xori, ori, andi |
| I-type | Load | lb, lh, lw, lbu, lhu |
| I-type | Jump and Link Register | jalr |
| S-type | Store | sb, sh, sw |
| B-type | Branch | beq, bne, blt, bge, bltu, bgeu |
| U-type | Upper Immediate | lui, auipc |
| UJ-type | Unconditional Jump | jal |
-
Three operand instruction format.
-
X0 is always zero.
-
32 means Address cability/Integer register length.
-
Immediate
- type No immediate.
- type 12 bits immediate. Shift instructions are I-type but repurpose the immediate field as a 5-bit shift amount for RV32I (6-bit for RV64I).
inst[30]distinguishes arithmetic from logical right shift, whileinst[31:26]are fixed to zero exceptinst[30](Range: ). - type The 12‑bit immediate is split into high 7 bits (immediate) and low 5 bits (immed). (maintain regularity)
- type 20 bits immediate.
-
LUI loads a 20‑bit immediate into the upper bits of a register; AUIPC adds a 20‑bit immediate to the current PC for position‑independent addressing. (When the lower 12 bits of a 32‑bit constant are ,
addisign‑extends them, causing an incorrect result. The assembler automatically adjusts the upper 20 bits when using thelipseudo‑instruction.) (Range: ) -
Jump
-
jal- , (Jumps are 2-byte aligned, so last bit is implicit zero).
- Range: .
- Beyond 1MB: Use AUIPC + JALR.
-
jalr- , ( clears LSB to ensure 2‑byte alignment).
-
Why do RISC-V loads/stores use base+immediate instead of base+index?
- Simpler hardware Only one address adder needed, reducing complexity.
- Faster address generation Immediate available at decode, no wait for index register.
- Fewer pipeline stalls Early hazard detection reduces bubbles.
Data Alignment
- No cache line crossing
- No double TLB (Translation Lookaside Buffer) misses
- No double page faults come from a single memory instruction execution
- Better cache line utilization
Stack / Frame Alignments
- Defined by ABI (e.g., RISC‑V psABI: 16‑byte)
- CRT aligns
spbeforemain ()
Compiler Reordering
-
Independent Variables (Rearrangement Allowed)
-
Struct Fields (Rearrangement Forbidden)
- Binary compatibility
- Pointer arithmetic
- Interoperability
PC-relative Addressing
Branch instructions use PC‑relative addressing with a 12‑bit signed offset (in 2‑byte units). Since branch targets are always multiples of 2, encoding in 2‑byte units doubles the reachable range without losing information.
Calling Convention
| RV Registers | ABI Name | Caller/Callee | Purpose |
|---|---|---|---|
| x0 | zero | — | Always zero |
| x1 | ra | Caller | Return address |
| x2 | sp | Callee | Stack pointer |
| x3 | gp | — | Global pointer (not used in typical code) |
| x4 | tp | — | Thread pointer (TLS) |
| x5–x7 | t0–t2 | Caller | Temporary registers |
| x8 | s0 / fp | Callee | Saved register / Frame pointer |
| x9 | s1 | Callee | Saved register |
| x10–x11 | a0–a1 | Caller | Arguments / Return values |
| x12–x17 | a2–a7 | Caller | Arguments |
| x18–x27 | s2–s11 | Callee | Saved registers |
| x28–x31 | t3–t6 | Caller | Temporary registers |
Leaf routines use args & caller‑saved only (no save/restore).
CISC
Size of Data Type in IA32
| C declaration | Intel data type | Assembly-code suffix | Size (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)
| Type | Form | Operator Value | Name |
|---|---|---|---|
| Immediate | Immediate | ||
| Register | Register | ||
| Memory | Scaled Indexed | ||
| Memory | Absolute | ||
| Memory | Indirect | ||
| Memory | Base + Displacement | ||
| Memory | Indexed | ||
| Memory | Indexed | ||
| Memory | Scale Indexed | ||
| Memory | Scale Indexed | ||
| Memory | Scale 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.)
movlwrites 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.)movqcan only be 32 bits (sign-extended to 64 bits), whereasmovabsqcan be 64-bit but the destination must be a register. -
[
movzbw,movzbl,movzwl,movzbq,movzwq]movzlqdoes not exist because ofmovlinstruction. -
[
movsbw,movsbl,movswl,movsbq,movswq,movslq,cltq]cltqsame asmovslq %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
| Instructions | Effect |
|---|---|
inc D | |
dec D | |
neg D | |
not D |
Binary Operations
| Instructions | Effect |
|---|---|
add S D | |
sub S D | |
imul S D | |
xor S D | |
or S D | |
and S D |
Shift Operations
| Instructions | Effect |
|---|---|
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
| Instruction | Effect | Description |
|---|---|---|
sete D | ||
setne D | ||
sets D | negative | |
setns D | nonnegative | |
setg D | Signed | |
setge D | Signed | |
setl D | Signed | |
setle D | Signed | |
seta D | Unsigned | |
setae D | Unsigned | |
setb D | Unsigned | |
setbe D | Unsigned |
Jump Instructions
| Instruction | Jump Condition | Description |
|---|---|---|
jmp Label | Direct Jump | |
jmp *Operand | Indirect Jump | |
je Label | ||
jne Label | ||
js Label | Negative | |
jns Label | Nonnegative | |
jg Label | Signed | |
jge Label | Signed | |
jl Label | Signed | |
jle Label | Signed | |
ja Label | Unsigned | |
jae Label | Unsigned | |
jb Label | Unsigned | |
jbe Label | Unsigned |
Conditional Move Instructions
| Instruction | Move Condition | Description |
|---|---|---|
cmove S, R | ||
cmovne S, R | ||
cmovs S, R | Negative | |
cmovns S, R | Nonnegative | |
cmovg S, R | Signed | |
cmovge S, R | Signed | |
cmovl S, R | Signed | |
cmovle S, R | Signed | |
cmova S, R | Unsigned | |
cmovae S, R | Unsigned | |
cmovb S, R | Unsigned | |
cmovbe S, R | Unsigned |
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
| Instruction | Description |
|---|---|
call Label | Procedure Call (Direct) |
call *Operand | Procedure Call (Indirect) |
ret | Return 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
| Expression | Type | Value | Assembly Code |
|---|---|---|---|
E | int* | movq %rdx, %rax | |
E[i] | int | movl (%rdx, %rcx, 4), %eax | |
&E[i] | int* | leaq 8(%rdx, %rcx, 4), %rax | |
&E[i] - E | long | movq %rcx, %rax |
Notes:
-
&E[i] - Eyields typelong(specificallyptrdiff_t) because pointer subtraction returns the number of elements between them as a signed integer. -
int*usesmovq(notmovl) 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:
-
The address of any K-byte basic object must be a multiple of .
-
The offset of the first member is always 0 in a structure.
-
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 :
-
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
- Read instruction bytes from memory using PC:
-
Decode
- Read up to two operands from registers
rA, rB→valA, valB- For
popq,pushq,call,ret: also read from%rsp
-
Execute
- Compute (ALU/address/stack) →
valE - Set condition codes
- Conditional moves: check CC, update dest register
- Jumps: decide branch
- Compute (ALU/address/stack) →
-
Memory
- Write to memory
- Read from memory →
valM
-
Write Back
- Write up to two results to registers
-
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.
-
retInserting 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
- Sequential Execution
halt, nop, rrmovq, irmovq , mrmovq, Opq, pushq, popq, covXX, addq
- Jump Execution
call, jxx (The Select PC mechanism is employed to correct branch mispredictions.)
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
nopinstruction. 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.
| Condition | F | D | E | M | W |
|---|---|---|---|---|---|
Handling ret | Stall | Bubble | Normal | Normal | Normal |
| Load/Use Hazard | Stall | Stall | Bubble | Normal | Normal |
| Mispredicted Branch | Normal | Bubble | Bubble | Normal | Normal |
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.