CS61C Lecture08: RISC-V lw, sw, Decision 1
一、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 指令
- 立即数范围:12位有符号数(-2048 ~ 2047) - 扩展机制:符号扩展到32位2. 大立即数处理
- 使用lui(Load Upper Immediate)指令加载高20位:
三、条件分支指令
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结构示例:
四、内存层次结构与优化
1. 存储技术对比
| 类型 | 速度 | 容量 | 用途 |
|---|---|---|---|
| SRAM | 最快 | 最小 | CPU缓存 |
| DDR SDRAM | 中等 | 大 | 主内存 |
| HBM | 较高 | 较大 | GPU/高性能计算 |
2. 局部性原理
- 时间局部性:最近访问的数据可能再次被访问
- 空间局部性:相邻内存位置可能被访问
- 编程实践:优化数据访问模式(如行优先遍历数组)
五、编译器优化策略
1. 寄存器分配优化
- 优先使用临时寄存器(t0-t6)
- 减少保存寄存器(s0-s11)的溢出操作
- 循环展开减少分支指令
2. 典型优化案例
// 原始代码
for (int i=0; i<100; i++) {
sum += array[i];
}
// 优化后汇编可能使用:
// 1. 指针算术替代数组索引
// 2. 循环展开4次减少分支判断
// 3. 寄存器保留sum避免内存访问
六、重点概念对比
| 概念 | 有符号处理 | 无符号处理 |
|---|---|---|
| 加载字节 | lb(符号扩展) | lbu(零扩展) |
| 比较指令 | blt/bge | bltu/bgeu |
| 溢出处理 | 补码运算 | 模运算 |
七、常见问题解析
- 为什么偏移量要是4的倍数?
- RISC-V采用32位字长,4字节对齐提高访问效率
-
非对齐访问需要多次内存操作
-
如何处理超过12位的立即数?
- 使用lui加载高20位
- 配合addi/add处理低12位
-
示例:加载0x12345678 → lui + addi
-
如何实现switch语句?
- 使用跳转表(Jump Table)
- 通过slli计算偏移量