本实验是将CSAPP家庭作业后面的几个问题组合成实验作业。在实验中,我们需要修改处理器的HCL描述来增加新的指令、修改循环策略等,修改后的处理器能够被模拟,并通过运行自动化测试检测。
在本实验中,我们需要掌握Y86相关汇编语言的操作、以及对于Y86 HCL描述,并且对于流水线、程序的优化有一定的了解。
下载实验包:archlab-handout.tar
(1)相关实验包可以到以下地址下载,里面还包含详细的答案,原始tar在CSAPP Lab original tar 文件夹下https://github.com/Davon-Feng/CSAPP-Labs。本文解答的内容在yzf-archlab_handout文件夹中
https://github.com/Davon-Feng/CSAPP-Labs/tree/master/yzf-archlab-handout
(2)载入tar文件后,需要运用 tar xvf archlab-handout.tar
将文件解压。里面包含README, Makefile, sim.tar, archlab.ps, archlab.pdf, and simguide.pdf.
(3)然后运用tar命令解压sim.tar文件,进入sim文件夹执行以下命令
unix > cd sim
unix > make clean ; make
在make过程中遇到以下问题:(1).usr/bin/ld: cannot find -lfl (2).make: bison:命令未找到 (3) .make: flex:命令未找到
对于第(1)个问题,运用sudo apt-get install libfl.so解决
对于第(2、3)个问题,运用sudo apt-get install bison flex解决
2.学习和掌握《深入理解计算机系统》第二版中第4章、第五章
该实验中的任务为在sim/misc
文件夹中,运用Y86指令撰写并且模拟example.c文件中的三个函数的功能。并且运用YAS进行编译,运用YIS进行运行。Y86汇编程序的编写规则见CSAPP书本的P237页,Y86程序
本博主实现代码文件,见之前链接下载文件中sim/misc文件夹下的如下所示文件
相关编译运行代码如下
unix > ./yas A-sum.ys
unix > ./yis A-sum.yo
# Sample linked list 实验数据
.align 4
ele1:
.long 0x00a
.long ele2
.long 0x0b0
.long ele3
ele3:
.long 0
ele2:
.long 0xc00
/* linked list element */ 链表的定义
typedef struct ELE {
int val;
struct ELE *next;
} *list_ptr;
对于该实验要求作出的解答如下:
# 函数执行开始地址为0
.pos 0
init: irmovl Stack, %esp
irmovl Stack, %ebp
call Main
halt
# Sample linked list 函数操作中需要运用到的数据定义
.align 4
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
#定义Main函数,调用sum_list函数
Main: pushl %ebp
rrmovl %esp, %ebp
irmovl ele1 , %eax
pushl %eax
call sumlist
rrmovl %ebp , %esp
popl %ebp
ret
# int sum_list(list_ptr ls) 相关sum_list 函数的实现
sumlist:
pushl %ebp
rrmovl %esp ,%ebp
xorl %eax,%eax #the return val = 0
mrmovl 8(%ebp) , %edx
andl %edx , %edx #ls == 0 ?
je End
Loop: mrmovl (%edx) , %ecx #ls->val ==> %ecx
addl %ecx , %eax #val += ls->val
irmovl $4 , %edi
addl %edi , %edx #next ==> edx
mrmovl (%edx), %esi
rrmovl %esi , %edx #ls->next ==>edx
andl %edx , %edx #set condition codes
jne Loop #if ls != 0 goto Loop
End: rrmovl %ebp , %esp
popl %ebp
ret
#定义栈的起始地址
.pos 0x100
Stack:
2.模拟example函数里面的rsum_list函数,是sum_list函数的递归版本,初始,数据,Mian函数和栈代码与sum_list的均相同。下面仅显示rsum_list的实现。相关运行命令行,和运行结果与sum_list相同
rsum_list:
pushl %ebp
rrmovl %esp , %ebp
pushl %ebx
irmovl $4 , %esi
subl %esi , %esp
xorl %eax , %eax
mrmovl 8(%ebp),%edx
andl %edx , %edx
je End
mrmovl (%edx) , %ebx
irmovl $4 , %esi
addl %esi , %edx
mrmovl (%edx) , %edi
rmmovl %edi , (%esp)
call rsum_list
addl %ebx , %eax
End:
addl %esi , %esp
popl %ebx
popl %ebp
ret
3.copy_block函数,拷贝源地址数据到目标地址,并且计算所有数据Xor值,相关实现代码如下所示。
.pos 0
init: irmovl Stack, %esp
irmovl Stack, %ebp
call Main
halt
.align 4
# Source block
src:
.long 0x00a
.long 0x0b0
.long 0xc00
# Destination block
dest:
.long 0x111
.long 0x222
.long 0x333
Main: pushl %ebp
rrmovl %esp , %ebp
irmovl $12 , %esi
subl %esi , %esp
irmovl src , %eax
rmmovl %eax , (%esp)
irmovl dest , %eax
rmmovl %eax , 4(%esp)
irmovl $3, %eax
rmmovl %eax, 8(%esp)
call copy_block
irmovl $12 , %esi
addl %esi , %esp
popl %ebp
ret
copy_block:
pushl %ebp
rrmovl %esp, %ebp
xorl %eax , %eax
mrmovl 12(%ebp) , %edx #edx <==>dest
mrmovl 8(%ebp) , %esi #esi <==> src
mrmovl 16(%ebp),%ecx #ecx <==> len
andl %ecx, %ecx
je End
Loop: mrmovl (%esi) , %ebx
rmmovl %ebx , (%edx) #copy src value to dest
xorl %ebx , %eax #compute the value ^= val
irmovl $4 , %edi
addl %edi , %edx #dest++
addl %edi , %esi #src++
irmovl $1,%edi
subl %edi , %ecx #len--
jne Loop
End: popl %ebp
ret
.pos 0x100
Stack:
相关运行结果:关注寄存器%eax中和0x00000111 ~ 0x000000333存储器中的答案
本实验的工作目录在sim/seq文件夹下,修改seq-full.hcl文件,添加新指令。
实验要求:相关指令的实现需求见《深入理解计算机系统》P310
(1)实现 iaddl指令 要求见练习题4.48、4.50,可以参考irmovl、opl的实现
(2)实现 leave指令 要求见练习题4.47、4.49,可以参考popl的实现
首先修改seq-full.hcl文件需要于都CSAPP处理器体系结构相关章节内容。实验的评分要求中,还需要写出iaddl、leave在顺序实现中的计算过程。
结合irmovl、opl的计算过程,通过分析,我们得到iaddl的计算过程如下:
结合popl的,结合leave指令分析分析得到:
%ebp-new = (%ebp-old) (新ebp指向的地址等于原ebp指针指向的存储器地址中的内容)
%esp-new = %ebp-old+4 (新esp指向的地址为原ebp指向的地址+0x4)
结合分析得到如下的计算过程
相关seq-full文件的修改如下所示:相关文件见下载链接中的seq-full.hcl文件
相应修改的结果通过了实验规定的测试。
注意编译时,可能遇到tcl not found;tk not found;libtcl not found;libtk not found问题
解决方法1: 将Make里面的注释“Comment this out if you don’t have Tcl/Tk.”下的行注释或删除
解决方法2:
tcl和tk文件:sudo apt-get install tk8.5-dev cl-8.5-dev
(一定要版本小于等于8.5,8.6版本有些属性已经被删除)
libtk和libtcl:sudo ln -s /usr/lib/x86_64-linux-gnu/libtk8.5.so /usr/lib/libtk.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libcl8.5.so /usr/lib/libtcl.so
实验C主要在sim/pipe文件夹下,任务为修改ncopy.ys和pipe-full.hcl 文件使得ncopy.ys 的运行速度越快越好。
pipe-full.hcl 推荐实现iaddl指令。在仅实现iaddl并且将ncopy.ys中的相应指令替换为iaddl后,时间由原来的16.44 提升到了13.96。相应iaddl在pip-full.hcl中的实现方法与partB中的实现类似,实现的结果见下载链接文件。
其中该部分实验最主要实现的是优化ncopy.ys函数。本解法主要涉及到的是CSAPP第五章的优化方法中的“循环展开方法”和第4章中的“加载使用冒险”
对于ncopy.ys中的ncopy函数进行了4次的循环展开。并且在原始的函数中存在加载使用冒险
,如下所示,mrmovl从存储器中读入src到esi,rmmovl从esi存储到dest中,期间因为加载使用冒险所以需要暂停一个周期,针对这个进行改进。
mrmovl (%ebx), %esi # read val from src
rmmovl %esi, (%ecx) # store src[0] to dest[0]
主要改进的方法在这两条指令中插入另一条mrmovl指令,避免了冒险节省时间,也为后面的循环展开提前获取到了值。
ncopy.ys相应改进部分实现如下所示:
# You can modify this portion
# Loop Header
xorl %eax , %eax
iaddl $-4 , %edx #len = len -4
andl %edx , %edx
jl remian
Loop: mrmovl (%ebx) , %esi
mrmovl 4(%ebx),%edi
rmmovl %esi , (%ecx)
andl %esi ,%esi
jle LNpos1
iaddl $1 , %eax
LNpos1: rmmovl %edi , 4(%ecx)
andl %edi , %edi
jle LNpos2
iaddl $1, %eax
LNpos2:mrmovl 8(%ebx) , %esi
mrmovl 12(%ebx),%edi
rmmovl %esi ,8 (%ecx)
andl %esi ,%esi
jle LNpos3
iaddl $1 , %eax
LNpos3: rmmovl %edi , 12(%ecx)
andl %edi , %edi
jle nextLoop
iaddl $1, %eax
nextLoop:
iaddl $16,%ebx
iaddl $16,%ecx
iaddl $-4,%edx
jge Loop
# maybe just remain less than 3
remian: iaddl $4 , %edx # Restore the true len
iaddl $-1, %edx
jl Done
mrmovl (%ebx) , %esi
mrmovl 4(%ebx),%edi
rmmovl %esi , (%ecx)
andl %esi ,%esi
jle rNpos
iaddl $1 , %eax
rNpos:
iaddl $-1, %edx
jl Done
rmmovl %edi , 4(%ecx)
andl %edi , %edi
jle rNpos1
iaddl $1, %eax
rNpos1:
iaddl $-1 , %edx
jl Done
mrmovl 8(%ebx) , %esi
rmmovl %esi , 8(%ecx)
andl %esi ,%esi
jle Done
iaddl $1 , %eax
##################################################################