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: