Files
Deshab-OS/CODE/UTSM/pe/x86emu32.c
T

990 lines
43 KiB
C
Raw Normal View History

2026-07-28 14:35:14 +08:00
/* x86emu32.c — x86-32 指令解释器(PE32 执行引擎)。
*
* 寄存器级解释执行 32位 PE 代码。覆盖 mingw-w64 -O0/-O1 控制台程序常用指令:
* ALU(ADD/OR/ADC/SBB/AND/SUB/XOR/CMP)、MOV(全形式)、PUSH/POP、
* INC/DEC/NEG/NOT、MUL/IMUL/DIV/IDIV、移位/旋转、LEA、XCHG、MOVSX/MOVZX、
* JMP/Jcc/CALL/RET/LOOP、字符串指令(+REP)、ENTER/LEAVE、INT(shim 调度)。
*
* 遇不支持指令时设置 error 并停止。
*/
#include "x86emu32.h"
#include "pe_shim.h"
#include <utsm/log.h>
#include <utsm/panic.h>
2026-07-28 14:35:14 +08:00
#include <utsm/types.h>
/* ===== 内存访问(带边界检查) ===== */
u8 x86emu32_read8(x86emu_state *emu, u32 addr) {
if (addr >= emu->mem_size) { emu->error = 1; emu->error_msg = "read8 OOB"; return 0; }
return emu->mem[addr];
}
u16 x86emu32_read16(x86emu_state *emu, u32 addr) {
if (addr + 1 >= emu->mem_size) { emu->error = 1; emu->error_msg = "read16 OOB"; return 0; }
return (u16)emu->mem[addr] | ((u16)emu->mem[addr+1] << 8);
}
u32 x86emu32_read32(x86emu_state *emu, u32 addr) {
if (addr + 3 >= emu->mem_size) { emu->error = 1; emu->error_msg = "read32 OOB"; return 0; }
return (u32)emu->mem[addr] | ((u32)emu->mem[addr+1] << 8) |
((u32)emu->mem[addr+2] << 16) | ((u32)emu->mem[addr+3] << 24);
}
void x86emu32_write8(x86emu_state *emu, u32 addr, u8 val) {
if (addr >= emu->mem_size) { emu->error = 1; emu->error_msg = "write8 OOB"; return; }
emu->mem[addr] = val;
}
void x86emu32_write16(x86emu_state *emu, u32 addr, u16 val) {
if (addr + 1 >= emu->mem_size) { emu->error = 1; emu->error_msg = "write16 OOB"; return; }
emu->mem[addr] = (u8)(val & 0xFF);
emu->mem[addr+1] = (u8)((val >> 8) & 0xFF);
}
void x86emu32_write32(x86emu_state *emu, u32 addr, u32 val) {
if (addr + 3 >= emu->mem_size) { emu->error = 1; emu->error_msg = "write32 OOB"; return; }
emu->mem[addr] = (u8)(val & 0xFF);
emu->mem[addr+1] = (u8)((val >> 8) & 0xFF);
emu->mem[addr+2] = (u8)((val >> 16) & 0xFF);
emu->mem[addr+3] = (u8)((val >> 24) & 0xFF);
}
/* ===== 栈操作 ===== */
void x86emu32_push32(x86emu_state *emu, u32 val) {
emu->regs[X86_ESP] -= 4;
x86emu32_write32(emu, emu->regs[X86_ESP], val);
}
u32 x86emu32_pop32(x86emu_state *emu) {
u32 val = x86emu32_read32(emu, emu->regs[X86_ESP]);
emu->regs[X86_ESP] += 4;
return val;
}
u64 x86emu32_read_arg(x86emu_state *emu, int esp_offset) {
return x86emu32_read32(emu, emu->regs[X86_ESP] + (u32)esp_offset * 4);
}
/* ===== 寄存器访问 ===== */
/* 32位寄存器名:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI(对应 0-7) */
/* 8位寄存器映射:AL,CL,DL,BL,AH,CH,DH,BH(0-3 = 低8位, 4-7 = 高8位) */
static u8 get_reg8(x86emu_state *emu, int idx) {
if (idx < 4) return (u8)(emu->regs[idx] & 0xFF);
return (u8)((emu->regs[idx - 4] >> 8) & 0xFF);
}
static void set_reg8(x86emu_state *emu, int idx, u8 val) {
if (idx < 4) {
emu->regs[idx] = (emu->regs[idx] & 0xFFFFFF00) | val;
} else {
emu->regs[idx - 4] = (emu->regs[idx - 4] & 0xFFFF00FF) | ((u32)val << 8);
}
}
static u16 get_reg16(x86emu_state *emu, int idx) {
return (u16)(emu->regs[idx] & 0xFFFF);
}
static void set_reg16(x86emu_state *emu, int idx, u16 val) {
emu->regs[idx] = (emu->regs[idx] & 0xFFFF0000) | val;
}
static u32 get_reg32(x86emu_state *emu, int idx) { return emu->regs[idx]; }
static void set_reg32(x86emu_state *emu, int idx, u32 val) { emu->regs[idx] = val; }
/* ===== EFLAGS 辅助 ===== */
static void set_flag(x86emu_state *emu, u32 mask, int on) {
if (on) emu->eflags |= mask; else emu->eflags &= ~mask;
}
static int get_flag(x86emu_state *emu, u32 mask) { return (emu->eflags & mask) ? 1 : 0; }
static u8 parity8(u8 v) {
v ^= v >> 4; v ^= v >> 2; v ^= v >> 1;
return (v & 1) == 0;
}
static void set_zf_sf_pf(x86emu_state *emu, u32 result, int size) {
u32 mask = (size == 1) ? 0xFF : (size == 2) ? 0xFFFF : 0xFFFFFFFF;
result &= mask;
set_flag(emu, X86_ZF, result == 0);
if (size == 1) set_flag(emu, X86_SF, (result & 0x80) != 0);
else if (size == 2) set_flag(emu, X86_SF, (result & 0x8000) != 0);
else set_flag(emu, X86_SF, (result & 0x80000000) != 0);
set_flag(emu, X86_PF, parity8((u8)result));
}
static void set_cf_add(x86emu_state *emu, u32 a, u32 b, int size) {
u32 mask = (size == 1) ? 0xFF : (size == 2) ? 0xFFFF : 0xFFFFFFFF;
set_flag(emu, X86_CF, ((u64)(a & mask) + (u64)(b & mask)) > mask);
}
static void set_cf_sub(x86emu_state *emu, u32 a, u32 b, int size) {
u32 mask = (size == 1) ? 0xFF : (size == 2) ? 0xFFFF : 0xFFFFFFFF;
set_flag(emu, X86_CF, (a & mask) < (b & mask));
}
static void set_of_add(x86emu_state *emu, u32 a, u32 b, u32 r, int size) {
u32 sign = (size == 1) ? 0x80 : (size == 2) ? 0x8000 : 0x80000000;
set_flag(emu, X86_OF, (~(a ^ b) & (a ^ r) & sign) != 0);
}
static void set_of_sub(x86emu_state *emu, u32 a, u32 b, u32 r, int size) {
u32 sign = (size == 1) ? 0x80 : (size == 2) ? 0x8000 : 0x80000000;
set_flag(emu, X86_OF, ((a ^ b) & (a ^ r) & sign) != 0);
}
/* ===== 指令取 ===== */
static u8 fetch8(x86emu_state *emu) {
u8 v = x86emu32_read8(emu, emu->eip);
emu->eip++;
return v;
}
static u16 fetch16(x86emu_state *emu) {
u16 v = x86emu32_read16(emu, emu->eip);
emu->eip += 2;
return v;
}
static u32 fetch32(x86emu_state *emu) {
u32 v = x86emu32_read32(emu, emu->eip);
emu->eip += 4;
return v;
}
/* ===== ModR/M 解码 ===== */
typedef struct {
int mod;
int reg; /* reg 字段(也可作 opcode 扩展) */
int rm; /* rm 字段 */
u32 ea; /* 有效地址(若 mod != 3) */
int has_ea; /* 是否有内存操作数 */
} modrm_dec;
static modrm_dec decode_modrm(x86emu_state *emu) {
modrm_dec m;
u8 b = fetch8(emu);
m.mod = (b >> 6) & 3;
m.reg = (b >> 3) & 7;
m.rm = b & 7;
m.has_ea = 0;
m.ea = 0;
if (m.mod == 3) return m; /* 寄存器直接寻址 */
m.has_ea = 1;
u32 base = 0;
int has_sib = (m.rm == 4);
if (has_sib) {
u8 sib = fetch8(emu);
int scale = 1 << ((sib >> 6) & 3);
int index = (sib >> 3) & 7;
int base_reg = sib & 7;
base = emu->regs[base_reg];
if (index != 4) { /* ESP 不作 index */
base += emu->regs[index] * (u32)scale;
}
} else {
base = emu->regs[m.rm];
}
/* disp */
if (m.mod == 0) {
if (!has_sib && m.rm == 5) {
/* disp32 直接地址 */
base = fetch32(emu);
}
} else if (m.mod == 1) {
base += (u32)(i32)(i8)fetch8(emu); /* disp8 符号扩展 */
} else { /* mod == 2 */
base += fetch32(emu);
}
m.ea = base;
return m;
}
/* 读/写 modr/m 操作数 */
static u32 read_rm32(x86emu_state *emu, const modrm_dec *m) {
if (m->mod == 3) return get_reg32(emu, m->rm);
return x86emu32_read32(emu, m->ea);
}
static void write_rm32(x86emu_state *emu, const modrm_dec *m, u32 val) {
if (m->mod == 3) set_reg32(emu, m->rm, val);
else x86emu32_write32(emu, m->ea, val);
}
static u8 read_rm8(x86emu_state *emu, const modrm_dec *m) {
if (m->mod == 3) return get_reg8(emu, m->rm);
return x86emu32_read8(emu, m->ea);
}
static void write_rm8(x86emu_state *emu, const modrm_dec *m, u8 val) {
if (m->mod == 3) set_reg8(emu, m->rm, val);
else x86emu32_write8(emu, m->ea, val);
}
static u16 read_rm16(x86emu_state *emu, const modrm_dec *m) {
if (m->mod == 3) return get_reg16(emu, m->rm);
return x86emu32_read16(emu, m->ea);
}
static void write_rm16(x86emu_state *emu, const modrm_dec *m, u16 val) {
if (m->mod == 3) set_reg16(emu, m->rm, val);
else x86emu32_write16(emu, m->ea, val);
}
/* ===== ALU 操作(按 op 索引:0=ADD 1=OR 2=ADC 3=SBB 4=AND 5=SUB 6=XOR 7=CMP) ===== */
static u32 alu_op(x86emu_state *emu, int op, u32 a, u32 b, int size) {
u32 r = 0;
u32 mask = (size == 1) ? 0xFF : (size == 2) ? 0xFFFF : 0xFFFFFFFF;
a &= mask; b &= mask;
switch (op) {
case 0: r = a + b; set_cf_add(emu, a, b, size); set_of_add(emu, a, b, r, size); set_zf_sf_pf(emu, r, size); break;
case 1: r = a | b; set_flag(emu, X86_CF, 0); set_flag(emu, X86_OF, 0); set_zf_sf_pf(emu, r, size); break;
case 2: { int cf = get_flag(emu, X86_CF); r = a + b + cf; set_cf_add(emu, a + cf, b, size); set_of_add(emu, a, b, r, size); set_zf_sf_pf(emu, r, size); break; }
case 3: { int cf = get_flag(emu, X86_CF); r = a - b - cf; set_cf_sub(emu, a - cf, b, size); set_of_sub(emu, a, b, r, size); set_zf_sf_pf(emu, r, size); break; }
case 4: r = a & b; set_flag(emu, X86_CF, 0); set_flag(emu, X86_OF, 0); set_zf_sf_pf(emu, r, size); break;
case 5: r = a - b; set_cf_sub(emu, a, b, size); set_of_sub(emu, a, b, r, size); set_zf_sf_pf(emu, r, size); break;
case 6: r = a ^ b; set_flag(emu, X86_CF, 0); set_flag(emu, X86_OF, 0); set_zf_sf_pf(emu, r, size); break;
case 7: r = a - b; set_cf_sub(emu, a, b, size); set_of_sub(emu, a, b, r, size); set_zf_sf_pf(emu, r, size); break; /* CMP 不写回 */
}
return r & mask;
}
/* ===== 移位操作(按 op:ROL/ROR/RCL/RCR/SHL/SHR/SAR/SAL) ===== */
static u32 shift_op(x86emu_state *emu, int op, u32 val, u8 count, int size) {
u32 mask = (size == 1) ? 0xFF : (size == 2) ? 0xFFFF : 0xFFFFFFFF;
val &= mask;
count &= 0x1F;
if (count == 0) return val;
u32 r = val;
switch (op) {
case 4: case 6: /* SHL / SAL */
r = val << count;
set_flag(emu, X86_CF, (val >> (32 - count)) & 1);
break;
case 5: /* SHR */
r = val >> count;
set_flag(emu, X86_CF, (val >> (count - 1)) & 1);
break;
case 7: /* SAR */
r = (u32)((i32)val >> count);
set_flag(emu, X86_CF, (val >> (count - 1)) & 1);
break;
case 0: /* ROL */
r = ((val << count) | (val >> (size * 8 - count))) & mask;
set_flag(emu, X86_CF, r & 1);
break;
case 1: /* ROR */
r = ((val >> count) | (val << (size * 8 - count))) & mask;
set_flag(emu, X86_CF, (r >> (size * 8 - 1)) & 1);
break;
default: break; /* RCL/RCR 暂简化 */
}
if (op >= 4) set_zf_sf_pf(emu, r, size); /* SHL/SHR/SAR 影响 ZF/SF/PF */
return r & mask;
}
/* ===== IAT CALL 拦截 ===== */
/* stdcall 参数个数表(kernel32.dll 函数:callee 清栈)。
* msvcrt.dll 函数为 cdecl(caller 清栈),不在此表。
* key = shim 函数名首字符 + 长度组合的简单 hash,避免 strcmp。
* 简化:直接用函数指针地址查表。 */
static int try_iat_call(x86emu_state *emu, u32 target) {
/* 检查是否为合成 shim 地址 */
if (target >= 0x00010000 && target < 0x00020000) {
int shim_idx = target & 0xFFFF;
if (shim_idx == 0xFFFF) {
/* 严格错误策略插桩:32 位解释器调用未实现 API = 静默 EAX=0
* 会给 PE 程序喂错误语义,零降级 panic(PE-E06)。 */
log_error("[PE32] call unimplemented API");
panic_full("PE-E06 EMU UNSHIMMED API CALLED",
"x86emu32 IAT call hit unimplemented stub: not implemented", 0);
2026-07-28 14:35:14 +08:00
emu->regs[X86_EAX] = 0;
return 1;
}
const pe_shim_entry *se = pe_shim_get(shim_idx);
if (!se) {
/* 严格错误策略插桩:shim 索引越界 = 导入解析已损坏,panic(PE-E07) */
log_error("[PE32] shim index out of range");
panic_full("PE-E07 SHIM INDEX OUT OF RANGE",
"x86emu32 IAT call with invalid shim index", 0);
2026-07-28 14:35:14 +08:00
emu->regs[X86_EAX] = 0;
return 1;
}
/* 从模拟栈读参数。CALL 被拦截前未 push 返回地址,
* 所以 ESP 指向第一个参数。 */
u32 esp_val = emu->regs[X86_ESP];
if (esp_val + 32 > emu->mem_size) {
emu->error = 1;
emu->error_msg = "shim esp OOB";
return 1;
}
u64 a0 = x86emu32_read32(emu, esp_val);
u64 a1 = x86emu32_read32(emu, esp_val + 4);
u64 a2 = x86emu32_read32(emu, esp_val + 8);
u64 a3 = x86emu32_read32(emu, esp_val + 12);
u64 ret;
if (se->fn32) {
/* 有专用 32位实现 */
void *esp_ptr = &emu->mem[esp_val];
ret = se->fn32(esp_ptr);
} else if (se->fn64) {
/* 回退:调用 64位 shim(最多 4 个参数)。
* BUG-20260801-007 后续修正:fn4_t 必须显式 ms_abi。
* UTSM 以 clang x86_64-unknown-none 编译,C 默认 ABI 是 SysV
* (arg1=RDI/RSI/RDX/RCX),而 shim 全部 __attribute__((ms_abi))
* (arg1=RCX/RDX/R8/R9)。typedef 不带 ms_abi 时编译器生成 SysV
* 调用序列 → shim 在 RCX 读到的是 SysV 第4参数 a3(=0) → gp(0)=0
* → shim_printf 解引用 NULL → #PF cr2=0(实测寄存器现场:
* rdi=0x401017 即 SysV arg1=fmt, rcx=0, cr2=0)。
* 原生 PE32+ 路径 guest 是 Windows 程序天生 MS ABI,不受影响。 */
typedef u64 (__attribute__((ms_abi)) *fn4_t)(u64, u64, u64, u64);
2026-07-28 14:35:14 +08:00
fn4_t f = (fn4_t)se->fn64;
ret = f(a0, a1, a2, a3);
/* stdcall 清栈:kernel32.dll 函数 callee 清栈。
* 简化:按已知参数个数调整 ESP。
* msvcrt.dll (cdecl) 不清栈。 */
if (se->dll[0] == 'k') { /* kernel32.dll */
int nargs = 4; /* 默认假设 4 参数 */
/* 按函数名精化参数个数 */
const char *fn = se->func;
if (fn[0]=='G' && fn[1]=='e' && fn[2]=='t' && fn[3]=='S') nargs = 1;
else if (fn[0]=='W' && fn[1]=='r' && fn[2]=='i') nargs = 5;
else if (fn[0]=='R' && fn[1]=='e' && fn[2]=='a' && fn[3]=='d') nargs = 5;
else if (fn[0]=='E' && fn[1]=='x' && fn[2]=='i' && fn[3]=='t') nargs = 1;
else if (fn[0]=='G' && fn[1]=='e' && fn[2]=='t' && fn[3]=='C') nargs = 0;
else if (fn[0]=='G' && fn[1]=='e' && fn[2]=='t' && fn[3]=='L') nargs = 0;
else if (fn[0]=='S' && fn[1]=='e' && fn[2]=='t' && fn[3]=='L') nargs = 1;
else if (fn[0]=='H' && fn[1]=='e' && fn[2]=='a' && fn[3]=='p') nargs = 3;
else if (fn[0]=='V' && fn[1]=='i' && fn[2]=='r') nargs = 4;
else if (fn[0]=='G' && fn[1]=='e' && fn[2]=='t' && fn[3]=='M') nargs = 1;
else if (fn[0]=='C' && fn[1]=='l' && fn[2]=='o') nargs = 1;
else if (fn[0]=='C' && fn[1]=='r' && fn[2]=='e') nargs = 7;
emu->regs[X86_ESP] += (u32)(nargs * 4);
}
} else {
log_warn("[PE32] no shim impl");
ret = 0;
}
emu->regs[X86_EAX] = (u32)ret;
return 1;
}
/* 检查是否为 ExitProcess 特殊地址(64位 ExitProcess shim) */
if (pe_shim_is_exit_call((u64)target)) {
pe_shim_exit_process(emu->regs[X86_EAX] ? emu->regs[X86_EAX] : 0);
emu->exited = 1;
return 1;
}
return 0; /* 不是 IAT/shim 调用 */
}
/* ===== 条件跳转判断 ===== */
static int check_jcc(x86emu_state *emu, int cond) {
int zf = get_flag(emu, X86_ZF);
int sf = get_flag(emu, X86_SF);
int of = get_flag(emu, X86_OF);
int cf = get_flag(emu, X86_CF);
int pf = get_flag(emu, X86_PF);
switch (cond & 0xF) {
case 0x0: return of;
case 0x1: return !of;
case 0x2: return cf;
case 0x3: return !cf;
case 0x4: return zf;
case 0x5: return !zf;
case 0x6: return cf || zf;
case 0x7: return !cf && !zf;
case 0x8: return sf;
case 0x9: return !sf;
case 0xA: return pf;
case 0xB: return !pf;
case 0xC: return sf != of;
case 0xD: return sf == of;
case 0xE: return zf || (sf != of);
case 0xF: return !zf && (sf == of);
}
return 0;
}
/* ===== 主执行循环 ===== */
int x86emu32_run(x86emu_state *emu, u64 *exit_code) {
emu->insn_limit = 500000000ULL; /* 5亿指令上限防死循环 */
while (!emu->exited && !emu->error && emu->insn_count < emu->insn_limit) {
emu->insn_count++;
/* 前缀处理 */
int operand_size = 4; /* 默认 32位 */
int rep_prefix = 0; /* 0=无, 1=REP/REPE, 2=REPNE(记录但暂未用于字符串指令) */
u8 op;
int prefix_done = 0;
while (!prefix_done) {
op = fetch8(emu);
switch (op) {
case 0x66: operand_size = 2; break;
case 0x67: break; /* 地址大小前缀(忽略,32位寻址) */
case 0xF0: break; /* LOCK */
case 0xF2: rep_prefix = 2; break; /* REPNE */
case 0xF3: rep_prefix = 1; break; /* REP/REPE */
case 0x26: case 0x2E: case 0x36: case 0x3E: case 0x64: case 0x65: break; /* 段前缀忽略 */
default: prefix_done = 1; break;
}
}
(void)rep_prefix; /* 记录前缀,字符串指令暂未使用 */
/* 操作数大小:对 0x66 前缀,32位操作变 16位 */
int osz = operand_size; /* 4 或 2 */
switch (op) {
/* ---- ALU modr/m(0x00-0x3F)---- */
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x08: case 0x09: case 0x0A: case 0x0B:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x18: case 0x19: case 0x1A: case 0x1B:
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x28: case 0x29: case 0x2A: case 0x2B:
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x38: case 0x39: case 0x3A: case 0x3B: {
int alu = (op >> 3) & 7;
int dir = op & 1; /* 0: r/m8←r8, 1: r/m32←r32 (或反向) */
int is8 = !(op & 4); /* 0x00-0x03=8位, 0x04+ =32位 */
modrm_dec m = decode_modrm(emu);
if (is8) {
u8 a, b; int cmp_only = (alu == 7);
if (dir == 0) { a = read_rm8(emu, &m); b = get_reg8(emu, m.reg); }
else { a = get_reg8(emu, m.reg); b = read_rm8(emu, &m); }
u8 r = (u8)alu_op(emu, alu, a, b, 1);
if (alu != 7) { if (dir == 0) write_rm8(emu, &m, r); else set_reg8(emu, m.reg, r); }
(void)cmp_only;
} else {
u32 a, b;
if (dir == 0) { a = read_rm32(emu, &m); b = get_reg32(emu, m.reg); }
else { a = get_reg32(emu, m.reg); b = read_rm32(emu, &m); }
u32 r = alu_op(emu, alu, a, b, osz);
if (alu != 7) { if (dir == 0) write_rm32(emu, &m, r); else set_reg32(emu, m.reg, r); }
if (osz == 2) { if (alu != 7) { if (dir == 0) write_rm16(emu, &m, (u16)r); else set_reg16(emu, m.reg, (u16)r); } }
}
break;
}
/* ---- ALU AL/EAX, imm ---- */
case 0x04: case 0x0C: case 0x14: case 0x1C:
case 0x24: case 0x2C: case 0x34: case 0x3C: {
int alu = (op >> 3) & 7;
u8 imm = fetch8(emu);
u8 r = (u8)alu_op(emu, alu, get_reg8(emu, 0), imm, 1);
if (alu != 7) set_reg8(emu, 0, r);
break;
}
case 0x05: case 0x0D: case 0x15: case 0x1D:
case 0x25: case 0x2D: case 0x35: case 0x3D: {
int alu = (op >> 3) & 7;
if (osz == 2) {
u16 imm = fetch16(emu);
u16 r = (u16)alu_op(emu, alu, get_reg16(emu, 0), imm, 2);
if (alu != 7) set_reg16(emu, 0, r);
} else {
u32 imm = fetch32(emu);
u32 r = alu_op(emu, alu, get_reg32(emu, 0), imm, 4);
if (alu != 7) set_reg32(emu, 0, r);
}
break;
}
/* ---- INC/DEC reg(0x40-0x4F)---- */
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x45: case 0x46: case 0x47: {
int r = op - 0x40;
int cf = get_flag(emu, X86_CF);
if (osz == 2) { u16 v = get_reg16(emu, r); u16 res = (u16)alu_op(emu, 0, v, 1, 2); set_reg16(emu, r, res); }
else { u32 v = get_reg32(emu, r); u32 res = alu_op(emu, 0, v, 1, 4); set_reg32(emu, r, res); }
set_flag(emu, X86_CF, cf); /* INC 不影响 CF */
break;
}
case 0x48: case 0x49: case 0x4A: case 0x4B:
case 0x4C: case 0x4D: case 0x4E: case 0x4F: {
int r = op - 0x48;
int cf = get_flag(emu, X86_CF);
if (osz == 2) { u16 v = get_reg16(emu, r); u16 res = (u16)alu_op(emu, 5, v, 1, 2); set_reg16(emu, r, res); }
else { u32 v = get_reg32(emu, r); u32 res = alu_op(emu, 5, v, 1, 4); set_reg32(emu, r, res); }
set_flag(emu, X86_CF, cf);
break;
}
/* ---- PUSH/POP reg ---- */
case 0x50: case 0x51: case 0x52: case 0x53:
case 0x54: case 0x55: case 0x56: case 0x57:
x86emu32_push32(emu, get_reg32(emu, op - 0x50));
break;
case 0x58: case 0x59: case 0x5A: case 0x5B:
case 0x5C: case 0x5D: case 0x5E: case 0x5F:
set_reg32(emu, op - 0x58, x86emu32_pop32(emu));
break;
/* ---- PUSHA/POPA ---- */
case 0x60: {
u32 sp = emu->regs[X86_ESP];
x86emu32_push32(emu, emu->regs[X86_EAX]);
x86emu32_push32(emu, emu->regs[X86_ECX]);
x86emu32_push32(emu, emu->regs[X86_EDX]);
x86emu32_push32(emu, emu->regs[X86_EBX]);
x86emu32_push32(emu, sp);
x86emu32_push32(emu, emu->regs[X86_EBP]);
x86emu32_push32(emu, emu->regs[X86_ESI]);
x86emu32_push32(emu, emu->regs[X86_EDI]);
break;
}
case 0x61: {
emu->regs[X86_EDI] = x86emu32_pop32(emu);
emu->regs[X86_ESI] = x86emu32_pop32(emu);
emu->regs[X86_EBP] = x86emu32_pop32(emu);
x86emu32_pop32(emu); /* 忽略原始 ESP */
emu->regs[X86_EBX] = x86emu32_pop32(emu);
emu->regs[X86_EDX] = x86emu32_pop32(emu);
emu->regs[X86_ECX] = x86emu32_pop32(emu);
emu->regs[X86_EAX] = x86emu32_pop32(emu);
break;
}
/* ---- PUSH imm ---- */
case 0x68: x86emu32_push32(emu, fetch32(emu)); break;
case 0x6A: x86emu32_push32(emu, (u32)(i32)(i8)fetch8(emu)); break;
/* ---- IMUL r, r/m, imm ---- */
case 0x69: case 0x6B: {
modrm_dec m = decode_modrm(emu);
u32 src = read_rm32(emu, &m);
u32 imm = (op == 0x69) ? fetch32(emu) : (u32)(i32)(i8)fetch8(emu);
i64 result = (i64)(i32)src * (i64)(i32)imm;
set_reg32(emu, m.reg, (u32)result);
set_flag(emu, X86_OF, result > 0x7FFFFFFFLL || result < -0x80000000LL);
set_flag(emu, X86_CF, get_flag(emu, X86_OF));
break;
}
/* ---- Jcc rel8 ---- */
case 0x70: case 0x71: case 0x72: case 0x73:
case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7A: case 0x7B:
case 0x7C: case 0x7D: case 0x7E: case 0x7F: {
i8 rel = (i8)fetch8(emu);
if (check_jcc(emu, op & 0xF)) emu->eip += (u32)(i32)rel;
break;
}
/* ---- ALU r/m, imm8 (0x80/0x82) / r/m, imm32 (0x81) ---- */
case 0x80: case 0x82: {
modrm_dec m = decode_modrm(emu);
u8 imm = fetch8(emu);
u8 a = read_rm8(emu, &m);
u8 r = (u8)alu_op(emu, m.reg, a, imm, 1);
if (m.reg != 7) write_rm8(emu, &m, r);
break;
}
case 0x81: {
modrm_dec m = decode_modrm(emu);
if (osz == 2) {
u16 imm = fetch16(emu);
u16 a = read_rm16(emu, &m);
u16 r = (u16)alu_op(emu, m.reg, a, imm, 2);
if (m.reg != 7) write_rm16(emu, &m, r);
} else {
u32 imm = fetch32(emu);
u32 a = read_rm32(emu, &m);
u32 r = alu_op(emu, m.reg, a, imm, 4);
if (m.reg != 7) write_rm32(emu, &m, r);
}
break;
}
case 0x83: {
modrm_dec m = decode_modrm(emu);
u32 imm = (u32)(i32)(i8)fetch8(emu);
if (osz == 2) {
u16 a = read_rm16(emu, &m);
u16 r = (u16)alu_op(emu, m.reg, a, imm & 0xFFFF, 2);
if (m.reg != 7) write_rm16(emu, &m, r);
} else {
u32 a = read_rm32(emu, &m);
u32 r = alu_op(emu, m.reg, a, imm, 4);
if (m.reg != 7) write_rm32(emu, &m, r);
}
break;
}
/* ---- TEST ---- */
case 0x84: case 0x85: {
modrm_dec m = decode_modrm(emu);
if (op == 0x84) {
u8 a = read_rm8(emu, &m); u8 b = get_reg8(emu, m.reg);
alu_op(emu, 4, a, b, 1); /* AND 不写回 */
} else if (osz == 2) {
u16 a = read_rm16(emu, &m); u16 b = get_reg16(emu, m.reg);
alu_op(emu, 4, a, b, 2);
} else {
u32 a = read_rm32(emu, &m); u32 b = get_reg32(emu, m.reg);
alu_op(emu, 4, a, b, 4);
}
break;
}
/* ---- XCHG ---- */
case 0x86: case 0x87: {
modrm_dec m = decode_modrm(emu);
if (op == 0x86) {
u8 a = read_rm8(emu, &m); u8 b = get_reg8(emu, m.reg);
write_rm8(emu, &m, b); set_reg8(emu, m.reg, a);
} else if (osz == 2) {
u16 a = read_rm16(emu, &m); u16 b = get_reg16(emu, m.reg);
write_rm16(emu, &m, b); set_reg16(emu, m.reg, a);
} else {
u32 a = read_rm32(emu, &m); u32 b = get_reg32(emu, m.reg);
write_rm32(emu, &m, b); set_reg32(emu, m.reg, a);
}
break;
}
/* ---- MOV ---- */
case 0x88: { modrm_dec m = decode_modrm(emu); write_rm8(emu, &m, get_reg8(emu, m.reg)); break; }
case 0x89: {
modrm_dec m = decode_modrm(emu);
if (osz == 2) write_rm16(emu, &m, get_reg16(emu, m.reg));
else write_rm32(emu, &m, get_reg32(emu, m.reg));
break;
}
case 0x8A: { modrm_dec m = decode_modrm(emu); set_reg8(emu, m.reg, read_rm8(emu, &m)); break; }
case 0x8B: {
modrm_dec m = decode_modrm(emu);
if (osz == 2) set_reg16(emu, m.reg, read_rm16(emu, &m));
else set_reg32(emu, m.reg, read_rm32(emu, &m));
break;
}
/* ---- LEA ---- */
case 0x8D: {
modrm_dec m = decode_modrm(emu);
if (osz == 2) set_reg16(emu, m.reg, (u16)m.ea);
else set_reg32(emu, m.reg, m.ea);
break;
}
/* ---- NOP / XCHG EAX,reg ---- */
case 0x90: break; /* NOP */
case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: {
int r = op - 0x90;
u32 tmp = emu->regs[0]; emu->regs[0] = emu->regs[r]; emu->regs[r] = tmp;
break;
}
/* ---- CWDE/CDQ ---- */
case 0x98: /* CWDE (32位) / CBW (16位) */
if (osz == 2) set_reg16(emu, 0, (u16)(i16)(i8)get_reg8(emu, 0));
else emu->regs[0] = (u32)(i32)(i16)get_reg16(emu, 0);
break;
case 0x99: /* CDQ (32位) / CWD (16位) */
if (osz == 2) set_reg16(emu, 2, (get_reg16(emu, 0) & 0x8000) ? 0xFFFF : 0);
else emu->regs[2] = (emu->regs[0] & 0x80000000) ? 0xFFFFFFFF : 0;
break;
/* ---- MOV moffs ---- */
case 0xA0: { u32 addr = fetch32(emu); set_reg8(emu, 0, x86emu32_read8(emu, addr)); break; }
case 0xA1: { u32 addr = fetch32(emu); if (osz==2) set_reg16(emu,0,x86emu32_read16(emu,addr)); else set_reg32(emu,0,x86emu32_read32(emu,addr)); break; }
case 0xA2: { u32 addr = fetch32(emu); x86emu32_write8(emu, addr, get_reg8(emu, 0)); break; }
case 0xA3: { u32 addr = fetch32(emu); if (osz==2) x86emu32_write16(emu,addr,get_reg16(emu,0)); else x86emu32_write32(emu,addr,get_reg32(emu,0)); break; }
/* ---- 字符串指令(简化:无 REP 单步)---- */
case 0xA4: { /* MOVSB */
u32 si = emu->regs[X86_ESI], di = emu->regs[X86_EDI];
u8 v = x86emu32_read8(emu, si);
x86emu32_write8(emu, di, v);
int df = get_flag(emu, X86_DF);
si += df ? -1 : 1; di += df ? -1 : 1;
emu->regs[X86_ESI] = si; emu->regs[X86_EDI] = di;
break;
}
case 0xA5: { /* MOVSD/W */
u32 si = emu->regs[X86_ESI], di = emu->regs[X86_EDI];
int df = get_flag(emu, X86_DF); int step = (osz==2)?2:4;
if (osz==2) { u16 v=x86emu32_read16(emu,si); x86emu32_write16(emu,di,v); }
else { u32 v=x86emu32_read32(emu,si); x86emu32_write32(emu,di,v); }
si += df ? -step : step; di += df ? -step : step;
emu->regs[X86_ESI]=si; emu->regs[X86_EDI]=di;
break;
}
case 0xAA: { /* STOSB */
u32 di = emu->regs[X86_EDI];
x86emu32_write8(emu, di, get_reg8(emu, 0));
int df = get_flag(emu, X86_DF);
di += df ? -1 : 1; emu->regs[X86_EDI] = di;
break;
}
case 0xAB: { /* STOSD/W */
u32 di = emu->regs[X86_EDI]; int df = get_flag(emu, X86_DF); int step=(osz==2)?2:4;
if (osz==2) x86emu32_write16(emu,di,get_reg16(emu,0));
else x86emu32_write32(emu,di,emu->regs[0]);
di += df?-step:step; emu->regs[X86_EDI]=di;
break;
}
case 0xAC: { /* LODSB */
u32 si = emu->regs[X86_ESI];
set_reg8(emu, 0, x86emu32_read8(emu, si));
int df = get_flag(emu, X86_DF);
si += df ? -1 : 1; emu->regs[X86_ESI] = si;
break;
}
case 0xAD: { /* LODSD/W */
u32 si = emu->regs[X86_ESI]; int df=get_flag(emu,X86_DF); int step=(osz==2)?2:4;
if (osz==2) set_reg16(emu,0,x86emu32_read16(emu,si)); else set_reg32(emu,0,x86emu32_read32(emu,si));
si += df?-step:step; emu->regs[X86_ESI]=si;
break;
}
/* ---- TEST AL/EAX, imm ---- */
case 0xA8: { u8 imm = fetch8(emu); alu_op(emu, 4, get_reg8(emu,0), imm, 1); break; }
case 0xA9: {
if (osz==2) { u16 imm=fetch16(emu); alu_op(emu,4,get_reg16(emu,0),imm,2); }
else { u32 imm=fetch32(emu); alu_op(emu,4,emu->regs[0],imm,4); }
break;
}
/* ---- MOV reg, imm ---- */
case 0xB0: case 0xB1: case 0xB2: case 0xB3:
case 0xB4: case 0xB5: case 0xB6: case 0xB7:
set_reg8(emu, op - 0xB0, fetch8(emu));
break;
case 0xB8: case 0xB9: case 0xBA: case 0xBB:
case 0xBC: case 0xBD: case 0xBE: case 0xBF:
if (osz==2) set_reg16(emu, op-0xB8, fetch16(emu));
else set_reg32(emu, op-0xB8, fetch32(emu));
break;
/* ---- shift r/m, imm8 ---- */
case 0xC0: case 0xC1: {
modrm_dec m = decode_modrm(emu);
u8 count = fetch8(emu);
if (op == 0xC0) { u8 v = read_rm8(emu,&m); write_rm8(emu,&m,(u8)shift_op(emu,m.reg,v,count,1)); }
else if (osz==2) { u16 v=read_rm16(emu,&m); write_rm16(emu,&m,(u16)shift_op(emu,m.reg,v,count,2)); }
else { u32 v=read_rm32(emu,&m); write_rm32(emu,&m,shift_op(emu,m.reg,v,count,4)); }
break;
}
/* ---- RET ---- */
case 0xC2: { u16 imm = fetch16(emu); emu->eip = x86emu32_pop32(emu); emu->regs[X86_ESP] += imm; break; }
case 0xC3: { emu->eip = x86emu32_pop32(emu); break; }
/* ---- MOV r/m, imm ---- */
case 0xC6: { modrm_dec m = decode_modrm(emu); u8 imm = fetch8(emu); write_rm8(emu,&m,imm); break; }
case 0xC7: {
modrm_dec m = decode_modrm(emu);
if (osz==2) { u16 imm=fetch16(emu); write_rm16(emu,&m,imm); }
else { u32 imm=fetch32(emu); write_rm32(emu,&m,imm); }
break;
}
/* ---- LEAVE ---- */
case 0xC9:
emu->regs[X86_ESP] = emu->regs[X86_EBP];
emu->regs[X86_EBP] = x86emu32_pop32(emu);
break;
/* ---- INT3 / INT ---- */
case 0xCC: /* INT3 */
emu->error = 1; emu->error_msg = "INT3 breakpoint";
break;
case 0xCD: { /* INT imm8 */
u8 v = fetch8(emu); (void)v;
/* 简化:忽略软件中断 */
break;
}
/* ---- shift r/m, 1 / CL ---- */
case 0xD0: case 0xD1: case 0xD2: case 0xD3: {
modrm_dec m = decode_modrm(emu);
u8 count = (op & 2) ? (get_reg8(emu, 1) & 0x1F) : 1;
int is8 = !(op & 1);
if (is8) { u8 v=read_rm8(emu,&m); write_rm8(emu,&m,(u8)shift_op(emu,m.reg,v,count,1)); }
else if (osz==2) { u16 v=read_rm16(emu,&m); write_rm16(emu,&m,(u16)shift_op(emu,m.reg,v,count,2)); }
else { u32 v=read_rm32(emu,&m); write_rm32(emu,&m,shift_op(emu,m.reg,v,count,4)); }
break;
}
/* ---- CALL rel32 ---- */
case 0xE8: {
i32 rel = (i32)fetch32(emu);
x86emu32_push32(emu, emu->eip); /* return address */
emu->eip += (u32)rel;
break;
}
/* ---- JMP rel32 ---- */
case 0xE9: { i32 rel = (i32)fetch32(emu); emu->eip += (u32)rel; break; }
/* ---- JMP rel8 ---- */
case 0xEB: { i8 rel = (i8)fetch8(emu); emu->eip += (u32)(i32)rel; break; }
/* ---- LOOP ---- */
case 0xE0: case 0xE1: case 0xE2: {
i8 rel = (i8)fetch8(emu);
u32 cx = emu->regs[X86_ECX] - 1;
emu->regs[X86_ECX] = cx;
int do_jump = (cx != 0);
if (op == 0xE0 && get_flag(emu, X86_ZF)) do_jump = 0; /* LOOPNE */
if (op == 0xE1 && !get_flag(emu, X86_ZF)) do_jump = 0; /* LOOPE */
if (do_jump) emu->eip += (u32)(i32)rel;
break;
}
case 0xE3: { /* JECXZ */
i8 rel = (i8)fetch8(emu);
if (emu->regs[X86_ECX] == 0) emu->eip += (u32)(i32)rel;
break;
}
/* ---- CALL/JMP r/m ---- */
case 0xFF: {
modrm_dec m = decode_modrm(emu);
switch (m.reg) {
case 0: { /* INC r/m */
int cf=get_flag(emu,X86_CF);
if (osz==2) { u16 v=read_rm16(emu,&m); write_rm16(emu,&m,(u16)alu_op(emu,0,v,1,2)); }
else { u32 v=read_rm32(emu,&m); write_rm32(emu,&m,alu_op(emu,0,v,1,4)); }
set_flag(emu,X86_CF,cf);
break;
}
case 1: { /* DEC r/m */
int cf=get_flag(emu,X86_CF);
if (osz==2) { u16 v=read_rm16(emu,&m); write_rm16(emu,&m,(u16)alu_op(emu,5,v,1,2)); }
else { u32 v=read_rm32(emu,&m); write_rm32(emu,&m,alu_op(emu,5,v,1,4)); }
set_flag(emu,X86_CF,cf);
break;
}
case 2: { /* CALL r/m32 */
u32 target = read_rm32(emu, &m);
if (try_iat_call(emu, target)) break;
x86emu32_push32(emu, emu->eip);
emu->eip = target;
break;
}
case 4: { /* JMP r/m32 */
u32 target = read_rm32(emu, &m);
if (try_iat_call(emu, target)) { emu->exited = 1; break; }
emu->eip = target;
break;
}
case 6: { /* PUSH r/m32 */
x86emu32_push32(emu, read_rm32(emu, &m));
break;
}
default:
emu->error = 1; emu->error_msg = "FF /reg unsupported";
break;
}
break;
}
/* ---- F6/F7 组 ---- */
case 0xF6: {
modrm_dec m = decode_modrm(emu);
if (m.reg == 0 || m.reg == 1) { /* TEST r/m8, imm8 */
u8 imm = fetch8(emu);
alu_op(emu, 4, read_rm8(emu,&m), imm, 1);
} else if (m.reg == 2) { /* NOT r/m8 */
write_rm8(emu, &m, ~read_rm8(emu, &m));
} else if (m.reg == 3) { /* NEG r/m8 */
u8 v = read_rm8(emu, &m);
u8 r = (u8)(-(i8)v);
set_flag(emu, X86_CF, v != 0);
set_zf_sf_pf(emu, r, 1);
write_rm8(emu, &m, r);
} else if (m.reg == 4) { /* MUL r/m8 */
u16 result = (u16)get_reg8(emu, 0) * (u16)read_rm8(emu, &m);
set_reg8(emu, 0, (u8)result);
set_reg8(emu, 4, (u8)(result >> 8));
set_flag(emu, X86_CF, result >> 8 != 0);
set_flag(emu, X86_OF, get_flag(emu, X86_CF));
} else {
emu->error = 1; emu->error_msg = "F6 /reg unsupported";
}
break;
}
case 0xF7: {
modrm_dec m = decode_modrm(emu);
if (m.reg == 0 || m.reg == 1) { /* TEST r/m32, imm32 */
if (osz==2) { u16 imm=fetch16(emu); alu_op(emu,4,read_rm16(emu,&m),imm,2); }
else { u32 imm=fetch32(emu); alu_op(emu,4,read_rm32(emu,&m),imm,4); }
} else if (m.reg == 2) { /* NOT */
if (osz==2) write_rm16(emu,&m,~read_rm16(emu,&m));
else write_rm32(emu,&m,~read_rm32(emu,&m));
} else if (m.reg == 3) { /* NEG */
if (osz==2) { u16 v=read_rm16(emu,&m); u16 r=(u16)(-(i16)v); set_flag(emu,X86_CF,v!=0); set_zf_sf_pf(emu,r,2); write_rm16(emu,&m,r); }
else { u32 v=read_rm32(emu,&m); u32 r=(u32)(-(i32)v); set_flag(emu,X86_CF,v!=0); set_zf_sf_pf(emu,r,4); write_rm32(emu,&m,r); }
} else if (m.reg == 4) { /* MUL */
if (osz==2) { u32 result=(u32)get_reg16(emu,0)*(u32)read_rm16(emu,&m); set_reg16(emu,0,(u16)result); set_reg16(emu,2,(u16)(result>>16)); set_flag(emu,X86_CF,result>>16!=0); set_flag(emu,X86_OF,get_flag(emu,X86_CF)); }
else { u64 result=(u64)emu->regs[0]*(u64)read_rm32(emu,&m); emu->regs[0]=(u32)result; emu->regs[2]=(u32)(result>>32); set_flag(emu,X86_CF,result>>32!=0); set_flag(emu,X86_OF,get_flag(emu,X86_CF)); }
} else if (m.reg == 5) { /* IMUL */
if (osz==2) { i32 result=(i32)(i16)get_reg16(emu,0)*(i32)(i16)read_rm16(emu,&m); set_reg16(emu,0,(u16)result); set_reg16(emu,2,(u16)(result>>16)); set_flag(emu,X86_OF,result>32767||result<-32768); set_flag(emu,X86_CF,get_flag(emu,X86_OF)); }
else { i64 result=(i64)(i32)emu->regs[0]*(i64)(i32)read_rm32(emu,&m); emu->regs[0]=(u32)result; emu->regs[2]=(u32)(result>>32); set_flag(emu,X86_OF,result>0x7FFFFFFFLL||result<-0x80000000LL); set_flag(emu,X86_CF,get_flag(emu,X86_OF)); }
} else if (m.reg == 6) { /* DIV */
if (osz==2) { u32 dividend=((u32)get_reg16(emu,2)<<16)|get_reg16(emu,0); u16 divisor=read_rm16(emu,&m); if(divisor){set_reg16(emu,0,(u16)(dividend/divisor));set_reg16(emu,2,(u16)(dividend%divisor));} }
else { u64 dividend=((u64)emu->regs[2]<<32)|emu->regs[0]; u32 divisor=read_rm32(emu,&m); if(divisor){emu->regs[0]=(u32)(dividend/divisor);emu->regs[2]=(u32)(dividend%divisor);} }
} else if (m.reg == 7) { /* IDIV */
if (osz==2) { i32 dividend=((i32)(i16)get_reg16(emu,2)<<16)|(i16)get_reg16(emu,0); i16 divisor=(i16)read_rm16(emu,&m); if(divisor){set_reg16(emu,0,(u16)(dividend/divisor));set_reg16(emu,2,(u16)(dividend%divisor));} }
else { i64 dividend=((i64)(i32)emu->regs[2]<<32)|(i32)emu->regs[0]; i32 divisor=(i32)read_rm32(emu,&m); if(divisor){emu->regs[0]=(u32)(dividend/divisor);emu->regs[2]=(u32)(dividend%divisor);} }
}
break;
}
/* ---- CLC/STC/CLI/STI/CLD/STD ---- */
case 0xF8: set_flag(emu, X86_CF, 0); break;
case 0xF9: set_flag(emu, X86_CF, 1); break;
case 0xFA: break; /* CLI(忽略) */
case 0xFB: break; /* STI(忽略) */
case 0xFC: set_flag(emu, X86_DF, 0); break;
case 0xFD: set_flag(emu, X86_DF, 1); break;
/* ---- INC/DEC r/m8 ---- */
case 0xFE: {
modrm_dec m = decode_modrm(emu);
int cf = get_flag(emu, X86_CF);
u8 v = read_rm8(emu, &m);
if (m.reg == 0) write_rm8(emu, &m, (u8)alu_op(emu, 0, v, 1, 1));
else if (m.reg == 1) write_rm8(emu, &m, (u8)alu_op(emu, 5, v, 1, 1));
set_flag(emu, X86_CF, cf);
break;
}
/* ---- MOVSX/MOVZX 在 0x0F 两字节 opcode 中处理 ---- */
case 0x0F: { /* 两字节 opcode */
u8 op2 = fetch8(emu);
if (op2 >= 0x80 && op2 <= 0x8F) { /* Jcc rel32 */
i32 rel = (i32)fetch32(emu);
if (check_jcc(emu, op2 & 0xF)) emu->eip += (u32)rel;
} else if (op2 == 0xAF) { /* IMUL r32, r/m32 */
modrm_dec m = decode_modrm(emu);
i64 result = (i64)(i32)get_reg32(emu, m.reg) * (i64)(i32)read_rm32(emu, &m);
set_reg32(emu, m.reg, (u32)result);
set_flag(emu, X86_OF, result > 0x7FFFFFFFLL || result < -0x80000000LL);
set_flag(emu, X86_CF, get_flag(emu, X86_OF));
} else if (op2 == 0xB6 || op2 == 0xB7) { /* MOVZX r32, r/m8/16 */
modrm_dec m = decode_modrm(emu);
if (op2 == 0xB6) { set_reg32(emu, m.reg, (u32)read_rm8(emu, &m)); }
else { set_reg32(emu, m.reg, (u32)read_rm16(emu, &m)); }
} else if (op2 == 0xBE || op2 == 0xBF) { /* MOVSX r32, r/m8/16 */
modrm_dec m = decode_modrm(emu);
if (op2 == 0xBE) { set_reg32(emu, m.reg, (u32)(i32)(i8)read_rm8(emu, &m)); }
else { set_reg32(emu, m.reg, (u32)(i32)(i16)read_rm16(emu, &m)); }
} else if (op2 == 0x1F) { /* NOP r/m(多字节 NOP) */
decode_modrm(emu);
} else if (op2 == 0x05) { /* SYSCALL(不应出现在32位PE) */
emu->error = 1; emu->error_msg = "SYSCALL in 32-bit PE";
} else {
emu->error = 1; emu->error_msg = "0F opcode unsupported";
}
break;
}
default:
emu->error = 1; emu->error_msg = "unsupported opcode";
break;
} /* end switch(op) */
if (emu->error) {
log_hex64("[PE32] error at EIP=", emu->eip);
log_hex64("[PE32] opcode=", op);
log_info("[PE32] ");
log_info(emu->error_msg ? emu->error_msg : "(null)");
break;
}
} /* end while */
if (emu->insn_count >= emu->insn_limit) {
log_error("[PE32] instruction limit reached");
emu->error = 1;
}
if (exit_code) *exit_code = emu->exit_code;
return emu->error ? -1 : 0;
}
int x86emu32_init(x86emu_state *emu, u8 *mem, u64 mem_size,
u32 image_base, u32 image_size,
pe_iat_entry *iat_entries, int iat_count,
u32 stack_top) {
for (int i = 0; i < 8; i++) emu->regs[i] = 0;
emu->eip = 0;
emu->eflags = 0x2; /* 保留位 = 1 */
emu->mem = mem;
emu->mem_size = mem_size;
emu->image_base = image_base;
emu->image_size = image_size;
emu->iat_entries = iat_entries;
emu->iat_count = iat_count;
emu->stack_base = stack_top;
emu->stack_size = 0x10000; /* 64KB 栈 */
emu->heap_base = image_base + image_size;
emu->heap_size = 0x100000; /* 1MB heap */
emu->heap_next = emu->heap_base;
emu->exited = 0;
emu->exit_code = 0;
emu->error = 0;
emu->error_msg = 0;
emu->insn_count = 0;
/* 设置 ESP 到栈顶,对齐 16 */
emu->regs[X86_ESP] = stack_top & ~0xFu;
emu->regs[X86_EBP] = 0;
return 0;
}