# 2019q3 Homework1 (review) contributed by < `Shengyuu` > ## 題組 1 考慮以下 C 程式的 align4 巨集的作用是,針對 4-byte alignment,找到給定地址的 round up alignment address。 ```cpp #include <stdio.h> #define align4(x) (((x) + K) & (-4)) int main(void) { int p = 0x1997; printf("align4(p) is %08x\n", align4(p)); return 0; } ``` 預期程式輸出 `align4(p) is 00001998` ### 解題思路 題目中 4-byte-alignment 的意思是要將給定的地址做 align ,讓地址永遠維持 4 的倍數,要維持 4 的倍數有兩種可能,分別是 `round up` 以及 `round down` ,例如:將題目中的 `p = 0x1997` align 成 `0x1998` 及為 `round up` ,若 align 成 `0x1994` 則為 `round down`。理解 align 的用意後再來看看程式碼: ```cpp #define align4(x) (((x) + K) & (-4)) ``` align4 這個巨集會將給定的地址 `x` 加上常數 `K` 之後和 `-4` 做 bit-and 的動作, `-4` 用 2'compliment 的二進位形式表示的話,最後面的 2 bits 值為 `00` 其餘皆為 `1` ,由此可知給定地址和 `-4` 做 bit-and 的結果一定會是 `4` 的倍數,也就是做 align4 的動作,既然 align 的動作做完了,合理推測變數 `K` 是為了 `round up` , 而對 align4 做 round up , K 的值就必須為 3 ### 延伸問題 在 Linux 核心原始程式碼找出類似的 alignment 巨集並解釋其作用 在 [linux/arch/riscv/include/asm/page.h](https://github.com/torvalds/linux/blob/cef7298262e9af841fb70d8673af45caf55300a1/arch/riscv/include/asm/page.h) 中有 ALIGN_UP 和 ALIGN_DOWN 兩個 macro ```cpp /* align addr on a size boundary - adjust address up/down if needed */ #define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1))) #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) ``` 第一個巨集 `_ALIGN_UP(addr, size)` 是"題目一"中 align4 的擴充版本,這裡可以指定要 align 的大小是多少,比較不一樣的地方是"題目一"是和 `-size` 做 bit-and ,而 _ALIGN_UP 是和 `~((size)-1)` 做 bit-and ,至換成二進位編碼可以發現兩者是等效的。第二個 _ALIGN_DOWN 巨集則是直接將 `addr` 和 `~((size))-1)` 做 bit-and ,就可以達到 align 的效果 ## 測驗 2 考慮以下 C 程式可取得以 `sizeof(int)` 為 alignment 基礎的整數空間,也就是說,當 `sizeof(int)` 為 `4` 的時候: * 給定 `char arr[13];`,`INT_SIZE_OF(arr)` 要得到 `16`; * 給定 `short int s;`,`INT_SIZE_OF(s)` 要得到 `4` ```cpp #include <stdint.h> #define INT_SIZE_OF(n) \ ((sizeof(n) + sizeof(int) + X) & ~(sizeof(int) + Y)) ``` ### 解題思路 仔細看程式碼後會發現,"測驗 2" 和 "測驗 1" 幾乎是一模一樣的概念, 都是對傳近來的參數 `n` 做 align4 的動作,再根據給的範例可以發現這題和 "測驗 1" 一樣都是做 round up 的 alignment ,因此可推論出 X 的值為 `-1` 。唯一要注意的地方就是 `&` 後面的部份和第一題有些許的差別,這裡是用 `~` 符號而不是像 "測驗 1" 用 `-` 符號,又我們知道 `-sizeof(int) = ~(sizeof(int) - 1)` ,可推論出 Y 的值同為 `-1` ###### tags: `進階電腦系統理論與實作 (Fall 2019)`