欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

七 Bit filed(二)

七 Bit filed(二)

现在我们切实的学习这些fields的作用.
    我们从使用REG field的单字节指令开始,格式是5:3,高5位是CODE field,低3位是register field.
    这里有几个问题:
    1.为什么我们从REG field开始呢?
REG field在寻址中使用最多,学习它我们可以更深入的学习指令的地址部分.Reg field在mod r/m和sib中被用到.Mod r/m和sib在绝大多数OpCode中是用来确定指令的地址部分的,它们总共有6个域,其中的4个用来存放寄存器的值.
    2.为什么从CODE:REG 5 : 3格式的单字节OpCode开始?
首先这是使用了bit field的最简单的格式,如果习惯了使用二进制和十六进制,我们可以更容易处理2 : 3 : 3的格式.另外,在5 : 3格式中,只有一个操作数,这使得编码和解码更加容易.
    现在我们运行regfield.exe(在附件中).它一共有三个Tab页.
    第一个“Reference”.你可以通过它生成单字节OpCode,通过二进制和十六进制显示.还有一些用来选择指令和操作数的按钮.
    这里有一些小技巧:依次单击第一列按钮,你可以看到他们产生的CODE域:
    INC  - 01000
    DEC  - 01001
    PUSH - 01010
    POP  - 01011
    -----------
    XCHG - 10010
除了XCHG - 10010,其他的是从01000至01011按1递增的.
    而寄存器操作数也是同样的.
    EAX  - 000
    ECX  - 001
    EDX  - 010
    EBX  - 011
    ESP  - 100
    EBP  - 101
    ESI  - 110
    EDI  - 111
    第一个Tab页实际上是一个最简易的汇编器,虽然它只能翻译5种类型的指令,且只能使用全寄存器.而剩下的两个Tab也是类似的,"tell mnemonic"页是一个饭汇编器,而"tell opcode"则是汇编器.
    在tell mnemonic页中可以看到一些类似“Reference”页中的按钮.你可以按动这些按钮,如果你所按按钮代表的OpCode和页面上以二进制或十六进制显示的是一致的,那么你可以继续下一个,否则重试.
    一些小提示:如果第一个十六进制数是
    4   - inc/dec , reg
    5   - push/pop, reg
    9   - xchg eax, reg
    如果同一个数字对应两个OpCode,那么就要看第二位十六进制数大于等于8.
    最后一个Tab页则是要我们解码或者说是汇编助记符(mnemonics).依照界面的提示:
    第二行就是需要被汇编的汇编指令,如XCHG EAX,EDX;
    你可以按下第三行的相应按钮使其正好是XCHG EAX,EDX的OpCode 10010 010;
    或者是在第四行的黑色文本框中输入十六进制数92;
    然后单击“TEST”按钮,如果你的输入是正确的就可以继续下一个,否则重试.(但是第三行的按钮似乎不怎么管用)
    多多联系直到你可以在5分钟之类得到100个正确的回答并且没有任何错误提示^_^.
    inc dec push pop xchg eax,reg这些都是单字节指令.但并不是只有这些指令才是单字节指令.例如
    00001111:11001 reg(bswap reg)
    第一个字节只是告诉处理器接下来的OpCode属于“新”的指令集.在这条指令中有用的部分也只用一个字节,并且属于5 : 3的格式,那么最后的三位就是Reg field了.如
    bswap eax = 0FC8  (11001 000)
    bswap ecx = 0FC9  (11001 001)
    ....
    bswap edi = 0FCF  (11001 111)
    你可以试着汇编/反汇编一些包含只使用一个寄存器操作数的modr/m的指令.如mul reg,iul reg等.
    在你开始之前我们先说说16位的寄存器.你一定还记得prefix 66h吧.在32位模式中,我们只需在OpCode前加上66就可以了.如:
    INC EAX   = 40h
    INC AX    = 66h 40h
    DEC ECX   = 49h
    DEC CX    = 66h 49h
    ...
    BSWAP EDI = 0F CF
    BSWAP DI  = 66 0F CF
    我们一起看看局部寄存器.
    以MUL和IMUL指令为例,他们是:
    MUL    1111011w:11 100 reg
    IMUL   1111011w:11 101 reg
    我们首先看到的是,两条指令首字节相同,并且最低位都是同样的标记"w"--F7(w=1),F6(w=0).
    讨论局部寄存器,这是不的不讲的一位(bit).
    若 w = 1,reg field为全寄存器,否则reg field为局部寄存器.
    所以:
    w = 1               w = 0
    reg      value      reg
    EAX      000        AL
    ECX      001        CL
    EDX      010        DL
    EBX      011        BL
    ESP      100        AH
    EBP      101        CH
    ESI      110        DH
    EDI      111        BH
    一共有8个通用寄存器,其中的4个可以作为两个局部寄存器使用.
    你可能会问,reg field有3bit,加上w bit一共4位,2^4=16,刚好足够表示这16个寄存器,既然这样,那么可以给每一个寄存器(包括全寄存器和局部寄存器)分配一个数字代号,为什么不采用这种方式呢?
    这个问题问得非好!(但是我的午饭时间到了,留个悬念也好,哈哈,下次继续啊~~)
    需要用到的小程序:regfield.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功