007a8187 - movss [edi+00001f24],xmm0
这是在变身成魔人状态后一定时间后出现的指令,这条指令显示就是保持魔人状态所扣魔力值的指令。
我们先选定007a80a6这条指令,然后点选[More information](更多信息),就会看到附加信息窗:

我们可以看到程序运行到这条指令时每个寄存器的状态,其中EDI=19AE1070(图是第二条指令的,不过无所谓,因为我们这里只是要看一下EDI的值),可以看到指令movss [edi+00001f24],xmm0中[edi+00001f24]的结果就是 [19AE2F94],而这个地址每次切换场景都会发生变化的原因就是EDI的值在变化,这里我们先不管它。
然后我们点选[Extra info]窗中右边的[>]按键,就会弹出浮点寄存器和SSE寄存器的状态,如图。

我们可以看到xmm0=8500.0,这正好就是满魔10000.0减掉变魔人的一格半1500.0后的结果。
上面这些就是如何查看追踪出的指令的每个寄存器的值,因为但看指令本身也难以理解其用途,但是把指令运行时寄存器的值代入到指令中,就很容易明白指令的作用。比如刚才
007a80a6 - movss [edi+00001f24],xmm0
我们把EDI=19AE1070和xmm0=8500.0代入后,就会发现这条指令的含义就是把8500.0这个值写入到[19AE2F94]这个地址,也就是满魔减去变魔人的一格半后的值写到魔力的地址。
还是选定这条指令,点选指令结果窗中[Show disassembler](查看反汇编),出现下图这样的窗口:

我们现在就来讲怎么来修改程序来达到变魔人不扣魔力的效果,修改的方法有很多很多,当然最简单的方法就是直接把007a80a6 - movss [edi+00001f24],xmm0这条指令用nop指令替换掉,也就是把原指令f3 0f 11 87 24 1f 00 00的8个字节全部用90替换。也就是禁止把程序把变魔人时消耗一格半魔后的结果写回内存。
这样改就要改很多字节(特别是我自己写SSG的时候),而且如果是x87浮点指令,读写指令还带栈操作的,单nop一条还会造成栈错位,所以我们应该还有更合理的方法。我们看007a80a6这条指令前面的几条指令:
7a8074 call edx //不知道调用哪里的子程序
7a8076 test al,al //测试al是否为零,因为从这里一直到7a80a6,都没有看到重新对al赋值的指令,而刚才我们看7a80a6这条指令的每个寄存器状态时看到,EAX=08DEC334,所以这里al=34,不=0
7a8078 je 007a8215 //上面test的结果=0则跳转,显然结果不为零,所以这里不会跳转,而是继续下条指令
7a807e cmp byte ptr [edi+00001f2d],00 //比较[edi+00001f2d]这里的一字节结果和00的大小,因为从这里到 7a80a6之前也没有给edi重新赋值的指令,所以这里的edi同样是=19AE1070,所以我们可以知道edi+00001f2d这里是什么值,把这个值加入地址列表(注意是1字节,因为指令上含有byte ptr),我们可以看到,普通状态时这个值为0,魔人状态时这个值为1,显然这条指令是在判定当前是否是魔人状态。
7a8085 jne 007a80e7 //如果上面比较结果不为零则跳转,显示这里是判定如果已经魔人状态了那么就不再重复扣变魔人时的一格半魔,如果是普通状态则不跳转,也就是要继续下面扣一格半魔力的指令。
7a8087 cmp byte ptr [edi+0000216c],01 //因为edi还是没有变化,所以我们还是可以知道这里的值,添加计算后的结果到地址列表,可以看到如果是普通装的话值为0,如果是无限魔力装的话这里就是01。当然因为我们之前要搜索魔力的地址,所以这里肯定是普通装也就是=0,因为这条指令是在比较和01的大小,所以我们这里手动把地址列表的结果改成1,会发现这里我们变成无限魔力装的效果了,这样也可以证实这个字节的作用。