爱技术

 找回密码
 注册会员

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 3943|回复: 11
收起左侧

【专题文章】语言包的结构和IDC文件的使用

[复制链接]
发表于 2005-8-10 00:00:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册会员 微信登录

x
[B]语言包的结构和IDC文件的使用[/B]
作者:coollang

在家里过年的时候收到张斌的Email,问起语言包的结构,那是因为手边没有资料,而且上网很不方便,只能作罢。我是11号才开始上班的,开始一直没有时间,所以积在周末把它发上来。

这里主要说一下语言包的结构,同时还有IDC文件的使用。IDC是IDA支持的一种类C的脚本语言,我以前也没有用过,恰好在国外的网站上发现了几个例子,于是发上来,给大家提供参考。这确实是很实用的一种东西。

西门子的语言包里面可能包含多个语言,而字串是压缩过的,其主要是对高频词组进行了压缩。同时对字串采用索引存储,即建立一个索引表。索引表中存放一个字串组(8个字串)的地址,字串组内部是一个字串链表。通过字串ID可以得到字串所在的字串组在索引表中的位置,然后根据索引找到字串组的地址。在字串组的内部通过顺序的查找链表来找到压缩后的字串。需要注意的是从压缩后的字串解压缩后的得到的并不是真正的字符串(GB或UNICODE),而是Siemens的内部格式的东西,还要作相应的转换才能得到Unicode字串。我写过的Sie2Uni就是作这个用的。西门子的这种存储方式兼顾了效率与空间的平衡,是一种不错的做法。细节如下,更多可参照Siemens Language Editor和Flash程序。
[upload=jpg]UploadFile/200422118592389018.jpg[/upload]

