You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Z3+X86_64场景下如何实现指向寄存器低半部分的二级指针

解决Z3框架中x86_64子寄存器(al/bl/r8b等)的延迟引用问题

核心思路是延迟计算子寄存器的表达式,不要在初始化阶段直接对z3::bv_const做extract,而是在需要使用子寄存器时,从父寄存器的当前表达式中动态提取对应位段。以下是具体实现方案:

1. 重构寄存器管理类

先实现一个基础的Register类,负责管理完整寄存器(如rax、rbx)的表达式,提供获取和更新表达式的接口:

#include <z3++.h>
#include <string>

class Register {
private:
    z3::context& ctx;
    std::string name;
    int bit_width;
    z3::expr current_expr;

public:
    Register(z3::context& c, const std::string& n, int bw) 
        : ctx(c), name(n), bit_width(bw), 
          current_expr(z3::bv_const(ctx, name.c_str(), bit_width)) {}

    // 更新寄存器的表达式
    void set(const z3::expr& new_expr) {
        current_expr = new_expr;
    }

    // 获取寄存器当前的表达式
    z3::expr get() const {
        return current_expr;
    }

    int get_bit_width() const {
        return bit_width;
    }
};

2. 封装子寄存器的延迟引用

实现SubRegister类,持有父寄存器的引用和位段范围,每次获取子寄存器表达式时,动态从父寄存器的当前值中提取:

class SubRegister {
private:
    Register& parent_reg;
    int start_bit;  // 低位起始位(如al是0)
    int end_bit;    // 高位结束位(如al是7)

public:
    SubRegister(Register& parent, int start, int end) 
        : parent_reg(parent), start_bit(start), end_bit(end) {}

    // 获取子寄存器的当前表达式
    z3::expr get() const {
        return z3::extract(parent_reg.get(), end_bit, start_bit);
    }

    // 给子寄存器赋值(自动更新父寄存器的表达式)
    void set(const z3::expr& sub_expr) {
        z3::expr parent_expr = parent_reg.get();
        int parent_bw = parent_reg.get_bit_width();
        
        // 构造新的父寄存器表达式:保留高位,替换子寄存器对应的位段
        z3::expr new_parent = z3::concat(
            z3::extract(parent_expr, parent_bw - 1, end_bit + 1),
            sub_expr
        );
        parent_reg.set(new_parent);
    }
};

3. 在上下文类中初始化寄存器和子寄存器

在你的x8664_ctx中,将完整寄存器和子寄存器关联起来:

class x8664_ctx {
public:
    z3::context ctx;
    // 64位完整寄存器
    Register rax;
    Register rbx;
    Register r8;
    // 8位子寄存器
    SubRegister al;
    SubRegister bl;
    SubRegister r8b;

    x8664_ctx() 
        : rax(ctx, "rax", 64), rbx(ctx, "rbx", 64), r8(ctx, "r8", 64),
          al(rax, 0, 7), bl(rbx, 0, 7), r8b(r8, 0, 7) {}
};

4. 实际使用示例

后续翻译指令时,无论是读取还是赋值子寄存器,都通过get()和set()方法操作,自动适配父寄存器的表达式更新:

void translate_mov_al_to_bl(x8664_ctx& ctx) {
    // 将al的值赋值给bl:先获取al的当前表达式,再设置给bl
    z3::expr al_val = ctx.al.get();
    ctx.bl.set(al_val);
}

void translate_mov_imm_to_rax(x8664_ctx& ctx) {
    // 给rax赋值立即数,al会自动指向新rax的低8位
    z3::expr imm = z3::bv_val(0x123456789abcdef, 64);
    ctx.rax.set(imm);
    // 此时调用ctx.al.get()会得到0xef的8位BV表达式
}

替代方案:用函数对象简化实现

如果不想额外定义SubRegister类,可以用std::function封装延迟计算逻辑:

class x8664_ctx {
public:
    z3::context ctx;
    Register rax;
    std::function<z3::expr()> al;
    std::function<void(const z3::expr&)> al_set;

    x8664_ctx() : rax(ctx, "rax", 64) {
        // 绑定al的读取逻辑
        al = [this]() {
            return z3::extract(rax.get(), 7, 0);
        };
        // 绑定al的赋值逻辑
        al_set = [this](const z3::expr& val) {
            z3::expr parent = rax.get();
            z3::expr new_rax = z3::concat(
                z3::extract(parent, 63, 8), val
            );
            rax.set(new_rax);
        };
    }
};

内容的提问来源于stack exchange,提问作者Leo Galante

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:35:08