x86 装配问题 - 任何人都可以确定下面发生了啥吗?
Posted
技术标签:
【中文标题】x86 装配问题 - 任何人都可以确定下面发生了啥吗?【英文标题】:x86 Assembly Question - Can anyone determine what is happening below?x86 装配问题 - 任何人都可以确定下面发生了什么吗? 【发布时间】:2021-03-14 10:02:21 【问题描述】:我为我玩的一个 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]
操作数)。像这样不太容易理解。
【参考方案1】:
使用绝对地址0
很奇怪,大概有某种重定位来修复这些地址。但是你的反汇编并没有显示出来。如果它是标准的对象文件格式,您可以使用objdump -dr -Mintel foo.o
来包含重定位元数据。
但无论如何,它使用fnsave
转储 x87 FPU 状态。
可能后面的地址具有不同的重定位修复元数据,即使它们在您转储的代码中都是[0]
。 fsave 区域的开头得到FPUControlWord
,从该位置到fld
/ fstp
4 个字节是没有意义的。
几乎可以肯定fld dword ptr [0]
/fstp dword ptr [0]
正在两个其他位置之间复制float
值,而不是加载/存储 FPU 控制和状态字,作为 4 字节单精度 float
。 (如果数据表示 NaN,可能会修改数据。)因此我们必须得出结论,每个[0]
寻址模式实际上可以是任何地址,无论是否在 fsave 区域内。 (fsave 区域中的浮点数将是 80 位 x87 格式,而不是 32 位(dword)单精度,因此fld dword
不太可能对它们进行操作。)
带有 0x33 .. 0x38 的 cmp
可能正在查看 x87 状态字的一个字节,也许是为了找出保存区域中的哪个插槽是当前的栈顶?不,状态字位不在字节的底部。但是比较结果(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]
地址,但似乎很明显,重定位可能会将该地址指向程序数据的其他部分,而不仅仅是这个补丁自己的私有存储。
【讨论】:
是的,正在进行一些搬迁。我刚刚用一些值更新了原始帖子,但我不知道这些值的含义。以上是关于x86 装配问题 - 任何人都可以确定下面发生了啥吗?的主要内容,如果未能解决你的问题,请参考以下文章