Skip to content

CS61C Lecture08: RISC-V lw, sw, Decision 1

约 724 个字 23 行代码 预计阅读时间 4 分钟 共被读过

一、RISC-V 内存操作指令

1. 寄存器与内存特性

  • 32个寄存器(x0-x31)速度比内存快约50倍
  • 特殊用途寄存器
  • x0 (zero): 恒为0
  • sp (x2): 栈指针
  • ra (x1): 返回地址
  • a0-a7 (x10-x17): 函数参数/返回值
  • s0-s11 (x8-x9, x18-x27): 保存寄存器
  • t0-t6 (x5-x7, x28-x31): 临时寄存器

2. 内存访问指令

指令 格式 功能 特点
lw lw rd, offset(rs1) 从内存加载32位字 偏移量必须是4的倍数
sw sw rs2, offset(rs1) 存储32位字到内存 数据流向:寄存器 → 内存
lb lb rd, offset(rs1) 加载字节(符号扩展) 用于char类型处理
lbu lbu rd, offset(rs1) 加载字节(零扩展) 处理无符号字符
sb sb rs2, offset(rs1) 存储字节 仅存储低8位

内存对齐原则
- 32位字必须位于4字节对齐地址
- 示例:int数组访问时,地址偏移量总是4的倍数(假设int为4字节)


二、立即数操作

1. addi 指令

Text Only
addi rd, rs1, imm  # rd = rs1 + sign_extend(imm)

- 立即数范围:12位有符号数(-2048 ~ 2047)
- 扩展机制:符号扩展到32位

2. 大立即数处理

  • 使用lui(Load Upper Immediate)指令加载高20位:
    Text Only
    lui x5, 0x12345    # x5 = 0x12345 << 12
    addi x5, x5, 0x678 # x5 = 0x12345678
    

三、条件分支指令

1. 基础分支指令

指令 功能 伪代码表示
beq 相等时跳转 if (rs1 == rs2) PC += offset
bne 不等时跳转 if (rs1 != rs2) PC += offset
blt 有符号小于时跳转 if (rs1 < rs2) PC += offset
bltu 无符号小于时跳转 if (rs1 < rs2) PC += offset
bge 有符号大于等于时跳转 if (rs1 >= rs2) PC += offset

2. 分支指令特点

  • 地址范围限制:±4KB范围(12位立即数 × 4字节)
  • 延迟槽:RISC-V无延迟槽,直接顺序执行

3. 条件判断模式

if-else结构示例

C
if (i == j) { ... } else { ... }

Text Only
    bne x13, x14, Else  # 相反条件判断
    # if-block
    j Exit
Else:
    # else-block
Exit:

四、内存层次结构与优化

1. 存储技术对比

类型 速度 容量 用途
SRAM 最快 最小 CPU缓存
DDR SDRAM 中等 主内存
HBM 较高 较大 GPU/高性能计算

2. 局部性原理

  • 时间局部性:最近访问的数据可能再次被访问
  • 空间局部性:相邻内存位置可能被访问
  • 编程实践:优化数据访问模式(如行优先遍历数组)

五、编译器优化策略

1. 寄存器分配优化

  • 优先使用临时寄存器(t0-t6)
  • 减少保存寄存器(s0-s11)的溢出操作
  • 循环展开减少分支指令

2. 典型优化案例

C
// 原始代码
for (int i=0; i<100; i++) {
    sum += array[i];
}

// 优化后汇编可能使用:
// 1. 指针算术替代数组索引
// 2. 循环展开4次减少分支判断
// 3. 寄存器保留sum避免内存访问

六、重点概念对比

概念 有符号处理 无符号处理
加载字节 lb(符号扩展) lbu(零扩展)
比较指令 blt/bge bltu/bgeu
溢出处理 补码运算 模运算

七、常见问题解析

  1. 为什么偏移量要是4的倍数?
    - RISC-V采用32位字长,4字节对齐提高访问效率
    - 非对齐访问需要多次内存操作

  2. 如何处理超过12位的立即数?
    - 使用lui加载高20位
    - 配合addi/add处理低12位
    - 示例:加载0x12345678 → lui + addi

  3. 如何实现switch语句?
    - 使用跳转表(Jump Table)
    - 通过slli计算偏移量

    Text Only
    slli x10, x5, 2   # 索引×4(每条指令4字节)
    add x10, x10, x6   # x6存储跳转表基址
    lw x11, 0(x10)     # 获取目标地址
    jr x11             # 跳转