contributed by <raygoah
>
FuncA 的作用:
可以看到一開始的 if 中,若此 linked list 還沒有創立,這時建立一個 node 作為 linked list 的開頭,被指標 start 所指向,而這邊特別注意到,new_node->next = new_node->prev = new_node;
這一行,在這裡指向下一個 node 的指標 next 以及指向前一個 node 的指標 prev,都是指向自己的
從題目中可以知道,此 linked list 為環狀,同時為雙向,接著從第 12 到第 14 行中可以看出,新增 node 時,新 node 的 prev 會指向原本 linked list 中的最後一個 node,同時新 node 的 next 會指向 start node,因此可以知道 FuncA 中新增 node 時,是將 node 插入在 linked list 的最尾端
因此由上可得,FuncA 中所做的事為 (e)
建立新節點,內容是 value
,並安插在結尾
FuncB 的作用:
(d)
建立新節點,內容是 value
,並安插在開頭FuncC 的作用:
在 FunC 中可以看到,其中有一個 while 迴圈,在迴圈中尋找值和 value2 相同的 node,接著在第 7 到第 11 行中可以看到,程式將新建立值為 value 1 的 node,插入在剛剛找到的值為 value2 的 node 後面
由上面可以知道,在 FuncC 中所做的,是將值為 value1 的 node,插入在值為 value2 的 node 後面,因此答案要選:(e)
找到節點內容為 value2
的節點,並在之後插入新節點,內容為 value1
在程式輸出中,訊息 Traversal in forward direction
後依序印出哪幾個數字呢?
value
,並安插在結尾value
,並安插在開頭value2
的節點,並在之後插入新節點,內容為 value1
在程式輸出中,訊息 Traversal in reverse direction
後依序印出哪幾個數字呢?
FuncX 的作用:
在 for 迴圈中可以看到,node 會從 head 的下一個開始,依序造訪整個 linked list ,直到當前的 node 為 null 或是指回 head 時停止,而最後回傳的值為 node - head
,若目前 node 正好為 head 的時候,便回傳 0,不是則回傳非 0 的數字
因此此題要選 (e)
判斷是否為 circular linked list,若為 circular 則回傳 0
,其他非零值
K1 K2 K3 K4 K5 >> 後面接的輸出為何
依照順序建立 linked list,[ ] 內為 node 的值
head[0] -> [1]
head[0] -> [1] -> [2]
head[0] -> [1] -> [2] -> [3]
head[0] -> [1] -> [2] -> [3] -> [4]
因此第 14 行中,linked list 不為 circular 因此回傳非 0 值,故 k1 為 Yes
第 15 行中,head->next->next->next->next = head;
,會將 [3] 的 next 接回 head,形成 circular,因此 k2 為 No,
head[0] -> [1] -> [2] -> [3] -> head[0]
第 17 行中,head->next->next->next->next->next = head->next;
,所形成的 linked list 和第 15 行中的 linked list 相同,並未改變,因此 k3 和 k2 一樣為 No
head[0] -> [1] -> [2] -> [3] -> head[0]
第 19 行中,head->next = head->next->next->next->next->next->next->next->next;
,等號右邊為 [0],會形成 head[0] -> head[0]
,因此為 circular ,k4 為 No
第 21 行中,因為 linked list 為 head[0] -> head[0]
因此 k5 的值為 0
count >>
後面接的輸出為何
FuncX(head, &count)
傳入 count 的記憶體位址,但是在 FuncX 中,做的是 data++ 而不是 * data++ ,因此並不會實際計算走訪的 node,所以最後離開 FuncX 後 count 值仍為 0Func 32 = ?
從式碼中可以看到,裡面有個遞迴呼叫,每次都把 x 右移 1 位,直到 x 的值為 0 時,會回傳 32,這時表示經過多次右移後得到的 x 其所有 bits 全部都為 0,但因為每次遞迴呼叫回傳後,後面還會將回傳值減掉 1,減一的意思代表著,這次右移去除掉的那個 bit,其存在不屬於從左到右連續全為 0 的一份子,因此把這些不屬於的部分一一減掉,便會得到一個 的數字
而這個數字換句話說,便等於最一開始的 x 從左到右,從高位元到低位元共有幾個連續的 0
因此此題要選: © 計算輸入數值 x 的二進位表示中,回傳開頭 (從高位到低位元) 有幾個 0,倘若 x 為 0x0,則輸出 32
M1, M2, M3 = ?
Func64 的作用為?
P1 應該為?
此函式是用來進行 32 位元的除法,在第六行中,先計算出 divisor 和 dividend 開頭皆為 0 的數字長度差距,差距為 mask
在第八行中,把除數向左移位 mask 位,為的就是讓除數對齊被除數,這樣才能達成我們平常在長除法時,從最高有效位開始做除法的目的,而在二進位中,因為只有 1 跟 0,所以除法是用減的,不需要計算相差幾倍的問題
參考 What does (1U << X) do?,才知道原來第九行中的 1U 是這個意思,代表把第 0 個 bit 設為 1,接著同樣移位 mask 位,讓 1 能夠對齊被除數的最高有效位
接著便是實際除法的部份,do while 中,被除數大於除數時,就讓被除數減掉除數後更新成新的被除數,接著第 13 行所做的便是除法中差幾倍的概念,只是因為數字都是 0 和 1,所以針對 mask 中 bit 為 1 的那一位數用 OR 的方式 set 在商數中,這樣有進行被除數和除數的相減時,對應的 bit 就會被設為 1,反之就會被設為 0
而藉由上面除法的過程,可以知道 mask 每次都必須要更新,需要向右移位一次,才能在每次要 set 商數時,能夠 set 到正確的 bit,所以得到 P1 必須填入 mask >> 1
P2 應該為?
udiv64 做的事情和 udiv32 相同,本質上也就是除法,但不同的地方在於這邊是針對 64 位元的數字做除法,且相比之下多了許多處理不同條件的程式碼
而注意到在實際除法的地方,多了一個變數 bits,在 32 位元的除法中,這裡 P2 的答案是 bit–,也就是判斷除到底了沒,是否該停止了,而這邊和 32 位元的地方不同,在 32 位元中,mask 同時用來 set bit 以及判斷除玩了沒有
這邊的話其實我不太清楚分開成兩個變數跟只用一個變數解決的差異在哪裡,思考後覺得有可能是讓一個變數 "專心" 做好一件事,會比較不容易出錯,或是比較好維護程式碼
jserv
老師的回答,如下:
afcidk
: 感覺這樣做才是正確的,為什麼 32-bit 的版本可以讓 mask>>=1 來替代 bits 的工作呢?
jserv
: 32-bit 版本的實作並不完整,其作用只是 helper function,用來實作 64-bit 版本,實際上也只有後者真的被使用
P3 P4 P5 應該為?
process 64 bit value as long as needed
以及 process 32 bit (or reduced 64 bit) value
,然後看到程式碼的部分,要印出字元,需要將數字正確輸出的話要加 49,也就是 0x31,因此 P3 以及 P5 皆為 0x31jserv++C
首先先將 3823806048287157.0 以二進位表示:01000011 00101011 00101011 01110110 01110010 01100101 01110011 01101010
接著要將這一長串 0 和 1 轉換成 char ,因此將每 8 個 bits 一組形成一個字元,最後呈現的結果便是 C++vresj
,但是因為使用的機器其儲存方式為 little-endian,所以顯示的結果會相反:jserv++C
再來看到題目的部份:
修改程式,允許輸出你的 GitHub 帳號名稱
輸出結果為:raygoah
修改 gen() 函式,透過特定的轉換,讓 m[]
的內容變為你的英文姓氏 (last name)
raygoah:
0 00000000110 1000011000010110111101100111011110010110000101110010
LEI_____:
0 10111110101 1111010111110101111101011111010010010100010101001100
上圖紅色的 1
, 2
, 3
對 MIPS 做了對應的修改,請考慮以下狀況,分別解釋對應的程式碼是否能運作。
1
1: Stuck at 0 left of cut
的修改,sw $s1, 0($s2)
能否運作?在 1
切斷的電路中,關係到寫入 reg 的指令能不能運作
由上圖可以看到,第一列是 R-type 指令,第二列是 lw ,第三列是 sw ,第四列是 beq,所以切斷 1
後,會影響到 R-type 以及 lw ,而 sw 則不會受到影響,因為 sw 不用將值寫入reg,而是相反的將值從 reg 中寫入 memory
因此 Q11 是能運作的,但在 Q12 中,因為有使用到 lw,且 add 為 R-type 指令,所以不能正常運作
2
Q21: 做了 2: Cut here
的修改後,以下程式能否運作?
2
中切掉的電路,會影響到 RS 的 forwarding3
3: Cut here
的修改後,以下程式能否運作? (exit
為某個副程式)在 3
中切斷的電路,會影響到 PC + 4 + (imm*4)
的部份,也就是 I 型指令 beq,而對於 R 型指令:jr ,或是 J 型指令: j,都是沒有影響的
因此在 Q31 中,沒有使用到 beq,使用了 jr 以及 j,所以可以正常執行
而在 Q32 中,因為使用到了 beq 所以沒有辦法順利執行