这个例子Lang_unpack_data.idc是一个解包siemens语言包的IDC文件,可以在IDA中生成对应的字串以及在Names window中生成标示(通过内值函数)。具体的语法可以查看IDA的帮助中IDC部分,熟悉C的应该没什么难度。而且可以很容易的转换为C程序。此程序我已经作了相当多的注释,应该很容易看懂。其实这个程序的算法就是Flash中的对应部分,我会把它一并附上。程序如下(抱歉,对应网站是非英语论坛,我不能得到作者,但是类似的程序我早已独立实现过):
使用方法是在IDA的File->IDC File(或F2),加载相应的IDC文件

  1. #include <idc.idc>

  2. //请根据需要除去对应的注释,其他未列出的可以通过在FuBu中查找Hex格式Byte
  3. //“BBBB0000“,这是语言包的标志,需要注意的是这里的地址是对应16M空间的地址,
  4. //请自行调整。
  5. #define LGP_BASE 0xE6C000   //6688
  6. //#define LGP_BASE 0xB00000   //x618
  7. //#define LGP_BASE 0x7A0000   //M55c
  8. //#define LGP_BASE 0xE00000   //S57c

  9. //解压缩函数,lang->语言ID,ea->字串开始地址 字串的存储格式为BYTE(字串长度,字串内容。。。)
  10. static unpack(lang,ea){
  11. auto lgp_ea,lgp_ea2,uni,o_lginfo,len,pos,s,blen,c,dec,ea1;

  12. lgp_ea=LGP_BASE;

  13. o_lginfo=Word(lgp_ea+0xA);  //语言Info表Offset

  14. len=Byte(ea);     //取得字串长度(并不是真实的长度,而是压缩后的长度)

  15. //以下几行是在IDA中处理对应BYTE的格式
  16. for (pos=ea;pos<ea+len;pos++)MakeUnkn(pos,1);
  17. if(len<=4)
  18.   MakeArray(ea,len);
  19. else{
  20.   MakeArray(ea,4);
  21.   MakeArray(ea+4,len-4);
  22. }

  23. lgp_ea=LGP_BASE+o_lginfo;  //语言Info表的Base地址
  24. lgp_ea2=lgp_ea+14*lang;   //对应语言的的Info表地址,每个Info表的大小是14个Byte

  25. //解压缩字串
  26. s="";uni=0;      //s为最终字串
  27. for(pos=1;pos<len;pos++){  
  28.   c=Byte(ea+pos);    //取得压缩后的Byte
  29.   blen=0;      //压缩前的Byte长度
  30.   dec=0;
  31.   while(c>=Word(lgp_ea2+2+blen*4)){ //取得压缩后Byte所对应的压缩表中的信息
  32.    dec=Word(lgp_ea2+2+blen*4);  //取得压缩表中的对应地址。压缩过程一般最多压缩4字符。压缩表分别是
  33.            //四字符压缩表,三字符压缩表,二、一字符压缩表
  34.    blen++;
  35.    if(blen==4) break;
  36.   }
  37.   
  38.   ea1=LGP_BASE+Word(lgp_ea2+4*blen)+(c-dec)*(blen+1); //取得压缩Byte所对应的解压缩后的字符(1到4个字符)地址
  39.   //以下输出压缩Byte所对应的解压缩后字符,并对特殊字符作相应的转换
  40.   do{
  41.    c=Byte(ea1);
  42.    if((c>=0x20 && c<0x80 && uni==0) || (c>0x10 && c<0x80 && uni>0)){
  43.     if (c+uni<0x1B0)
  44.      s=s+form("%c",c+uni);
  45.     else
  46.      s=s+form("%c",c+uni+0x30);

  47.    } else {
  48.     s=s+form("<%02X>",c);  //先用<>输出特殊字符的BYTE值
  49.     //以下或者是一些前导字符或者是特殊字符,需要作相应的转换
  50.     if (c==0x9B) uni=0x170;  
  51.     if (c==0x96) uni=0x80;
  52.     if (c==0x97) uni=0x100;
  53.     if (c==0x95 || c==0x91) uni=0x0;
  54.     if (c==0x8a || c==0x0d) s=s+"\n";
  55.    }
  56.    ea1++;
  57.    blen--;
  58.   } while(blen>=0);
  59. }

  60. MakeRptCmt(ea,s);    //在标示名字的地址出输出对应的字符
  61. if (lang>0) MakeName(ea,""); //非英语语言输出空(可能考虑到Unicode字符问题)
  62. }

  63. //在字串组内查找次序为n的字串的地址
  64. static shift(ea,n){
  65. while(n--){
  66.   ea=ea+Byte(ea);
  67. }
  68. return ea;
  69. }

  70. static main(void){
  71. auto nLangs,lang_id,lll,ref,ea1,ceil,mnem,op1,op2,msg_id,idx1,idx2,ea2,eap,i,sadd,npara,o_msgidx,mea,v,max_id;

  72. npara =Word(LGP_BASE+6);    //语言包的Page数量(C166不能跨Page边界)
  73. o_msgidx=Word(LGP_BASE+0x12);   //字串组索引表的Offset,字串索引表以Word为单位,存储字串组的Page内Offset。
  74. max_id=Word(LGP_BASE+0x2a);    //最大字串ID
  75. nLangs=Word(LGP_BASE+0xE);    //语言数量(英文、简体中文…)


  76. for (msg_id=0;msg_id<=max_id;msg_id++){

  77.   for (lang_id=0;lang_id<nLangs;lang_id++){
  78.    eap=LGP_BASE+0x3c;    //ID范围->Page表
  79.    sadd=0;       //Page
  80.    for(i=1;i<npara;i++){   //查找字串的所在Page
  81.     if((msg_id*nLangs+lang_id)<Word(eap)) break;
  82.     eap=eap+2;
  83.     sadd++;
  84.    }

  85.    v=(msg_id*nLangs+lang_id)/8; //字串组索引表的ID,每8个一组。每组内用链表存储
  86.    idx2=(msg_id*nLangs+lang_id)%8; //组内次序
  87.       mea=Word(LGP_BASE+o_msgidx+v*2)+LGP_BASE+sadd*0x4000; //计算字串内容开始地址,基地址+Page地址+OffsetInPage,
  88.                     //最后一项是从字串组索引表中查询得到
  89.    mea=shift(mea,idx2);   //找到对应字串的地址
  90.    unpack(lang_id,mea);   //解压缩相应字串。因为语言包对字符进行了压缩,对高频词组进行了压缩。
  91.    if (lang_id==0)
  92.     //如果需要10进制的ID,可以在下面修改。
  93.     if(!MakeName(mea,form("Lgp_str_%03X",msg_id)))return; //如果是英文(默认是语言0),则输出Name。
  94.    Jump(mea);
  95.   }
  96. }
  97. }
