To 小行者:很遗憾,我没有学过编译原理,只学过汇编语言。推荐参考书目:《IBM PC汇编语言程序设计》沈美明 温冬婵 编著,清华大学出版社,1991年6月第一版。
最近我发的帖子基本由浅到深,总结了上个月做修改器的经验与方法。如果能看懂博雅张生关于增加策略伤害系数种类的帖子,便可以跟着学习下去。
另外,一句话中加上太多空格,会让人看的很吃力。
exe修改举例——破浪履补丁
将使用补丁前后的exe文件加以比较,可以看出该补丁更改了8个地方,分别是:
自0x3EBCF起0xEF字节
自0x375DD起0x0A字节
自0x398FE起0x1C字节
自0x3B09C起0x13字节
自0x40213起0x0A字节
自0x50926起0x0F字节
自0x50B51起0x0F字节
自0x8AA98起0x08字节
下面分别加以介绍:
曹操传中关于地形的两个函数,原本功能分别为:
函数名 ecx ebp+08 返回值
:0043F7CF 武将战场属性地址 地形编号 al,武将在该地形上消耗行动力(考虑宝物效果)
:0043F84D 武将战场属性地址 al,武将在当前地形上的攻防加成
该补丁将这两个函数合并为一个函数,其功能为:
函数名 ecx ebp+08 返回值
:0043F7CF 武将战场属性地址 地形编号 al,武将在该地形上消耗行动力(考虑宝物效果)
dl,武将在当前地形上的攻防加成(考虑宝物效果)
具体介绍新函数的代码:
:0043F7CF 55 push ebp
:0043F7D0 8BEC mov ebp, esp //函数头,保存ebp和esp值
:0043F7D2 83EC14 sub esp, 00000014 //函数中可用内存为5个dword,地址ebp-04,ebp-08,...,ebp-14
:0043F7D5 894DEC mov dword ptr [ebp-14], ecx//保存武将战场属性地址
:0043F7D8 E893BCFFFF call 0043B470 //获取武将职业于al
:0043F7DD 25FF000000 and eax, 000000FF
:0043F7E2 8945FC mov dword ptr [ebp-04], eax//保存武将职业
:0043F7E5 83F81B cmp eax, 0000001B //检测武将职业是否超过最大职业数
:0043F7E8 7C0A jl 0043F7F4 //未超过,继续执行
:0043F7EA 0CFF or al, FF
:0043F7EC 80E200 and dl, 00
:0043F7EF E98C000000 jmp 0043F880 //超过,此职业无效,设定行动消耗为FF,攻防加成为0,结束函数。
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0043F7E8©
|
:0043F7F4 8B4DEC mov ecx, dword ptr [ebp-14]//读取武将战场属性地址
:0043F7F7 E8643BFCFF call 00403360
:0043F7FC 50 push eax
:0043F7FD E88F61FFFF call 00435991 //获得武将当前所在地形编号
:0043F802 83C404 add esp, 00000004 //压栈参数出栈
:0043F805 25FF000000 and eax, 000000FF
:0043F80A 8945F0 mov dword ptr [ebp-10], eax//保存武将当前所在地形编号
:0043F80D 50 push eax
:0043F80E 8B4DFC mov ecx, dword ptr [ebp-04]//读取武将职业
:0043F811 6BC93C imul ecx, 0000003C
:0043F814 81C1E0E44A00 add ecx, 004AE4E0
:0043F81A E871380000 call 00443090 //获得该职业该地形的攻防加成
:0043F81F 8845F4 mov byte ptr [ebp-0C], al //保存攻防加成
:0043F822 8B4508 mov eax, dword ptr [ebp+08]//读取参数,地形编号
:0043F825 25FF000000 and eax, 000000FF
:0043F82A 50 push eax
:0043F82B E840380000 call 00443070 //获得该职业该地形的行动力消耗
:0043F830 8845F8 mov byte ptr [ebp-08], al //保存行动力消耗
:0043F833 6A22 push 00000022 //恶路移动(凌波微步)的特殊效果编号
:0043F835 8B55EC mov edx, dword ptr [ebp-14]
:0043F838 8B0A mov ecx, dword ptr [edx] //获得该武将data编号
:0043F83A 6BC948 imul ecx, 00000048
:0043F83D 81C1681B4A00 add ecx, 004A1B68 //计算武将基本属性地址
:0043F843 E8C181FCFF call 00407A09 //检测武将是否装备特殊效果编号为0x22的道具(返回值于eax,1是0否)
:0043F848 85C0 test eax, eax
:0043F84A 742E je 0043F87A //没有装备,则结束函数
:0043F84C 8B4508 mov eax, dword ptr [ebp+08]//读取参数,地形编号
:0043F84F 3C09 cmp al, 09 //浅滩
:0043F851 7408 je 0043F85B
:0043F853 3C0A cmp al, 0A //沼泽
:0043F855 7404 je 0043F85B
:0043F857 3C0D cmp al, 0D //大河
:0043F859 7505 jne 0043F860
* Referenced by a (U)nconditional or ©onditional Jump at Addresses:
|:0043F851©, :0043F855©
|
:0043F85B B001 mov al, 01 //行动力消耗为1
:0043F85D 8945F8 mov dword ptr [ebp-08], eax//保存行动力消耗
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0043F859©
|
:0043F860 8B45F0 mov eax, dword ptr [ebp-10]//读取当前所在地形编号
:0043F863 3C09 cmp al, 09 //浅滩
:0043F865 7504 jne 0043F86B
:0043F867 B00B mov al, 0B
:0043F869 EB0C jmp 0043F877
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0043F865©
|
:0043F86B 3C0A cmp al, 0A //沼泽
:0043F86D 7502 jne 0043F871
:0043F86F EB06 jmp 0043F877
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0043F86D©
|
:0043F871 3C0D cmp al, 0D //大河
:0043F873 7505 jne 0043F87A
:0043F875 B00C mov al, 0C
* Referenced by a (U)nconditional or ©onditional Jump at Addresses:
|:0043F869(U), :0043F86F(U)
|
:0043F877 8945F4 mov dword ptr [ebp-0C], eax//保存攻防加成
* Referenced by a (U)nconditional or ©onditional Jump at Addresses:
|:0043F84A©, :0043F873©
|
:0043F87A 8B45F8 mov eax, dword ptr [ebp-08]//将移动力消耗放在eax,只有低8位有效
:0043F87D 8B55F4 mov edx, dword ptr [ebp-0C]//将攻防加成放在edx,只有低8位有效
* Referenced by a (U)nconditional or ©onditional Jump at Address:
|:0043F7EF(U)
|
:0043F880 8BE5 mov esp, ebp //函数结束,恢复入口的ebp和esp值
:0043F882 5D pop ebp
:0043F883 C20400 ret 0004 //返回并使参数出栈
因为此函数的合并,调用部分也需要做相应修改。
原本调用:0043F7CF的地方,由于入口、出口均未发生变化,故无需修改。
原本调用:0043F84D的地方,调用函数地址、返回值发生变化,需要修改。这种情况共六处:
:004381DD , :0043A4FE , :0043A510 , :0043BC9C , :0043BCA7 , :00440E13
原调用方法:
:004381DD E86B760000 call 0043F84D
:004381E2 25FF000000 and eax, 000000FF
更改为:
:004381DD E8ED750000 call 0043F7CF
:004381E2 33C0 xor eax, eax
:004381E4 0AC2 or al, dl
:004381E6 90 nop
在有限的空间内辗转腾挪,不但把edx的数据传入eax,还把eax的高三字节清零。:0043A4FE,:0043A510,:00440E13的修改方法类似。
原调用方法:
:0043BC9C E8AC3B0000 call 0043F84D
:0043BCA1 8845F4 mov byte ptr [ebp-0C], al
更改为:
:0043BC9C E82E3B0000 call 0043F7CF
:0043BCA1 8855F4 mov byte ptr [ebp-0C], dl
这个更改一目了然,不需解释。:0043BCA7的修改方法与之类似。
这样便实现了破浪履的移动力和攻防加成功能,下面来看看绘图功能。
去腿部分:
:00451523 8B4D18 mov ecx, dword ptr [ebp+18]//读取武将战场属性编号
:00451526 81E1FF000000 and ecx, 000000FF
:0045152C 6BC924 imul ecx, 00000024
:0045152F 81C1502C4B00 add ecx, 004B2C50 //计算武将战场属性地址
:00451535 E8E6CDFEFF call 0043E320 //获得武将的朝向
更改为:
:00451523 8B4D18 mov ecx, dword ptr [ebp+18]//读取武将战场属性编号
:00451526 E85BE3FEFF call 0043F886 //自定义函数
:0045152B 85C0 test eax, eax //检测是否装备破浪履
:0045152D 0F85E8010000 jne 0045171B //如装备则不执行去腿操作
:00451533 90 nop
:00451534 90 nop
:00451535 E8E6CDFEFF call 0043E320 //获得武将的朝向
绘船部分与之类似:
:0045174E 8B4D18 mov ecx, dword ptr [ebp+18]//读取武将战场属性编号
:00451751 81E1FF000000 and ecx, 000000FF
:00451757 6BC924 imul ecx, 00000024
:0045175A 81C1502C4B00 add ecx, 004B2C50 //计算武将战场属性地址
:00451760 E8BBCBFEFF call 0043E320 //获得武将的朝向
更改为:
:0045174E 8B4D18 mov ecx, dword ptr [ebp+18]//读取武将战场属性编号
:00451751 E830E1FEFF call 0043F886 //自定义函数
:00451756 85C0 test eax, eax //检测是否装备破浪履
:00451758 0F8590010000 jne 004518EE //如装备则不执行绘船操作
:0045175E 90 nop
:0045175F 90 nop
:00451760 E8BBCBFEFF call 0043E320 //获得武将的朝向
由这两处调用,可以定义出函数:0043F886的输入输出如下:
函数名 ecx 返回值
:0043F886 武将战场属性编号 eax,是否装备破浪履(1是0否)
ecx,武将战场属性地址(提供下面获得朝向的函数0043E320使用)
实现如下:
:0043F886 55 push ebp
:0043F887 8BEC mov ebp, esp
:0043F889 51 push ecx //等效于sub esp, 00000004 表示函数中可用内存为1个dword,地址ebp-04
:0043F88A 81E1FF000000 and ecx, 000000FF
:0043F890 6BC924 imul ecx, 00000024
:0043F893 81C1502C4B00 add ecx, 004B2C50 //计算武将战场属性地址
:0043F899 8BD1 mov edx, ecx
:0043F89B 894DFC mov dword ptr [ebp-04], ecx//保存武将战场属性地址
:0043F89E 6A22 push 00000022 //恶路移动(凌波微步)的特殊效果编号
:0043F8A0 8B0A mov ecx, dword ptr [edx] //获得武将data编号
:0043F8A2 6BC948 imul ecx, 00000048
:0043F8A5 81C1681B4A00 add ecx, 004A1B68 //计算武将基本属性地址
:0043F8AB E85981FCFF call 00407A09 //检测武将是否装备特殊效果编号为0x22的道具(返回值于eax,1是0否)
:0043F8B0 8B4DFC mov ecx, dword ptr [ebp-04]//将武将战场属性地址放于ecx
:0043F8B3 8BE5 mov esp, ebp
:0043F8B5 5D pop ebp
:0043F8B6 C3 ret
最后,修改0x8AA98处的宝物效果说明,将“恶路移动”改为“凌波微步”。
|