我正在使用Z3
开展一些装配程序分析任务。我被困在模拟x86
操作码bsf
的语义。
bsf operand1 operand2
的语义被定义为在源操作数(操作数1)中搜索最低有效位集(1位)。
其语义可以在C
中模拟为:
if(operand1 == 0) {
ZF = 0;
operand2 = Undefined;
}
else {
ZF = 0;
Temporary = 0;
while(Bit(operand1, Temporary) == 0) {
Temporary = Temporary + 1;
operand2 = Temporary;
}
}
现在,假设每个操作数(例如寄存器)维护symbolic expression
,我试图在Z3Py
中模拟上述语义。我写的代码是这样的(简化):
def aux_bsf(x): # x is operand1
if simplify(x == 0):
raise Exception("undefined in aux_bsf")
else:
n = x.size()
for i in range(n):
b = Extract(i, i, x)
if simplify(b == 1):
return BitVecVal(i, 32)
raise Exception("undefined in bsf")
但是,我发现simplify(x==0)
(例如,x
等于BitVecVal(13, 32) + BitVec("symbol1", 32)
)的评估始终等于True
。换句话说,我总是被困在第一个例外!
我在这里做错了什么..?
=============================================== ===== 好的,所以我认为我需要的是:
def aux_bsf(x):
def aux(x, i):
if i == 31:
return 31
else:
return If(Extract(i, i, x) == 1, i, aux(x, i+1))
return aux(x, 0)
答案 0 :(得分:3)
简化(x == 0)返回表达式,它不返回True / False,其中False = 0.Python会将表达式引用视为非零值,因此将第一个分支。除非' x'是一个位向量常量,简化不会返回一个确定的值。同样的问题是简化(b == 1)。
您可以在operand1和operand2之间编码 relation 等函数,例如:
def aux_bsf(s, x, y):
for k in range(x.size()):
s.Add(Implies(lsb(k, x), y == k)
def lsb(k, x):
first0 = True
if k > 0:
first0 = Extract(x, k-1,0) == 0
return And(Extract(x,k,k) == 1, first0)
对于aux_bsf指定不足的情况,您也可以使用未解释的函数。
例如:
def aux_bsf(x):
bv = x.sort()
bsf_undef = Function('bsf-undef', bv, bv)
result = bsf_undef(x)
for k in reverse(range(bv.size()))
result = If(Extract(x, k, k) == 1), BitVecVal(k, bv), result)
return result
def reverse(xs):
....