---
# System prepended metadata

title: 'linux2021: [e361](https://github.com/e361)'

---

# linux2021: [e361](https://github.com/e361)

:::warning
注意細節!
:notes: jserv
:::

## 測驗 $\alpha$-1 舉出linux核心原始程式碼裡頭的案例並說明

>linux kernel裡的 <bitop.h> 定義的幾個circular shift macro,包含
```c   
static inline rol64(__u64 word, unsigned int shift)
static inline ror64(__u64 word, unsigned int shift)
static inline rol32(__u32 word, unsigned int shift)
static inline ror32(__u32 word, unsigned int shift)
static inline rol16(__u16 word, unsigned int shift)
ror16(...), rol8(...), ro8(...)
```

* 這些聚集根據操作的位元數不同,做出往右/往左的 circular shift
共同的操作為: 
word >> (shift & x) | word << (-shift & x) [往左循環位移]
word << (shift & x) | word >> (-shift & x) [往右循環位移]
其中 x 是操作對象的位元數在少1

* shift 為主要位移的數量, 而 -shift 則是反方向需要補上去的
跟 x 做 AND bitwise operation 是為了消除符號
最後 OR bitwise operation 將個別部份連接起來
----------------------------------------------------------------------

## 測驗$\alpha$-2 x86-64具備rotr和rotl指令,上述C程式碼經過編譯器最佳化後,能否運用到這兩個指令？

C code
```c=
int main(void){
    int ch = 0b11010001;
    printf("%d\n", rotr8(ch, 2));
    printf("%d\n", rotl8(ch, 1));
    
    return 0;
}    
```
>使用gcc編譯的結果：
:::spoiler
```shell=1
$gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
$gcc -S -o rotate.s rotate.c

節錄自rotate.s
rotl8:
.LFB2:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, %eax
	movl	%esi, -24(%rbp)
	movb	%al, -20(%rbp)
	movl	$7, -4(%rbp)
	movl	-4(%rbp), %eax
	andl	%eax, -24(%rbp)
	movzbl	-20(%rbp), %edx
	movl	-24(%rbp), %eax
	movl	%eax, %ecx
	sall	%cl, %edx
	movl	%edx, %eax
	movl	%eax, %esi
	movzbl	-20(%rbp), %edx
	movl	-24(%rbp), %eax
	negl	%eax
	andl	-4(%rbp), %eax
	movl	%eax, %ecx
	sarl	%cl, %edx
	movl	%edx, %eax
	orl	%esi, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE2:
	.size	rotl8, .-rotl8
	.type	rotr8, @function
rotr8:
.LFB3:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, %eax
	movl	%esi, -24(%rbp)
	movb	%al, -20(%rbp)
	movl	$7, -4(%rbp)
	movl	-4(%rbp), %eax
	andl	%eax, -24(%rbp)
	movzbl	-20(%rbp), %edx
	movl	-24(%rbp), %eax
	movl	%eax, %ecx
	sarl	%cl, %edx
	movl	%edx, %eax
	movl	%eax, %esi
	movzbl	-20(%rbp), %edx
	movl	-24(%rbp), %eax
	negl	%eax
	andl	-4(%rbp), %eax
	movl	%eax, %ecx
	sall	%cl, %edx
	movl	%edx, %eax
	orl	%esi, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
```
:::
* 根據編譯完的結果,編譯器把需要位移的bytes數做位置偏移,並沒有利用到 ROR,ROL
  而是利用SAR,SAL 算術位移運算來達到等同的效果
----------------------------------------------------------
## 測驗$\beta$-1 說明上述程式碼的原理
```c=
#include <stdint.h>

static inline uintptr_t align_up(uintptr_t sz, size_t alignment)
{
    uintptr_t mask = alignment - 1;
    if ((alignment & mask) == 0) {  /* power of two? */
        return (sz + mask) & ~mask;       
    }
    return (((sz + mask) / alignment) * alignment);
}
```
* 分為兩階段討論,上述程式碼alignment非2^次方時,其實是在做ceiling的動作,
* (sz + mask) / alignment == $\lceil$sz / alignment$\rceil$
* 在alignment是2^次方部份, &~mask指的是說對所需的總對齊數求商,因為mask是alignemnt的餘數,而(sz+mask)指的是說原本有沒有剩餘無法被alignment整除的部份,如果有得補回去

:::warning
power of 2 的翻譯是「2 的冪」
:notes: jserv
:::

---

## 測驗$\beta$-2 Linux kernel 的 align-up alike macro?

* some linux kernel align macro
```c=
#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
#define __ALIGN_MASK(x, mask) (((x) + (mask))&~(mask))
```
* eg. ALIGN(16, 4) ---> 16
* 更具通用性
* 有保護的功能???
