嵌套商店运营的有效方式

时间:2017-05-26 15:52:57

标签: z3

Most efficient way to represent memory buffers in Z3中,关于如何使嵌套存储操作更有效的问题得到回答,可以用({1}}中的选择替换(嵌套)存储操作。但是,我需要存储操作,因为先前的约束必须用新约束替换。

例如:以下约束模拟以下汇编程序:

(assert (= (select A i1) v1))

我想证明rbx和rcx是相等的,我断言(= RBX!2 RCX!2)并且期望模型可以满足。这非常有效。我断言(不是(= RBX!2 RCX!2))并且期望模型不能满足。当我将以下约束提供给Z3时(例如here),它给出了一个近乎即时的答案:UNSAT。但是,如果我在C#程序中证明了同样的问题(见下文),它就无法推断出UNSAT(在合理的时间内)。

问题:我可以尝试使C#程序与SMT2.0程序一样快?

mov qword ptr [rax], rbx
mov rcx, qword ptr [rax]

C#代码:

(declare-fun RAX!0 () (_ BitVec 64))
(declare-fun RAX!1 () (_ BitVec 64))
(declare-fun RAX!2 () (_ BitVec 64))

(declare-fun RBX!0 () (_ BitVec 64))
(declare-fun RBX!1 () (_ BitVec 64))
(declare-fun RBX!2 () (_ BitVec 64))

(declare-fun RCX!0 () (_ BitVec 64))
(declare-fun RCX!1 () (_ BitVec 64))
(declare-fun RCX!2 () (_ BitVec 64))

(declare-fun MEM!0 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!1 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!2 () (Array (_ BitVec 64) (_ BitVec 8)))

(assert (= RAX!1 RAX!0))
(assert (= RBX!1 RBX!0))
(assert (= RCX!1 RCX!0))
(assert (let ((a!1 (store (store (store MEM!0 RAX!0 ((_ extract 7 0) RBX!0))
                         (bvadd #x0000000000000001 RAX!0)
                         ((_ extract 15 8) RBX!0))
                  (bvadd #x0000000000000002 RAX!0)
                  ((_ extract 23 16) RBX!0))))
(let ((a!2 (store (store (store a!1
                                (bvadd #x0000000000000003 RAX!0)
                                ((_ extract 31 24) RBX!0))
                         (bvadd #x0000000000000004 RAX!0)
                         ((_ extract 39 32) RBX!0))
                  (bvadd #x0000000000000005 RAX!0)
                  ((_ extract 47 40) RBX!0))))
  (= MEM!1
     (store (store a!2
                   (bvadd #x0000000000000006 RAX!0)
                   ((_ extract 55 48) RBX!0))
            (bvadd #x0000000000000007 RAX!0)
            ((_ extract 63 56) RBX!0))))))
(assert (= RAX!2 RAX!1))
(assert (= RBX!2 RBX!1))
(assert (= RCX!2
   (concat (select MEM!1 (bvadd #x0000000000000007 RAX!1))
           (select MEM!1 (bvadd #x0000000000000006 RAX!1))
           (select MEM!1 (bvadd #x0000000000000005 RAX!1))
           (select MEM!1 (bvadd #x0000000000000004 RAX!1))
           (select MEM!1 (bvadd #x0000000000000003 RAX!1))
           (select MEM!1 (bvadd #x0000000000000002 RAX!1))
           (select MEM!1 (bvadd #x0000000000000001 RAX!1))
           (select MEM!1 RAX!1))))
(assert (= MEM!2 MEM!1))
(assert (not (= RBX!2 RCX!2)))

1 个答案:

答案 0 :(得分:1)

遗憾的是,我无法运行C#程序来使用它。但是我注意到你打电话给Simplify

solver.Assert(ctx.MkEq(mem1, memX7).Simplify() as BoolExpr);

我很好奇为什么你需要这个电话?也许那是罪魁祸首?

要尝试的另一件事是使用未解释的函数来表示内存,而不是Array。 UF通常更容易处理,它们在我的个人经历中提供了大致相同的抽象。

查看C#界面生成​​的SMT-Lib可能是个好主意,看看翻译是否与你想象的有很大不同。我想你可以使用以下函数来做到这一点:https://github.com/Z3Prover/z3/blob/master/src/api/dotnet/AST.cs#L195