x86_64 Linux汇编中logical AND的实现方法
x86_64 汇编逻辑与实现方案
逻辑运算的核心前提是先将任意输入值归一化为严格的0(逻辑假)或1(逻辑真),再做运算。你之前遇到按位与和逻辑非行为不对齐的问题,根源是直接对未归一化的原始整数值做运算,且你当前用x < 1实现的逻辑非本身不符合通用逻辑语义——有符号比较下所有负数都会判定为小于1,会把非0的负数错判为逻辑假。
方案1:标准语义实现(对齐C/绝大多数通用逻辑规则:非0即真,0即假)
首先修正逻辑非的实现,替换掉有问题的x < 1写法:
; 输入遵循x86_64 System V调用约定:rdi = 第一个参数x ; 输出al = !x logical_not: test rdi, rdi ; 按位与x自身,仅当x全0时置ZF=1,不修改原x值 setz al ; ZF=1时al=1(x为0,!x为真),否则al=0(x非0,!x为假) ret
该实现对正数、负数一视同仁,只要值非0就判定为逻辑真,符合通用编程逻辑预期。
对应的逻辑与有两种成熟实现:
- 分支实现:逻辑直白,代码量小
; 输入:rdi = a, rsi = b ; 输出al = a && b logical_and: test rdi, rdi jz .ret_false ; a为0直接返回假 test rsi, rsi setnz al ; b非0则返回1,否则返回0 ret .ret_false: xor eax, eax ret
- 无分支实现:无跳转开销,性能更优
logical_and: xor eax, eax test rdi, rdi setnz dl ; 归一化a:非0则dl=1,否则dl=0 test rsi, rsi setnz al ; 归一化b:非0则al=1,否则al=0 and al, dl ; 对两个0/1值做按位与,结果等价于逻辑与 ret
这里的
and指令操作的是已经归一化到0/1的值,不会出现负数判定异常的问题。
方案2:对齐你现有逻辑非的特殊语义
如果你有特殊业务需求,必须保持“值大于等于1为逻辑真,值小于1(含0、所有负数)为逻辑假”的判定规则,和你当前的x < 1逻辑非实现完全对齐,可使用以下无分支逻辑与实现:
; 输入:rdi = a, rsi = b ; 输出al = a && b,判定规则对齐x<1的逻辑非 logical_and_aligned: xor eax, eax cmp rdi, 1 setge dl ; a >=1则dl=1,否则dl=0 cmp rsi, 1 setge al ; b >=1则al=1,否则al=0 and al, dl ; 两个归一化值按位与得到结果 ret
关键说明
不要直接对原始输入值使用二进制and指令做逻辑运算——原始整数可能是负数、大于1的正数,直接按位与的结果不会自动归一化到0/1区间,必然出现逻辑判定错误。所有逻辑运算都要先把输入按你定义的规则转换成0或1,再做按位运算即可得到正确结果。
内容的提问来源于stack exchange,提问作者user17411100
相关产品推荐
相关产品推荐

