Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly x86指令前缀解码_Assembly_X86_X86 64_Disassembly - Fatal编程技术网

Assembly x86指令前缀解码

Assembly x86指令前缀解码,assembly,x86,x86-64,disassembly,Assembly,X86,X86 64,Disassembly,我目前正在为x86_x64 CISC开发一个反汇编程序。 关于前缀指令解码,我有两个问题: 对于以下流: \x9b\x9b\xd9\x30 \xf2\x66\x0f\x12\x00 GCC和objdump输出 fstenv [eax] 所以他们首先读取所有前缀 (不超过15),然后继续检查正确的说明 使用最后一个前缀read\x9b和\xd9使其成为fstenv 指示 另一方面,Capstone wait wait fnstenv dword ptr [eax] 现在,很明显,这是错误

我目前正在为x86_x64 CISC开发一个反汇编程序。 关于前缀指令解码,我有两个问题:

  • 对于以下流:

    \x9b\x9b\xd9\x30
    
    \xf2\x66\x0f\x12\x00
    
    GCC
    objdump
    输出

    fstenv [eax]
    
    所以他们首先读取所有前缀 (不超过15),然后继续检查正确的说明 使用最后一个前缀read
    \x9b
    \xd9
    使其成为
    fstenv
    指示

    另一方面,
    Capstone

    wait
    wait
    fnstenv dword ptr [eax] 
    
    现在,很明显,这是错误的 它放入2条等待指令,而不仅仅是1条。但它是否应该
    wait
    指令或
    GCC
    objdump
    在右边 此处用于使用
    fstenv
    指令

  • 对于以下流:

    \x9b\x9b\xd9\x30
    
    \xf2\x66\x0f\x12\x00
    
    GCC
    objdump
    输出

    data16 movddup xmm0,QWORD PTR [eax]
    
    所以他们正在安排 前缀按特定顺序排列,因此在
    \xf2
    之前解释
    \x66
    因此,他们仍然使用最后一个前缀read
    \xf2
    来 确定指令
    movdup
    。他们就在这里等你 使用前缀的这种排列逻辑,还是它们错了

    另一方面,
    Capstone

    wait
    wait
    fnstenv dword ptr [eax] 
    
    movlpd xmm0,qword ptr[eax]

    所以他们没有按任何顺序排列前缀,只是 读取最后一个前缀
    \x66
    以确定指令
    movlpd
    在这种情况下比
    GCC
    更符合逻辑
    objdump
    正在执行


  • cpu实际如何解释这些流?

    您的cpu实际如何解释这些流可以相对容易地进行测试


    对于第一个流,您可以使用我的工具。您可以使用该命令

    sudo./nanoBench.sh-asm_init“mov RAX,R14”-asm.字节0x9b,0x9b,0xd9,0x30”

    此命令首先将
    RAX
    设置为有效的内存地址,然后多次运行流。在我的核心i7-8700K上,我得到以下输出(对于固定功能性能计数器):

    我们可以看到CPU执行三条指令,因此
    Capstone
    似乎是正确的


    您可以使用nanoBench的调试模式分析第二个流:

    sudo./nanoBench.sh-展开1-asm“mov-RAX,R14;mov-qword-ptr[RAX],1234;。字节0xf2,0x66,0x0f,0x12,0x00”-调试

    这将在gdb内部首先执行asm代码,然后生成断点陷阱。现在我们可以查看XMM0寄存器的当前值:

    (gdb) p $xmm0.v2_int64
    $1 = {1234, 1234}
    
    因此,XMM0的高四字和低四字现在与地址RAX处的内存具有相同的值,这表明CPU执行了
    movddup
    指令


    您还可以在不使用nanoBench的情况下分析第二个流。为此,可以将以下汇编程序代码保存在文件
    asm.s

    .intel_syntax noprefix
    
    .global _start
    _start:
        mov RAX, RSP
        mov qword ptr [RAX], 1234   
        .byte 0xf2, 0x66, 0x0f, 0x12, 0x00
        int 0x03 /* breakpoint trap */
    
    然后,您可以使用

    as asm.s -o asm.o
    ld -s asm.o -o asm
    
    现在,您可以使用gdb使用
    gdb./asm
    对其进行分析:

    (gdb) r
    Program received signal SIGTRAP, Trace/breakpoint trap.
    0x0000000000400088 in ?? ()
    (gdb) p $xmm0.v2_int64
    $2 = {1234, 1234}
    

    9B 9B D9 30
    顶石是正确的,objdump的
    fstenv
    也基本正确。

    fstenv
    不是真正的机器指令,它是fwait+
    fnstenv
    的伪指令。请注意,列出的
    fnstenv
    的机器代码是
    D9/6
    ,而
    fstenv
    在这之前添加了一个
    9B

    9B
    不是指令前缀,它是一个单独的1字节指令,称为
    。在最初的8086+8087上,这是必要的,因为8087是一个真正独立的协处理器。请参见顶部答案下方的评论;在286之前,它们的耦合不够紧密,主CPU无法知道是否存在未决的FPU异常

    我不确定细节,但8086/186上的
    fnstsw
    可能会读取旧版本的状态字,该状态字没有从屏蔽异常设置最新标志。或者,它可能只与未屏蔽异常有关,用于从乘法或
    fnst*
    指令之前的任何内容获取FP异常。根据Stephen Kitt的评论,286和更新版本“在执行NPX指令之前检查其测试行”,自动等待

    当然,带有集成FPU的CPU在精确的FP异常和同步行为方面没有问题,因此
    fwait
    在那里是浪费空间


    Capstone的
    wait
    /
    wait
    /
    fnstenv-dword-ptr[eax]
    因此更加明确,因为就CPU而言,它实际上是3条指令。(Andreas的回答显示了现代x86性能计数器的记录)

    Objdump将前面的两条
    fwait
    指令视为单个
    fstenv
    的一部分。将其解码为
    fwait
    会更准确
    fstenv-dword ptr[eax]
    因为英特尔的手册仅将
    fstenv
    记录为包含单个
    fwait
    操作码。但是额外的
    fwait
    没有架构效果


    第二部分 正如Andreas的回答所示,
    F266 0f 12 00
    在实际硬件上解码为
    movddup
    (64位广播),前缀为无意义的
    66
    (数据16操作数大小)objdump是正确的,至少对于该CPU是正确的

    有文档记录的编码,其中F2为必填前缀,0F为转义字节

    我们可能期望它像解码一个毫无意义的F2 REP前缀一样,但事实并非如此顶点错误。强制前缀字节有一些规则:包括“如果使用F2或F3,则忽略66前缀”

    我不能100%确定这个序列在所有硬件上都能保证解码为
    movddup
    ,当然如果我