在Z3中模拟x86操作码'bsf'的语义

时间:2016-09-17 19:28:45

标签: z3 z3py

我正在使用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)

1 个答案:

答案 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):
    ....