assembly - x86 装配问题 - 任何人都可以确定下面发生了什么吗?
问题描述
我为我玩的一个 20 多年前的游戏下载了一个修改,它是用汇编代码编写的。它添加了雾效果,然后基于此改变抓地力水平。然而,雾级别似乎是随机选择的。
用受过训练的眼睛很容易看到下面发生的事情吗?我通过反汇编程序运行它,所以不确定它是否真的正确显示......
很容易发现递增的 0x33、0x34、0x35 等,所以我有一种重要的感觉。
0x0000000000000000: DD 35 00 00 00 00 fnsave dword ptr [0]
0x0000000000000006: 80 3D 00 00 00 00 B8 cmp byte ptr [0], 0xb8
0x000000000000000d: 75 24 jne 0x33
0x000000000000000f: 80 3D A8 11 55 00 02 cmp byte ptr [0x5511a8], 2
0x0000000000000016: 0F 85 E6 00 00 00 jne 0x102
0x000000000000001c: 80 3D 00 00 00 00 00 cmp byte ptr [0], 0
0x0000000000000023: 75 30 jne 0x55
0x0000000000000025: 50 push eax
0x0000000000000026: A1 04 B5 6C 00 mov eax, dword ptr [0x6cb504]
0x000000000000002b: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000030: 58 pop eax
0x0000000000000031: EB 22 jmp 0x55
0x0000000000000033: 80 3D B0 11 55 00 02 cmp byte ptr [0x5511b0], 2
0x000000000000003a: 0F 85 C2 00 00 00 jne 0x102
0x0000000000000040: 80 3D 00 00 00 00 00 cmp byte ptr [0], 0
0x0000000000000047: 75 0C jne 0x55
0x0000000000000049: 50 push eax
0x000000000000004a: A1 0C B5 6C 00 mov eax, dword ptr [0x6cb50c]
0x000000000000004f: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000054: 58 pop eax
0x0000000000000055: 80 3D 00 00 00 00 33 cmp byte ptr [0], 0x33
0x000000000000005c: 75 11 jne 0x6f
0x000000000000005e: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000064: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000006a: E9 30 00 00 00 jmp 0x9f
0x000000000000006f: 80 3D 00 00 00 00 34 cmp byte ptr [0], 0x34
0x0000000000000076: 75 11 jne 0x89
0x0000000000000078: D9 05 00 00 00 00 fld dword ptr [0]
0x000000000000007e: D9 1D 00 00 00 00 fstp dword ptr [0]
0x0000000000000084: E9 30 00 00 00 jmp 0xb9
0x0000000000000089: 80 3D 00 00 00 00 35 cmp byte ptr [0], 0x35
0x0000000000000090: 75 11 jne 0xa3
0x0000000000000092: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000098: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000009e: E9 30 00 00 00 jmp 0xd3
0x00000000000000a3: 80 3D 00 00 00 00 36 cmp byte ptr [0], 0x36
0x00000000000000aa: 75 11 jne 0xbd
0x00000000000000ac: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000b2: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000b8: E9 30 00 00 00 jmp 0xed
0x00000000000000bd: 80 3D 00 00 00 00 37 cmp byte ptr [0], 0x37
0x00000000000000c4: 75 11 jne 0xd7
0x00000000000000c6: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000cc: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000d2: E9 30 00 00 00 jmp 0x107
0x00000000000000d7: 80 3D 00 00 00 00 38 cmp byte ptr [0], 0x38
0x00000000000000de: 75 11 jne 0xf1
0x00000000000000e0: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000e6: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000ec: E9 30 00 00 00 jmp 0x121
0x00000000000000f1: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000f7: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000fd: E9 1F 00 00 00 jmp 0x121
0x0000000000000102: E8 00 00 00 00 call 0x107
0x0000000000000107: D9 05 00 00 00 00 fld dword ptr [0]
0x000000000000010d: D8 25 00 00 00 00 fsub dword ptr [0]
0x0000000000000113: D8 C9 fmul st(1)
0x0000000000000115: D8 05 00 00 00 00 fadd dword ptr [0]
0x000000000000011b: D9 1D 00 00 00 00 fstp dword ptr [0]
0x0000000000000121: 50 push eax
0x0000000000000122: B8 01 00 00 00 mov eax, 1
0x0000000000000127: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000012c: B8 BE 00 00 00 mov eax, 0xbe
0x0000000000000131: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000136: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000013b: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000140: 58 pop eax
0x0000000000000141: E8 00 00 00 00 call 0x146
0x0000000000000146: 83 3D 00 00 00 00 00 cmp dword ptr [0], 0
0x000000000000014d: 75 20 jne 0x16f
0x000000000000014f: 50 push eax
0x0000000000000150: A1 00 00 00 00 mov eax, dword ptr [0]
0x0000000000000155: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000015a: A1 00 00 00 00 mov eax, dword ptr [0]
0x000000000000015f: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000164: A1 00 00 00 00 mov eax, dword ptr [0]
0x0000000000000169: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000016e: 58 pop eax
0x000000000000016f: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000175: D8 35 00 00 00 00 fdiv dword ptr [0]
0x000000000000017b: D8 0D 00 00 00 00 fmul dword ptr [0]
0x0000000000000181: D9 E0 fchs
0x0000000000000183: D8 05 00 00 00 00 fadd dword ptr [0]
0x0000000000000189: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000018f: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000195: D8 35 00 00 00 00 fdiv dword ptr [0]
0x000000000000019b: D8 0D 00 00 00 00 fmul dword ptr [0]
0x00000000000001a1: D9 E0 fchs
0x00000000000001a3: D8 05 00 00 00 00 fadd dword ptr [0]
0x00000000000001a9: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000001af: D9 EE fldz
0x00000000000001b1: D8 1D 00 00 00 00 fcomp dword ptr [0]
0x00000000000001b7: 9B wait
0x00000000000001b8: DF E0 fnstsw ax
0x00000000000001ba: 9E sahf
0x00000000000001bb: 74 1E je 0x1db
0x00000000000001bd: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000001c3: D8 35 00 00 00 00 fdiv dword ptr [0]
0x00000000000001c9: D8 0D 00 00 00 00 fmul dword ptr [0]
0x00000000000001cf: D8 05 00 00 00 00 fadd dword ptr [0]
0x00000000000001d5: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000001db: DD 25 00 00 00 00 frstor dword ptr [0]
0x00000000000001e1: E9 00 00 00 00 jmp 0x1e6
<Relocation>
<FromVirtualAddress>004A56B9</FromVirtualAddress>
<ToVirtualAddress>988700</ToVirtualAddress>
<Type>0x0014</Type>
</Relocation>
<BinaryPatch>
<VirtualAddress>0x00A0D308</VirtualAddress>
<Data>
00000000
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D30C</VirtualAddress>
<Data>
0AD7233C
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D314</VirtualAddress>
<Data>
CDCC4C3E
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D31C</VirtualAddress>
<Data>
CDCC4C3E
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D324</VirtualAddress>
<Data>
CDCC4C3E
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D32C</VirtualAddress>
<Data>
0000803E
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D330</VirtualAddress>
<Data>
00004040
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D334</VirtualAddress>
<Data>
00008040
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D338</VirtualAddress>
<Data>
0000A040
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D33C</VirtualAddress>
<Data>
0000C040
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D340</VirtualAddress>
<Data>
0000E040
</Data>
</BinaryPatch>
<BinaryPatch>
<VirtualAddress>0x00A0D344</VirtualAddress>
<Data>
0AD7233C
</Data>
</BinaryPatch>
<Relocation>
<FromVirtualAddress>988702</FromVirtualAddress>
<ToVirtualAddress>00A0D0A0</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>988708</FromVirtualAddress>
<ToVirtualAddress>0040E9C0</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>98871E</FromVirtualAddress>
<ToVirtualAddress>00A0D304</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>98872C</FromVirtualAddress>
<ToVirtualAddress>00A0D304</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>988742</FromVirtualAddress>
<ToVirtualAddress>00A0D304</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>988750</FromVirtualAddress>
<ToVirtualAddress>00A0D304</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
<Relocation>
<FromVirtualAddress>988757</FromVirtualAddress>
<ToVirtualAddress>00A0D304</ToVirtualAddress>
<Type>0006</Type>
</Relocation>
解决方案
使用绝对地址0
很奇怪,大概有某种重定位来修复这些地址。但是你的反汇编并没有显示出来。如果它是标准的对象文件格式,您可以使用它objdump -dr -Mintel foo.o
来包含重定位元数据。
但无论如何,它用于fnsave
转储 x87 FPU 状态。
可能后面的地址具有不同的重定位修复元数据,即使它们都[0]
在您转储的代码中。fsave 区域的开头获取,从该位置到/ 4 个字节FPUControlWord
是没有意义的。fld
fstp
几乎可以肯定fld dword ptr [0]
/在其他 2 个位置之间fstp dword ptr [0]
复制一个float
值,而不是将 FPU 控制和状态字加载/存储到位,作为 4 字节单精度float
。(如果数据表示 NaN,可能会修改数据。) 因此我们必须得出结论,每种[0]
寻址模式实际上可以是任何地址,无论是否在 fsave 区域内。(fsave 区域中的浮点数将采用 80 位 x87 格式,而不是 32 位(dword)单精度,因此fld dword
不太可能对它们进行操作。)
with 0x33 .. 0x38 可能正在查看 x87 状态字的cmp
一个字节,也许是为了找出保存区域中的哪个插槽是当前的栈顶?不,状态字位不在字节的底部。但比较结果(C2、C1、C0)位于状态字( http://www.ray.masmcode.com/tutorial/fpuchap1.htm )的高字节的底部,以及异常状态位在低字节的底部。
因此,这条比较/分支链可能正在 fsave 区域中寻找某些东西。 或者更有可能它只是检查游戏数据某个字节的几个可能值之一。 请注意它如何在不等于时跳转到下一个 cmp/jne。 所以这是if
/else
链,或者是实现switch
/ case 0x33:
/ case 0x34:
/ ... 语句的一种方式。
整个事情周围的fnsave
/frstor
可能是一条红鲱鱼,它可能根本不在那个数据中。相反,它可能只是保存/恢复 FPU 状态,因此它可以使用 x87 指令本身而不会弄乱主程序。我最初认为它是因为[0]
地址而读取了保存区域,但似乎很明显,重定位可能会将该地址指向程序数据的其他部分,而不仅仅是这个补丁自己的私有存储。
推荐阅读
- docker - Docker-compose 完全忽略了我包含环境变量的文件
- java - Eclipse Maven 项目:是否可以将一个版本的 JDK 用于项目,而将另一个版本的 JDK 用于测试?
- python - 使用单行代码迭代一列以基于逻辑创建另一列
- javascript - 在道具更改之前运行 React componentDidUpdate
- docker - 连接到 ClusterIP,要设置什么防火墙策略?
- asp.net-core - 使用 Nginx 作为反向代理时出现错误 404
- python - Pyinstaller 导入的代码无法加载图片
- sql - 2 选择不同的 WHERE
- typescript - 打字稿:如何声明默认导出也是 UMD 命名空间?
- javascript - 为什么 console.log() 会绕过 addEventListener?