Uni*_*orn 18 c bit-manipulation
我想在32/64位数据字段中替换位/位(大于1)而不影响其他位.例如:
我有一个64位寄存器,其中第5位和第6位可以取值0,1,2,3.
5:6
0 0
0 1
1 0
1 1
Run Code Online (Sandbox Code Playgroud)
现在,当我读取寄存器时,我得到值0x146(0001 0 10 0 0110).现在我想将第5位和第6位的值更改为01.(现在它是10,十进制是2,我想要在没有其他位受到影响的情况下将其替换为1 e 01)并仅在修改了位5和6的情况下写回寄存器(因此在更改后变为126)
我试过这样做
reg_data=0x146
reg_data |= 1 << shift (shift in this case is 5)
Run Code Online (Sandbox Code Playgroud)
如果我在位5和6处执行该值将变为11(0x3)而不是01(0x1),这是我想要的.
设置一点是可以的,但不止一点,我发现它有点困难.
任何建议都非常感谢.
vy3*_*y32 26
你为什么不使用位掩码?有点像:
new_value = 0, 1, 2 or 3 // (this is the value you will set in)
bit_mask = (3<<5) // (mask of the bits you want to set)
reg_data = (reg_data & (~bit_mask)) | (new_value<<5)
Run Code Online (Sandbox Code Playgroud)
这保留了旧位和OR的新位.
Ama*_*9MF 10
reg_data &= ~( (1 << shift1) | (1 << shift2) );
reg_data |= ( (1 << shift1) | (1 << shift2) );
Run Code Online (Sandbox Code Playgroud)
第一行清除(shift1,shift2)的两位,第二行设置它们.
这是一个通用的过程,它作用于一个长数组,考虑到它是一个长位域并分别寻址每个位的位置
#define set_bit(arr,x) ((arr[(x)>>3]) |= (0x01 << ((x) & 0x07)))
#define clear_bit(arr,x) (arr[(x)>>3] &= ~(0x01 << ((x) & 0x07)))
#define get_bit(arr,x) (((arr[(x)>>3]) & (0x01 << ((x) & 0x07))) != 0)
Run Code Online (Sandbox Code Playgroud)
简单地,索引使用索引的低3 btis来识别char数组的每个位置内的8个不同的位位置,并且上部的剩余位地址用于表示由所表示的位的阵列位置x
.希望这可以帮助.
编辑1: 要设置一个位,您需要将目标字与该特定位位置为1的另一个字或与目标的所有其他字相对应.其他位置的所有0都确保目标中的现有1是在OR期间,并且特定位置中的1确保目标在该位置获得1.如果我们有掩码= 0x02 = 00000010(1字节),那么我们可以对任何单词进行OR运算以设置该位pos
target = 1 0 1 1 0 1 0 0
OR + + + + + + + +
mask 0 0 0 0 0 0 1 0
---------------
answer 1 0 1 1 0 1 1 0
Run Code Online (Sandbox Code Playgroud)
要清除一点,您需要将目标字与该特定位位置为0的另一个字进行AND运算并且总共为1.在所有其他位位置中的所有1确保在AND期间,目标保持其在那些位置中的0和1,并且要清除的位位置中的0也将在目标字中设置该位位置0.如果我们有相同的掩码= 0x02,那么我们可以准备这个掩码来清除〜掩码
mask = 0 0 0 0 0 0 1 0
~mask = 1 1 1 1 1 1 0 1
AND . . . . . . . .
target 1 0 1 1 0 1 1 0
---------------
answer 1 0 1 1 0 1 0 0
Run Code Online (Sandbox Code Playgroud)