复制代码

  1. //在6688Flash中的实现
  2. 0xE0:3EFA ; ★★★★★★★★ S U B R O U T I N E  ★★★★★★★★★★★★★★★★★★★
  3. 0xE0:3EFA GetStringByID:                        ; CODE XREF: 0xC7:88B6P
  4. 0xE0:3EFA                                       ; sub_E1FCE8+30P
  5. 0xE0:3EFA                 push    r6
  6. 0xE0:3EFC                 mov     r6, #0FE04h
  7. 0xE0:3F00                 extp    #37h, #1 ; '7'
  8. 0xE0:3F04                 mov     r10, word_DCEF2 ; R10 -> Cur LgInfo Table
  9. 0xE0:3F08                 extp    #37h, #1 ; '7'
  10. 0xE0:3F0C                 mov     r2, word_DCEF8 ; R2 -> CurrentLgID
  11. 0xE0:3F10                 scxt    DPP0, #39Bh
  12. 0xE0:3F14                 ; assume dpp0: 39Bh (page 0xE6C000)
  13. 0xE0:3F14                 push    DPP2
  14. 0xE0:3F16                 mov     r1, #0Eh      ; Language Count
  15. 0xE0:3F18                 mov     r3, [r1]
  16. 0xE0:3F1A                 mulu    r12, r3
  17. 0xE0:3F1C                 mov     r12, MDL
  18. 0xE0:3F20                 add     r12, r2
  19. 0xE0:3F22                 or      r13, #8000h
  20. 0xE0:3F26                 mov     r15, #39Bh
  21. 0xE0:3F2A                 mov     r1, #6        ; Paragraphs Count
  22. 0xE0:3F2C                 mov     r2, [r1]
  23. 0xE0:3F2E                 sub     r2, #1
  24. 0xE0:3F30                 mov     r3, #3Ch ; '<' ; Current paragraphs
  25. 0xE0:3F34 loc_E03F34:                           ; CODE XREF: GetStringByID+48j
  26. 0xE0:3F34                 mov     r5, [r3]      ; 找到对应的段
  27. 0xE0:3F36                 cmpd1   r2, #0
  28. 0xE0:3F38                 jmpr    cc_Z, loc_E03F44
  29. 0xE0:3F3A                 cmp     r12, r5       ; R12 -> ID*LgCount + LgID
  30. 0xE0:3F3C                 jmpr    cc_C, loc_E03F44
  31. 0xE0:3F3E                 add     r15, #1       ; R15 -> Current Page
  32. 0xE0:3F40                 add     r3, #2
  33. 0xE0:3F42                 jmpr    cc_UC, loc_E03F34 ; 找到对应的段
  34. 0xE0:3F44 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  35. 0xE0:3F44 loc_E03F44:                           ; CODE XREF: GetStringByID+3Ej
  36. 0xE0:3F44                                       ; GetStringByID+42j
  37. 0xE0:3F44                 mov     [r6], r15
  38. 0xE0:3F46                 mov     r1, r12
  39. 0xE0:3F48                 shr     r1, #3
  40. 0xE0:3F4A                 shl     r1, #1
  41. 0xE0:3F4C                 mov     r2, #12h      ; Offset of All MsgID Offset
  42. 0xE0:3F50                 add     r1, [r2]
  43. 0xE0:3F52                 mov     r4, [r1]
  44. 0xE0:3F54                 or      r4, #8000h
  45. 0xE0:3F58                 mov     r5, r12
  46. 0xE0:3F5A                 and     r5, #7
  47. 0xE0:3F5C                 jmpr    cc_UC, loc_E03F64
  48. 0xE0:3F5E ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  49. 0xE0:3F5E loc_E03F5E:                           ; CODE XREF: GetStringByID+6Cj
  50. 0xE0:3F5E                 movb    rl1, [r4]     ; 遍历链表,查找String位置
  51. 0xE0:3F60                 movbz   r1, rl1
  52. 0xE0:3F62                 add     r4, r1
  53. 0xE0:3F64 loc_E03F64:                           ; CODE XREF: GetStringByID+62j
  54. 0xE0:3F64                 cmpd1   r5, #0
  55. 0xE0:3F66                 jmpr    cc_NZ, loc_E03F5E ; 遍历链表,查找String位置
  56. 0xE0:3F68                 movb    rl3, [r4+]    ; RL3 -> Length,FirstByte
  57. 0xE0:3F6A                 mov     r11, [r10]    ; R11 -> InfoTable
  58. 0xE0:3F6C                 calls   0E0h, UnpackLngString
  59. 0xE0:3F70                 mov     [r6], r14
  60. 0xE0:3F72                 nop
  61. 0xE0:3F74                 movb    [r13], word_FF1C
  62. 0xE0:3F78                 pop     DPP2
  63. 0xE0:3F7A                 pop     DPP0
  64. 0xE0:3F7C                 ; assume dpp0: 0FFFFh (page 0x3FFFC000)
  65. 0xE0:3F7C                 pop     r6
  66. 0xE0:3F7E                 rets

  67. 0xE0:3F80 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  68. 0xE0:3F80 loc_E03F80:                           ; CODE XREF: UnpackLngString+4j
  69. 0xE0:3F80                 movb    rl2, [r4+]
  70. 0xE0:3F82                 movbz   r2, rl2
  71. 0xE0:3F84                 mov     [r6], r14
  72. 0xE0:3F86                 mov     r1, [r10+2]
  73. 0xE0:3F8A                 cmp     r2, r1
  74. 0xE0:3F8C                 jmpr    cc_NC, loc_E03F94
  75. 0xE0:3F8E                 mov     r5, r11
  76. 0xE0:3F90                 add     r5, r2
  77. 0xE0:3F92                 jmpr    cc_UC, loc_E03FE8
  78. 0xE0:3F94 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  79. 0xE0:3F94 loc_E03F94:                           ; CODE XREF: 0xE0:3F8Cj
  80. 0xE0:3F94                 mov     r1, [r10+6]
  81. 0xE0:3F98                 cmp     r2, r1
  82. 0xE0:3F9A                 jmpr    cc_NC, loc_E03FAE
  83. 0xE0:3F9C                 mov     r5, r2
  84. 0xE0:3F9E                 mov     r1, [r10+2]
  85. 0xE0:3FA2                 sub     r5, r1
  86. 0xE0:3FA4                 shl     r5, #1
  87. 0xE0:3FA6                 mov     r1, [r10+4]
  88. 0xE0:3FAA                 add     r5, r1
  89. 0xE0:3FAC                 jmpr    cc_UC, loc_E03FE4
  90. 0xE0:3FAE ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  91. 0xE0:3FAE loc_E03FAE:                           ; CODE XREF: 0xE0:3F9Aj
  92. 0xE0:3FAE                 mov     r1, [r10+0Ah]
  93. 0xE0:3FB2                 cmp     r2, r1
  94. 0xE0:3FB4                 jmpr    cc_NC, loc_E03FCC
  95. 0xE0:3FB6                 mov     r5, r2
  96. 0xE0:3FB8                 mov     r1, [r10+6]
  97. 0xE0:3FBC                 sub     r5, r1
  98. 0xE0:3FBE                 mov     r1, r5
  99. 0xE0:3FC0                 shl     r5, #1
  100. 0xE0:3FC2                 add     r5, r1
  101. 0xE0:3FC4                 mov     r1, [r10+8]
  102. 0xE0:3FC8                 add     r5, r1
  103. 0xE0:3FCA                 jmpr    cc_UC, loc_E03FE0
  104. 0xE0:3FCC ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  105. 0xE0:3FCC loc_E03FCC:                           ; CODE XREF: 0xE0:3FB4j
  106. 0xE0:3FCC                 mov     r5, r2
  107. 0xE0:3FCE                 mov     r1, [r10+0Ah]
  108. 0xE0:3FD2                 sub     r5, r1
  109. 0xE0:3FD4                 shl     r5, #2
  110. 0xE0:3FD6                 mov     r1, [r10+0Ch]
  111. 0xE0:3FDA                 add     r5, r1
  112. 0xE0:3FDC                 movb    [r13+], [r5]
  113. 0xE0:3FDE                 add     r5, #1
  114. 0xE0:3FE0 loc_E03FE0:                           ; CODE XREF: 0xE0:3FCAj
  115. 0xE0:3FE0                 movb    [r13+], [r5]
  116. 0xE0:3FE2                 add     r5, #1
  117. 0xE0:3FE4 loc_E03FE4:                           ; CODE XREF: 0xE0:3FACj
  118. 0xE0:3FE4                 movb    [r13+], [r5]
  119. 0xE0:3FE6                 add     r5, #1
  120. 0xE0:3FE8 loc_E03FE8:                           ; CODE XREF: 0xE0:3F92j
  121. 0xE0:3FE8                 movb    [r13+], [r5]
  122. 0xE0:3FEA ; ★★★★★★★★ S U B R O U T I N E  ★★★★★★★★★★★★★★★★★★★
  123. 0xE0:3FEA UnpackLngString:                      ; CODE XREF: GetStringByID+72P
  124. 0xE0:3FEA                 mov     [r6], r15
  125. 0xE0:3FEC                 subb    rl3, #1
  126. 0xE0:3FEE                 jmpr    cc_NZ, loc_E03F80
  127. 0xE0:3FF0                 rets
  128. 0xE0:3FF0 ; End of function UnpackLngString
