4.52以后的题目中的代码大多是书上的,如需使用请联系 [email protected]
更新:关于编译Y86-64中遇到的问题,可以参考一下CS:APP3e 深入理解计算机系统_3e Y86-64模拟器指南
流水线部分只写了偶数题号的,这几天太浮躁,落下了好多课。。。
4.45
A. 不正确,当REG为%rsp时,这样会压入%rsp - 8而非%rsp
B. 对于 pushq REG:
4.46
A. 不正确,当REG为%rsp是,这样会使得%rsp的值为(%rsp) + 8 而非(%rsp)
B. 对于popq REG:
4.47
A. (不知道这题有什么意义。。。)
B. bubblesort.ys:
运行结果如下:

可以看到,之前由大到小的数组被排列成了由小到大的顺序。另外,0x01f0和0x01f8处是压入的两个返回地址,不是数组边界溢出。
4.48
书上6-11行为:
其对应4.47里面的:
将其改为条件转移,使用了两个<code>cmovl</code>:
4.49
这一题要求只能使用一个<code>cmov</code>指令实现书上的6-11行。我们首先分析一下4.48里面两条<code>cmov</code>冗余的地方:我们使用了两个<code>cmovl</code> ,其实这两个的条件码是一样的。于是我们可以使用一个<code>cmovl</code> 到一个寄存器A,然后在另一个寄存器B用算术运算将其线性关联起来(例如减法)。例如,如果我们要交换[A],[B],我们先将[A]存在%r1, -[A]存在%r2,<code>cmovl</code> [B], %r1,<code>addq</code> %r1, %r2,这时如果[A]大于[B],%r1中为[B],%r2中为[B]-[A],否则%r1中为[A],%r2中为0。随后,我们将%r1赋值给A,[B]-%r2赋值给B即可。
代码如下:
这里要注意一下,我这里为了方便使用了%r12寄存器,但是它是一个Callee saved的,所以我们要在<code>bubblesort</code>首尾分别加上<code>pushq %r12</code>和<code>popq %r12</code> .
4.50
这里要特别注意到原来的stack为0x200,这个时候的代码量会导致代码区段淹没到栈的部分,所以要将stack的位置增高一些。
4.51
iaddq V, rB
Fetch:
icode:ifun <-- M1[PC]
rA:rB <-- M1[PC+1]
valC <-- M8[PC+2]
valP <-- PC+10
Decode:
valB <-- R[rB]
Execute:
ValE <-- valB + valC
Memory:
Write back:
R[rB] <-- valE
PC update:
PC <-- valP
4.52
由4.51 ,在seq-full.hcl中添加IIADDQ,得到如下代码:
4.54
pipe-full.hcl:
4.56
pipe-btfnt.hcl:
4.58
这个题巴拉巴拉说了一大堆就是要处理<code>popq</code>的情况。其中有一个方法就是使用4.46里面的替换策略,将<code>popq</code>动态替换为(这里我们先实现为<code>iaddq</code> ):
处理<code>iaddq</code>后,在第二次fetch的时候PC不变,但是icode变为一个特殊的编码(书上说的是IPOP2),以此来识别进行<code>mrmovq 8(%rsp), REG</code>的操作。书上把要改变的地方用“1W”标出来了。
pipi-1w.hcl: