找回密码
 加入
搜索
查看: 5121|回复: 4

[原创] AU3中BitAnd与Win32汇编中的&按位进行与操作的本质思考

[复制链接]
发表于 2015-1-24 18:58:26 | 显示全部楼层 |阅读模式
本帖最后由 李岸 于 2015-1-24 19:00 编辑

心越静,思考的越透彻。不要着急,宇宙有求必应!我可能是最笨的才会写出来进行思考,写出来至少自己在碰到这些本质上的问题不会再度卡壳。本着"没有交流的思考不是完整的思考"的原则,我将这篇文章发出来,如果能引发出你的共鸣,那么请像我一样。期待与你的交流!

在AU3论坛中找到了篇帖子为这个问题作为参考:
白痴问个比较白痴的问题:在实际中我到底怎么样才会用到BitOR,BitAND,BitXOR?

     AU3中的BitAnd、BitOr、BitNot、BitXor、And、Or、Not;分别对应汇编中的And、Or、Not、Xor、&&、||、!;两者中的前四个指令,多用于两个操作数之间的逻辑操作,并且保存结果到变量或者源操作数中。两者中的后三个指令,多用于表达式中的逻辑操作。&&、||都会被翻译成与自身相或,来判断是否等于0.所以结果不会变只会影响相应的标志位。如ZF,程序也正是用ZF标志位来判断是否转跳。

总是觉得逻辑上过得去,但是总觉得缺少了点背景资料(为什么会有这个东西存在,它的历史是什么呢,背后的思想又是什么呢?);既然这类操作多用于组合标志位,那么不妨以此来作为思考的切入点。
一个Flg初始化为0000000000000(32个0),那么每一个都是一个"Flg",0和1表示(开或者关)。(这句话的意思是让你把思维切换到二进制来思考这个问题)

纵观整个AU3帮助文档,所有涉及组合标志位的函数如:FileOpen,WinGetState等函数(有兴趣的可以查看一下windowsconst.au3)的组合标志位都是1、2、4、8、16...发现了什么?它们与二进制每位的权值一一对应。

引申出另一个问题:为什么没有用3、5、7、9..这些常数作为组合标志位的值呢?对照一下上下的区别是:没错,上文是除了1都是偶数,下文是奇数。所以这个问题的答案可以说:用上文的所有偶数构造出最接近下文的偶数,然后+1就可以了。所以一个二进制的Flg组合标志位,十进制表示为奇数,那么这个二进制位的第0位必然是1.

从另一个角度讲,这样的组合标志位原则有利于逻辑运算;比如9 and 8,二进制位分别为1001与1000,除了8所代表的二进制第三个标志位其他位全部为0。根据与运算的规则,结果肯定不为零所以成真。

又例如一个实际的例子:

1 = 窗口存在
2 = 窗口可见
4 = 窗口可用(未被禁用)
8 = 窗口为激活状态
16 = 窗口为最小化状态
32 = 窗口为最大化状态
你想要判断这个窗口是不是最小化,就用:
$win_state=WinGetState("***","****")
If BitAND($win_state,8)==8 Then ***********

如果窗口的状态为1、2、4,那么二进制为0001,0010,0100.可见8d所代表的第三位都是0,所以If BitAND($win_state,8)==8肯定是不成立的。
如果为16和32呢?那么二进制为10000,100000。可见8d所代表的第三为都是0,所以If BitAND($win_state,8)==8肯定是不成立的。
只有16  <  窗口状态  >  8 的情况下,If BitAND($win_state,8)==8 Then ***********才会成立。因为这时候无论要表示9~15中的任意一个数都要用到8(二进制的第三位为1),但大于15就进位了。

从这个意义上讲,窗口的状态总是向下包含的;可以看到8(窗口为激活状态),绝对包含,1、2、4这些属性位。因为“窗口为激活状态”,那么不可能不存在这些状态“窗口存在”, “ 窗口可见 ”,“窗口可用(未被禁用) ”,但二进制表示为8的时候,又有了一个新的意义那就是“窗口为激活状态”。同理没有“窗口最大化”的概念,哪里来的“窗口最小化”这个概念呢?没有“窗口最小化”这个概念,哪里来的“窗口为激活状态”这个概念呢?无论从数学的意义上,还是从函数说明上来理解这个概念都是行得通的。

继续往下思考,可以发现有些标志位的组合都有类似这样的说明“此标志必须与XX标志共同使用”或者“此标志不能与XX标志共同使用”;例如OPENFILENAME这个结构中,OFN_FILEMUSTEXIST和OFN_PATHMUSTEXIST必须共同使用,那么这两个常量的取值是多少呢?分别是1000h和800h;


总结:
          先把视角切换到二进制位的32位Flg,帮助文档上缩写的十进制1、2、4、8,说白了只是标志位组合中的相应位是否为1而已。(为了适应人类的长了十根手指而产生的思考局限)
          再说的透彻点,这个组合标志位所代表的十进制,或者十六进制的数值是没有意义的,从二进制的角度来讲它也只代表32个按钮的开关状态而已。
          强制开启开关可以使用or 开关组状态1和索引(我觉得这样理解更透彻),如果要检测一个开关是否被开启可以使用and 开关组 索引和状态1。
          如果把组合标志位想像成开关,1代表开,0代表关。将BitAnd(32个开关,000000000001000)1代表我要开其中的一个开关。如果这个开关之前是关着的,那么 1 and 0 = 0 。
          如果这个开关之前是开着的,那么1 and 1 = 1。可见and指令是返回之前开关的状态...
          按照这个思路的话,如果我要关一个开关,这个开关之前是关着的,0 and 0 = 0 反之 0 and 1 == 0,“and指令是返回之前开关的状态”在这里又不适用了。
 楼主| 发表于 2015-1-24 19:02:02 | 显示全部楼层
欢迎拍砖~
发表于 2015-1-25 11:35:04 | 显示全部楼层
不錯,慢慢消化.
发表于 2018-2-24 19:21:35 | 显示全部楼层
感谢楼主分享,感觉还不错
发表于 2018-9-22 08:29:17 | 显示全部楼层
正好,慢慢来,学习
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-21 21:55 , Processed in 0.072859 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表