随笔-341  评论-2670  文章-0  trackbacks-0
    完整的转换方法需要intel提供免费翻印下载的那本手册。手册过于精简,因此这里给出的例子用于辅助对手册进行理解。假设读者阅读过intel提供的手册,或其他相关资料。

    x86中大多数指令的16位与32位版本(指的是寄存器而不是地址)的opcode都是相同的。如果将一个字节66H加载指令前的话,使用“与缺省不同的位数”。也就是说,用的操作系统是32位的话,那么使用66H前缀就代表需要对16位的寄存器进行操作。

    下面对指令ADD [EDX*8+EBX+256],EBX进行翻译。x86的32位CPU所用的指令集结构是:Prefix | OpCode | ModR/M | SIB | Displacement | Immediate。

    指令名ADD,第一个参数为dword ptr [EDX*8+EBX+256],第二个参数为EBX。因此应该使用下面的opcode进行翻译(见手册)。
1 01/r                ADD,r/m32,r32

    r/m32代表由寄存器表达式计算而成的指针数值所指向的内存中记载的32位数字,而r32则代表一个32位。这里用的是r/m32和r32而不是r/m16和r/16,因此不需要66H前缀,因此指令的第一个字节是01H

    第二个字节是ModR/M码,这一个字节指的是操作数的形式。我们需要一个r/m32与r/32,因此ModR/M的前两位是10,因为Mod=10下面的R/M位为100的时候可以使用[SIB+disp32]作为参数,也就是[EDX*8+EBX+256]了,此时SIB=EDX*8+EBX,disp32=256=00 01 00 00。这时我们确定了5个位。再看看opcode,有/r标志,也就是说digit那3个位将用来记住第二个参数EBX,EBX的代号是3,也就是011。将Mod=10,digit=011,R/M=100连起来得到第二个字节的值:10011100=9CH

    第三个字节是SIB,用来表达EDX*8+EBX。SIB所表示的是Index*Scale+Base,其中Index=EDX=2=010,Base=EBX=3=011,Scale=8=3=11(这里1,2,4,8分别用0,1,2,3来表示,因此8=3)。将它们按照Scale Index Base的顺序组合起来,得到第三个字节的值:11010011=D3H

    接下来就是disp32了。disp32=256,很容易得出这4个字节分别是00H 01H 00H 00H

    于是这个指令的2进制码就是01 9C D3 00 01 00 00

    接下里看一看Prefix的意思。如果写的指令是ADD [EDX*8+EBX+256],BX的话,BX是16位,因此32位指针指向的也是16位的两个字节,所以使用如下opcode:
1 01/r                ADD,r/m16,r16

    翻译过程与上面一致,但是需要加上66H前缀使之使用它16位版本的指令。因此这个指令的2进制码就是66 01 9C D3 00 01 00 00了。

    如何检查上面的翻译对不对呢?只需要打开vc2008,将汇编代码写在__asm{ }里面,然后下个断点,运行之后用ctrl+alt+D,并在右键菜单打开show code bytes选项即可。这里附上从vc2008的调试其中复制出来的结果:
 1    106:     __asm
 2    107:     {
 3    108:         INT 3
 4 011A7186 CC               int         3    
 5    109:         ADC AL,8
 6 011A7187 14 08            adc         al,8 
 7    110:         ADC AX,8
 8 011A7189 66 83 D0 08      adc         ax,8 
 9    111:         ADC EAX,8
10 011A718D 83 D0 08         adc         eax,8 
11    112:         ADD AL,10
12 011A7190 04 0A            add         al,0Ah 
13    113:         ADD AX,10
14 011A7192 66 83 C0 0A      add         ax,0Ah 
15    114:         ADD EAX,10
16 011A7196 83 C0 0A         add         eax,0Ah 
17    115:         ADD AL,DL
18 011A7199 02 C2            add         al,dl 
19    116:         ADD AX,DX
20 011A719B 66 03 C2         add         ax,dx 
21    117:         ADD EAX,EDX
22 011A719E 03 C2            add         eax,edx 
23    118:         ADD BL,[EDX]
24 011A71A0 02 1A            add         bl,byte ptr [edx] 
25    119:         ADD BX,[EDX*2]
26 011A71A2 66 03 1C 55 00 00 00 00 add         bx,word ptr [edx*2
27    120:         ADD EBX,[EDX*4+8]
28 011A71AA 03 1C 95 08 00 00 00 add         ebx,dword ptr [edx*4+8
29    121:         ADD [EDX*8+EBX],BL
30 011A71B1 00 1C D3         add         byte ptr [ebx+edx*8],bl 
31    122:         ADD [EDX*8+EBX],BX
32 011A71B4 66 01 1C D3      add         word ptr [ebx+edx*8],bx 
33    123:         ADD [EDX*8+EBX+256],BX
34 011A71B8 66 01 9C D3 00 01 00 00 add         word ptr [ebx+edx*8+100h],bx 
35    124:         ADD [EDX*8+EBX+256],EBX
36 011A71C0 01 9C D3 00 01 00 00 add         dword ptr [ebx+edx*8+100h],ebx 
37    125:         BSWAP EAX
38 011A71C7 0F C8            bswap       eax  
39    126:         BSWAP EDI
40 011A71C9 0F CF            bswap       edi  
41    127:     }
posted on 2009-02-16 15:45 陈梓瀚(vczh) 阅读(3275) 评论(5)  编辑 收藏 引用 所属分类: JIT

评论:
# re: JIT脚本引擎:将汇编指令转换为机器码 2009-02-16 16:56 | erfg
那有这方面的相关资料啊?
把参考文献也注明好吗?  回复  更多评论
  
# re: JIT脚本引擎:将汇编指令转换为机器码 2009-02-16 18:33 | 陈梓瀚(vczh)
@erfg
Intel的官方主页上有手册下载,还可以填一份表格然后让他免费将印刷版寄给你。  回复  更多评论
  
# re: JIT脚本引擎:将汇编指令转换为机器码 2009-02-17 09:15 | 梦在天涯
高深啊!  回复  更多评论
  
# re: JIT脚本引擎:将汇编指令转换为机器码 2009-02-17 11:17 | kals
@陈梓瀚(vczh)
好申请吗?  回复  更多评论
  
# re: JIT脚本引擎:将汇编指令转换为机器码 2009-02-17 13:48 | 陈梓瀚(vczh)
@kals
基本有求必应  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理