bit_operator

最近写mit的JOS操作系统看到一些有意思的位运算的使用方法,在这里分享/记录一下。

一 使用&位可以快速清除低位

页表的entry格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
31                                  12 11                      0
+--------------------------------------+-------+---+-+-+---+-+-+-+
| | | | | | |U|R| |
| PAGE FRAME ADDRESS 31..12 | AVAIL |0 0|D|A|0 0|/|/|P|
| | | | | | |S|W| |
+--------------------------------------+-------+---+-+-+---+-+-+-+

P - PRESENT
R/W - READ/WRITE
U/S - USER/SUPERVISOR
D - DIRTY
AVAIL - AVAILABLE FOR SYSTEMS PROGRAMMER USE

NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.

现在需要从页表entry中获得页的物理地址。我们知道因为页的物理地址也是关于页大小对齐的,所以在页表entry存储的只是页对应的物理地址的高20bits。只要将entry的低12bits置零就可以得到对应的物理地址。在JOS中是这样做的

1
2
3
#define PADDR(pte) pte & ~0xfff
// 0xfff是12bits都是1的数字,取~后使得高20bits都为1,低12bits都为0。再与pte取&即可
// 将低12bits置零,其余bit保持不变

二 使用|位运算来结合flags:

还是在一中页表的例子,在设置页表的时候要设置12bits的flags来控制页是否present/读写权限/用户权限等等。

JOS中做法大致如下

1
2
3
4
5
6
7
8
define PTE_P 0x1
define PTE_W 0x2
//
typedef uint32_t pte_t
// 声明一个entry
pte_t pte = 0x8000ffff; // 随便写的一个
// 设置flag P = 1 R/W = 1
pte = PADDR(pte) | PTE_P | PTE_W ; // pte的最后两个bit就会变成11

使用或位运算可以用来清晰方便的combine flags。

三 快速置零

1
2
3
4
// 快速将a的值清零
a ^= a;
a &= 0x0;
// 第一种做法在写汇编的时候更加常见

四 待补充…