上节的只知道了可以获取兵种代码,而且内存中很多数据都是与兵种代码相关的,接下来我们就开始研究兵种代码对应的汇编代码,比如说根据兵种代码确定兵种名字。
英杰传中不止一处会显示人物对应的兵种名称,显然这是和兵种代码相关的,显示对应的兵种名称,可以看下面两处的代码,arg_0都是部队战场数据的首地址。
seg002:7978 8B 5E 06 mov bx, [bp+arg_0]
seg002:797B 6B 07 2C imul ax, [bx], 44
seg002:797E 05 16 68 add ax, 6816h
seg002:7981 89 46 F0 mov [bp+var_10], ax
seg002:7984 53 push bx
seg002:7985 9A 6C 93 F2 2C call sub_3628C
seg002:798A 88 46 F7 mov [bp+var_9], al
...
seg002:7B2A 8A 5E F7 mov bl, [bp+var_9]
seg002:7B2D 2A FF sub bh, bh
seg002:7B2F 03 DB add bx, bx
seg002:7B31 FF B7 A2 0A push word ptr [bx+0AA2h] ; "兵种名称"的字符串地址
seg002:7B35 68 D9 33 push 33D9h ; 输出格式"%s"
seg002:7B38 68 26 51 push 5126h
seg002:7B3B 9A 3E 0C F6 1C call sub_1DB9E ; 打印"兵种名称"字符串
seg002:7B40 83 C4 06 add sp, 6
seg002:8D44 8B 76 06 mov si, [bp+arg_0]
seg002:8D4C 6B 3C 2C imul di, [si], 44
seg002:8D4F 81 C7 16 68 add di, 6816h
seg002:8D53 56 push si
seg002:8D54 9A 6C 93 F2 2C call sub_3628C
seg002:8D59 88 46 F7 mov [bp+var_9], al
...
seg002:8E5A 8A 5E F7 mov bl, [bp+var_9]
seg002:8E5D 2A FF sub bh, bh
seg002:8E5F 03 DB add bx, bx
seg002:8E61 FF B7 A2 0A push word ptr [bx+0AA2h] ; "兵种名称"的字符串地址
seg002:8E65 68 3A 34 push 343Ah ; 输出格式"%s"
seg002:8E68 68 26 51 push 5126h
seg002:8E6B 9A 3E 0C F6 1C call sub_1DB9E ; 打印"兵种名称"字符串
seg002:8E70 83 C4 06 add sp, 6
seg002:7B38-seg002:7B3B/seg002:8E6B-seg002:8E6B都是同样的调用显示文字的函数,显示文字的内容是根据seg002:7B31/seg002:8E61的值来确定,这就是接下来的重点,要想知道显示文字的内容,那么我们需要找到DS段的内存偏移地址0AA2处看里面的内存数据是什么?
dseg:0AA2 28 0A
dseg:0AA4 2D 0A
dseg:0AA6 32 0A
dseg:0AA8 37 0A
dseg:0AAA 3C 0A
dseg:0AAC 43 0A
dseg:0AAE 4A 0A
dseg:0AB0 51 0A
dseg:0AB2 58 0A
dseg:0AB4 5F 0A
dseg:0AB6 64 0A
dseg:0AB8 69 0A
dseg:0ABA 6E 0A
dseg:0ABC 75 0A
dseg:0ABE 7E 0A
dseg:0AC0 87 0A
dseg:0AC2 8E 0A
dseg:0AC4 95 0A
dseg:0AC6 9A 0A
光看这处内存数据是看不出有兵种代码对应的兵种名称,需要从原来的代码先研究seg002:7B2A-seg002:7B31/seg002:8E5A-seg002:8E61的代码的意义。
seg002:7B2A/seg002:8E5A取出兵种代码,seg002:7B2F/seg002:8E5F将这个兵种代码自加(乘2),再取出DS:[兵种代码*2 + 0AA2h]的2字节值。接下来的问题就是seg002:7B31/seg002:8E61的word ptr [bx+0AA2h]这句汇编代码的意义。
当兵种代码的值从0到0x13(19)变化,word ptr [bx+0AA2h]的结果分别是0A28, 0A2D, 0A32, 0A37, 0A3C, 0A43, 0A4A, 0A51, 0A58, 0A5F, 0A64, 0A69, 0A6E, 0A75, 0A7E, 0A87, 0A8E, 0A95, 0A9A。
再从这几个值的DS段内存的偏移地址处查看内存数据。
dseg:0A28 B5 75 A7 4C 00 asc_411F8 text "BIG5", '短兵',0 ; DATA XREF: dseg:0AA2↓o
dseg:0A2D AA F8 A7 4C 00 asc_411FD text "BIG5", '長兵',0 ; DATA XREF: dseg:0AA4↓o
dseg:0A32 BE D4 A8 AE 00 asc_41202 text "BIG5", '戰車',0 ; DATA XREF: dseg:0AA6↓o
dseg:0A37 A4 7D A7 4C 00 asc_41207 text "BIG5", '弓兵',0 ; DATA XREF: dseg:0AA8↓o
dseg:0A3C B3 73 A9 B8 A7 4C 00 asc_4120C text "BIG5", '連弩兵',0 ; DATA XREF: dseg:0AAA↓o
dseg:0A43 B5 6F A5 DB A8 AE 00 asc_41213 text "BIG5", '發石車',0 ; DATA XREF: dseg:0AAC↓o
dseg:0A4A BB B4 C3 4D A7 4C 00 asc_4121A text "BIG5", '輕騎兵',0 ; DATA XREF: dseg:0AAE↓o
dseg:0A51 AD AB C3 4D A7 4C 00 asc_41221 text "BIG5", '重騎兵',0 ; DATA XREF: dseg:0AB0↓o
dseg:0A58 AA F1 BD C3 B6 A4 00 asc_41228 text "BIG5", '近衛隊',0 ; DATA XREF: dseg:0AB2↓o
dseg:0A5F A4 73 B8 E9 00 asc_4122F text "BIG5", '山賊',0 ; DATA XREF: dseg:0AB4↓o
dseg:0A64 B4 63 B8 E9 00 asc_41234 text "BIG5", '惡賊',0 ; DATA XREF: dseg:0AB6↓o
dseg:0A69 B8 71 B8 E9 00 asc_41239 text "BIG5", '義賊',0 ; DATA XREF: dseg:0AB8↓o
dseg:0A6E AD 78 BC D6 B6 A4 00 asc_4123E text "BIG5", '軍樂隊',0 ; DATA XREF: dseg:0ABA↓o
dseg:0A75 B2 72 C3 7E A7 4C B9 CE 00 asc_41245 text "BIG5", '猛獸兵團',0 ; DATA XREF: dseg:0ABC↓o
dseg:0A7E AA 5A B3 4E AE 61 B6 A4 00 asc_4124E text "BIG5", '武術家隊',0 ; DATA XREF: dseg:0ABE↓o
dseg:0A87 A7 AF B3 4E AE 76 00 asc_41257 text "BIG5", '妖術師',0 ; DATA XREF: dseg:0AC0↓o
dseg:0A8E B2 A7 A5 C1 B1 DA 00 asc_4125E text "BIG5", '異民族',0 ; DATA XREF: dseg:0AC2↓o
dseg:0A95 A5 C1 B2 B3 00 asc_41265 text "BIG5", '民眾',0 ; DATA XREF: dseg:0AC4↓o
dseg:0A9A B9 42 BF E9 B6 A4 00 asc_4126A text "BIG5", '運輸隊',0 ; DATA XREF: dseg:0AC6↓o
dseg:0AA2 28 0A dw offset asc_411F8 ; "短兵"
dseg:0AA4 2D 0A dw offset asc_411FD ; "長兵"
dseg:0AA6 32 0A dw offset asc_41202 ; "戰車"
dseg:0AA8 37 0A dw offset asc_41207 ; "弓兵"
dseg:0AAA 3C 0A dw offset asc_4120C ; "連弩兵"
dseg:0AAC 43 0A dw offset asc_41213 ; "發石車"
dseg:0AAE 4A 0A dw offset asc_4121A ; "輕騎兵"
dseg:0AB0 51 0A dw offset asc_41221 ; "重騎兵"
dseg:0AB2 58 0A dw offset asc_41228 ; "近衛隊"
dseg:0AB4 5F 0A dw offset asc_4122F ; "山賊"
dseg:0AB6 64 0A dw offset asc_41234 ; "惡賊"
dseg:0AB8 69 0A dw offset asc_41239 ; "義賊"
dseg:0ABA 6E 0A dw offset asc_4123E ; "軍樂隊"
dseg:0ABC 75 0A dw offset asc_41245 ; "猛獸兵團"
dseg:0ABE 7E 0A dw offset asc_4124E ; "武術家隊"
dseg:0AC0 87 0A dw offset asc_41257 ; "妖術師"
dseg:0AC2 8E 0A dw offset asc_4125E ; "異民族"
dseg:0AC4 95 0A dw offset asc_41265 ; "民眾"
dseg:0AC6 9A 0A dw offset asc_4126A ; "運輸隊"
此时便豁然开朗了,DS:0AA2到DS:0AC6保存的是"兵种名称"的字符串地址,而地址对应的内存空间保存的则是兵种名称的BIG5码,每个兵种名称BIG5码的末尾都是00代表字符串的末尾。
如果想直接在MAIN.EXE中修改兵种名称可以用UE等工具搜索兵种名称对应的BIG码,或者直接查找MAIN.EXE文件位置0x0037BC8处是短兵字符串dseg:0A28的位置,MAIN.EXE文件位置0x0037C72对应dseg:0AA2的位置。
很多修改MOD的爱好者都遵循一个原则,不要改动字符串的长度以免出错,然而事实真是如此吗?在修改兵种名称这块,有没有其他更好的办法?