位操作的详解

#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK
(MCDR2_ADDRESS)
#define BIT_MASK(_bf)(((1U<<(bw##_bf))-1)<<
(bs##_bf)
#define SET_BITS(_dst,_bf,_val)\
((_dst)=((_dst)&~(BIT_MASK(_bf)))I
(((_val)<<(bs##_bf))&(BIT_MASK(_bf))))
SET_BITS(MCDR2,MCDR2_ADDRESS,RegisterNumb
er);

解释1

#define中,标准只定义了###两种操作#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。
这主要是宏定义的问题,宏定义其实就是从最后一个一个替换到所有的define都替换完了。可以理解为重命名。
1.
SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);
MCDR2替换__dst
MCDR2_ADDRESS替换__bf
RegisterNumber替换__val,
SET_BITS(__dst, __bf, __val) 就变成
((MCDR2) = ((MCDR2) & ~(BIT_MASK(MCDR2_ADDRESS))) |(((RegisterNumber) << (bsMCDR2_ADDRESS)) & (BIT_MASK(MCDR2_ADDRESS))))
2.
#define BIT_MASK(__bf) (((1U << (bw ## __bf)) - 1) << (bs ## __bf))
即用(((1U << (bw ## __bf)) - 1) << (bs ## __bf)) 替换BIT_MASK(__bf) 得出
((MCDR2) = ((MCDR2) & ~((((1U << (bwMCDR2_ADDRESS)) - 1) << (bsMCDR2_ADDRESS)) )) |(((RegisterNumber) << (bsMCDR2_ADDRESS)) & ((((1U << (bwMCDR2_ADDRESS)) - 1) << (bsMCDR2_ADDRESS)))))
3.然后使用
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17得出
((MCDR2) = ((MCDR2) & ~((((1U << (4)) - 1) << (17)) )) |(((RegisterNumber) << (17)) & ((((1U << (4)) - 1) << (17)))))
其中((((1U << (4)) - 1) << (17)) )算出二进制数"1111 0000 0000 0000 0000 0",
~((((1U << (4)) - 1) << (17)) )则为"0000 1111 1111 1111 1111 1"

MCDR2 = ((MCDR2) & "0000 1111 1111 1111 1111 1" ) | ((RegisterNumber << 17) & "1111 0000 0000 0000 0000 0").
最后应该是MCDR2=MCDR2的低17位,加上RegisterNumber的低四位最后MCDR2的高4位)

 

解释:2

对于下列宏进行分析:

#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17

#define bmMCDR2_ADDRESSBIT_MASK(MCDR2_ADDRESS)

#define BIT_MASK(_bf)((1U<<(bw##_bf))-1)<<(bs##_bf) 

#define SET_BITS(_dst, _bf, _val)\

         (_dst)= ((_dst)&~(BIT_MASK(_bf))) |(((_val)<<(bs##_bf))&(BIT_MASK(_bf))))

// 使用形式:SET_BITS(MCDR2,MCDR2_ADDRESS, RegisterNumber) 

BIT_MASK:形成bwMCDR2_ADDRESS1位及bsMCDR2_ADDRESS0位的二进位串,即(bwMCDR2_ADDRESS+ bsMCDR2_ADDRESS)位地址的高bwMCDR2_ADDRESS1的掩码。在此例中,bmMCDR2_ADDRESS = 1  1110  0000 0000  0000  0000

工作原理:

(1U<<(bw##_bf))-1:将1左移bwMCDR2_ADDRESS位,并-1,当为4时,即(B1  0000 – 1) = 1111

((1U<<(bw##_bf))-1)<<(bs##_bf):左移bsMCDR2_ADDRESS位,补0,即1  1110 0000  0000  0000  0000

SET_BITS:将_dst地址的低bsMCDR2_ADDRESS(此例为17)_val组成新地址。

_dst=1  0010  1001  1100  0101  0011_val = 0011,则_dst将形成新的地址:

0      0110  1001  1100  0101  0011

工作原理:

_dst)&~(BIT_MASK(_bf)):将掩码取反,与_dst相与,即取低bsMCDR2_ADDRESS位。

(_val)<<(bs##_bf)):将_val左移bsMCDR2_ADDRESS位,_val对应高bwMCDR2_ADDRESS位。

(_dst)&~(BIT_MASK(_bf))) |(((_val)<<(bs##_bf))&(BITMASK(_bf))):即将上两值或运算,取_valbsMCDR2_ADDRESS位,取_valbwMCDR2_ADDRESS位。

作用:SET_BITS可用于更新(bwMCDR2_ADDRESS+ bsMCDR2_ADDRESS)IP地址的网络编号。

源码如下所示:

#include "stdio.h"
#include <stdlib.h>
#include "conio.h"
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)
#define BIT_MASK(_bf) ((1U<<(bw##_bf))-1)<<(bs##_bf) 
#define SET_BITS(_dst, _bf, _val)\
(_dst)= ( ((_dst)&~(BIT_MASK(_bf))) | (((_val)<<(bs##_bf)) & (BIT_MASK(_bf))) )
/*使用形式:SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber)*/
void main()
{
unsigned dst =  0x1ffff; /* 1 1111 1111 1111 1111*/
unsigned regnum = 0x8; /* 1000 */
printf("%x\n", BIT_MASK(MCDR2_ADDRESS)); /*0x1e0000, : 1 1110 0000 0000 0000 0000*/ 
SET_BITS(dst, MCDR2_ADDRESS, regnum); 
printf("%x\n", dst);/*11ffff,: 1 0001 1111 1111 1111 1111*/
}

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值