如何匹配MOV读两字节后接AND指令的x86原汇编代码?
旧VC++编译游戏反汇编匹配问题解决方法
我正在反编译一款用Microsoft Visual C++ 4.1/4.2编译的Windows 95旧游戏可执行文件,在decomp.me上为每个函数创建scratch,目标是写出能精准匹配原汇编的C代码(注意decomp.me采用AT&T汇编语法)。
遇到的核心问题:
原汇编通过先读取两字节数据,再用AND指令清零高位,实现从四字节结构/联合体中读取unsigned short:
mov 0x4328f8(,%eax,2),%ax
and $0xffff,%eax
但尝试常规写法时,生成的汇编始终不匹配:
- 直接用unsigned short类型读取并赋值给unsigned int,编译器会生成带xor的指令且无and:
xor %edx,%edx
mov _DAT_004328f8-0x10(,%eax,2),%dx - 用有符号short类型,mov会变成movswl,手动加
& 0xFFFF也无法生成预期的and指令:movswl _DAT_004328f8-0x10(,%eax,2),%eax
可行的解决思路
切换低优化级别
在decomp.me的编译器设置中选择-O0(无优化)。旧版VC++4.x优化程度低,不会使用movzx这类现代扩展指令,而无优化的GCC编译行为更接近旧编译器,会生成先读16位寄存器再清零高位的代码。拆分赋值操作
不要将读取和类型转换合并成一行,拆分为两步明确的赋值,引导编译器生成匹配的汇编:// 定义数据指针,对应原汇编的0x4328f8地址 unsigned short *game_data = (unsigned short *)0x4328f8; // 假设eax是传入的索引值 unsigned int index = eax; // 第一步:读取16位值到临时变量 unsigned short temp = game_data[index]; // 第二步:转换为32位无符号整数 unsigned int result = temp;强制阻止优化(可选)
如果低优化级别仍被编译器优化掉and指令,给临时变量添加volatile修饰,强制编译器保留中间读取步骤:volatile unsigned short temp = game_data[index]; unsigned int result = temp;
内容的提问来源于stack exchange,提问作者user16316067
相关产品推荐
相关产品推荐