复制代码

附件:
Lang_unpack_data.idc[upload=rar]viewfile.asp?ID=9889[/upload]













[此贴子已经被作者于2004-2-21 19:00:18编辑过]
发表于 2005-8-10 00:01:00 | 显示全部楼层
大家风范!!!!!!
老大,就是老大!!!!!!!!!!!!!!!!!111
发表于 2005-8-10 00:03:00 | 显示全部楼层
签到,慢慢研究
发表于 2005-8-10 00:04:00 | 显示全部楼层
收下先
发表于 2005-8-10 00:05:00 | 显示全部楼层
签到。
发表于 2005-8-10 00:06:00 | 显示全部楼层
不愧大师!
很怀念SL456688i,他现在还好吗?
发表于 2005-8-10 00:07:00 | 显示全部楼层
触角越来越广了,小8事业发展中……
发表于 2005-8-10 00:08:00 | 显示全部楼层
收到,我也要慢慢研究!!!
发表于 2005-8-10 00:09:00 | 显示全部楼层

收到
多谢狼大
发表于 2005-8-10 00:11:00 | 显示全部楼层
狼大就是狼大!!
发表于 2006-3-29 22:46:55 | 显示全部楼层

厉害

!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2007-4-2 09:21:53 | 显示全部楼层
狼大的帖子那是必定要顶的!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员 微信登录

本版积分规则

小黑屋|Archiver|手机版|爱技术 ( 沪ICP备08115260号-3 )

GMT+8, 2024-5-20 01:18

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表