IA32 Assembly拆分缓存地址为tag、索引、偏移时出现段错误求助
问题排查与解决
现有代码的核心错误
- 违反IA32调用约定:
%ebx是被调用者需保存的寄存器,直接修改会破坏调用方上下文,是触发段错误的核心原因。 - 地址字段拆分错位:按照缓存参数,8位地址的结构为
高4位tag + 中间2位组索引 + 最低2位块偏移,你的代码把最低2位识别为tag、高4位识别为偏移,完全错位。 - 缺失核心逻辑:仅完成了地址拆分,没有实现cache行校验、tag匹配、返回值设置的逻辑,函数功能不完整。
- 不符合题目要求:未使用8位位操作指令,全程使用32位指令处理8位地址参数。
地址拆分规则确认
本次缓存参数:块大小B=4、组数S=4、直接映射E=1,8位地址拆分规则如下:
- 块偏移:占最低2位,对应掩码
0x3,无需移位 - 组索引:占第2~3位,对应掩码
0x3,需右移2位后取低2位 - 标签tag:占最高4位,对应掩码
0xF,需右移4位后取低4位
修正后的实现代码
.global check_cache check_cache: pushl %ebp movl %esp, %ebp pushl %ebx # 保存被调用者寄存器%ebx,符合调用约定 movl 8(%ebp), %ebx # %ebx存cache数组首地址 movb 12(%ebp), %al # %al存8位地址addr # 拆分三个地址字段 movb %al, %cl andb $0x3, %cl # %cl = 块偏移offset movb %al, %dl shrb $2, %dl andb $0x3, %dl # %dl = 组索引index shrb $2, %al andb $0xF, %al # %al = tag # 计算对应cache行的地址:每个line占6字节(1+1+4,无对齐填充) movzbl %dl, %edx leal (%ebx, %edx, 6), %ebx # %ebx = 对应cache行的指针 # 检查valid位和tag匹配 cmpb $0, (%ebx) je miss # valid位为0直接未命中 cmpb %al, 1(%ebx) jne miss # tag不匹配未命中 # 命中,返回block[offset] movzbl %cl, %ecx movb 2(%ebx, %ecx), %al # valid偏移0,tag偏移1,block起始偏移2 jmp exit miss: movb $0xFF, %al # 未命中返回0xFF exit: popl %ebx # 恢复%ebx popl %ebp ret
不用位操作指令的实现方案
可以通过除法和取余运算实现等价的拆分逻辑,本质和位操作等价,但执行效率更低:
- 块偏移:
addr % 4 - 组索引:
(addr / 4) %4 - tag:
addr / 16
不过这种方式最终编译出来还是会被优化为位操作,建议优先使用题目推荐的位操作指令实现。
内容的提问来源于stack exchange,提问作者Bradley
相关产品推荐
相关产品推荐

