linyunwen
raygoah
contributed by <LinYunWen
, raygoah
>
將 Func32
改寫為以下功能等價的程式碼:
如果 x 不為 0 就將自己向右平移一位 (除以二) ,然後再呼叫自己一次,否則回傳 32
改用 GDB 搭配 script 來實作遞迴程式的追蹤功能,避免用到 printf(),參見: http://kfunk.org/2014/08/29/scripting-gdb-to-execute-commands-at-particular-breakpoints/
jserv
延伸題目:
在 x86_64/Aarch32/Aarch64 ISA 中找出對應於 Func32 的指令,隨後在 GitHub 專案中找到 3 個應用案例並解說;
回顧 Week1 到 Week5 的教材和作業,提出可用對應於 Func32 (或下方 Func64) 的指令加速的案例;
此函式是用來進行 32 位元的除法, #6 中,先計算出 divisor 和 dividend 開頭皆為 0 的數字長度差距,差距為 mask
#8 中,把除數向左移位 mask 位,為的就是讓除數對齊被除數,這樣才能達成我們平常在長除法時,從最高有效位開始做除法的目的,而在二進位中,因為只有 1 跟 0,所以除法是用減的,不需要計算相差幾倍的問題
參考 What does (1U << X) do?,才知道原來第九行中的 1U 是這個意思 (unsigned value 1) ,代表把第 n 個 bit 設為 1,接著同樣移位 mask 位,讓 1 能夠對齊被除數的最高有效位
接著便是實際除法的部份,do while 中,被除數大於除數時,就讓被除數減掉除數後更新成新的被除數,接著第 13 行所做的便是除法中差幾倍的概念,只是因為數字都是 0 和 1,所以針對 mask 中 bit 為 1 的那一位數用 OR 的方式 set 在商數中,這樣有進行被除數和除數的相減時,對應的 bit 就會被設為 1,其餘位元不變
而藉由上面除法的過程,可以知道 mask 因為要對齊到每次正在運算的那個位元,必須要向右移位一次,才能在每次要 set 商數時,能夠 set 到正確的 bit,所以得到 P1 必須填入 mask >> 1
包含 P2 的函式為 udiv64
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 版本,實際上也只有後者真的被使用
process 64 bit value as long as needed
以及 process 32 bit (or reduced 64 bit) value
,然後看到程式碼的部分,要印出字元,需要將數字在 ASCII 正確輸出的話要加 49,也就是 0x31,因此 P3 以及 P5 皆為 0x31
- 除以 10 的地方改為除以 16
- 輸出 10 以上要以 ABCDEF 代替,在 ASCII 中相當於加 0x37
TingL7
- Java class file 的前 4 byte 為 magic number
CAFEBABE
主要做用在於辨認 file 是否是能被接受的 class file- 參考c語言里malloc的最優實現方式是什麼?,
malloc()
中也會設置 magic number,主要是因為避免 free 到沒有 malloc 的位址,藉由 magic number 設置與否就可以檢查
TingL7