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 一个操作码字节如何根据;寄存器/操作码“;领域那是什么?_Assembly_X86 64_Disassembly_Machine Code - Fatal编程技术网

Assembly 一个操作码字节如何根据;寄存器/操作码“;领域那是什么?

Assembly 一个操作码字节如何根据;寄存器/操作码“;领域那是什么?,assembly,x86-64,disassembly,machine-code,Assembly,X86 64,Disassembly,Machine Code,如何确定字节数组将在机器代码中转换成什么 我知道如果我在开始时看到0f,它是一条2字节指令,但我看到了其他前缀,在x64调试器的一些反汇编中,我看到了奇怪的交互,如48 83 C4 38,我可以在操作码引用中看到48表示操作数是64字节 但是83说根据名为“寄存器/操作码字段”的字段,它可以是7条不同的指令。什么? 有人能解释一下处理器如何使用这些字节来确定: 运行什么指令 指令使用的寄存器和/或地址(如果有) 这取决于特定的体系结构,不仅仅是x86-64,还取决于实际的芯片供应商。例如,您可以

如何确定字节数组将在机器代码中转换成什么

我知道如果我在开始时看到0f,它是一条2字节指令,但我看到了其他前缀,在x64调试器的一些反汇编中,我看到了奇怪的交互,如48 83 C4 38,我可以在操作码引用中看到48表示操作数是64字节

但是
83
说根据名为“寄存器/操作码字段”的字段,它可以是7条不同的指令。什么?

有人能解释一下处理器如何使用这些字节来确定:

  • 运行什么指令
  • 指令使用的寄存器和/或地址(如果有)

  • 这取决于特定的体系结构,不仅仅是x86-64,还取决于实际的芯片供应商。例如,您可以检查

    这有一整章专门讨论字节码中命令的语法,然后是每个可用命令的另一章。图2.1为您提供了一个想法:

    摘自上述手册。例如,如果您使用ARM,这将发生变化


    人们可能需要多年的时间才能“流利地阅读”字节码,因此略读一下这一点只能让您大致了解语法或查找特定内容的良好资源。

    这取决于特定的体系结构,不仅仅是x86-64,还取决于实际的芯片供应商。例如,您可以检查

    这有一整章专门讨论字节码中命令的语法,然后是每个可用命令的另一章。图2.1为您提供了一个想法:

    摘自上述手册。例如,如果您使用ARM,这将发生变化


    人们可能需要多年的时间才能“流利地阅读”字节码,因此略读一下这一点只能让您大致了解语法或查找特定对象的良好资源。

    0x48
    是REX前缀,W字段设置为1,意味着64位操作数大小。 (不是64字节)

    许多指令即时版本的操作码,包括
    83
    ,使用ModR/M字节中的3位
    /r
    字段作为3个额外的操作码位。英特尔的第二卷手册记录了这一点,我认为附录中的操作码表包括了这一点

    这就是为什么大多数原始8086立即数指令,如
    和r/m,imm
    仍然只允许2个操作数,这与
    shrd eax、edx、4
    imul edx、[rdi],12345
    不同,其中两个ModRM字段都用于对操作数以及操作码隐含的立即数进行编码。SHRD/SHLD和添加386和imul立即。可能不幸的是,copy and and(
    和eax,edx,0xf
    )不可编码,但至少x86可以使用LEA进行复制和添加/sub


    每个指令都有自己的文档,例如显示编码,如
    REX.W+83/0 ib
    对于
    添加r/m64,imm8
    ,这就是您所拥有的

    0xc4=0B11000000,因此reg字段=0。因此,我们的操作码是用英特尔的符号表示的
    83/0

    其余的ModRM字段为:

    • mode=0b11,因此rm字段编码的是寄存器操作数,而不是寻址模式的基址寄存器
    • rm=0b100。reg#4=SPL/SP/ESP/RSP。(在本例中是RSP,因为它是64位操作数大小)。请参阅英特尔手册或表格
    因此,指令是添加rsp,0x38

    ndisam-b64
    同意:

    $ cat > foo.asm
    db 0x48, 0x83, 0xC4, 0x38
    $ nasm foo.asm     # create a flat binary with those bytes, not an object file
    $ ndisasm -b64 foo
    00000000  4883C438          add rsp,byte +0x38
    

    0x48
    是REX前缀,W字段设置为1,表示64位操作数大小。 (不是64字节)

    许多指令即时版本的操作码,包括
    83
    ,使用ModR/M字节中的3位
    /r
    字段作为3个额外的操作码位。英特尔的第二卷手册记录了这一点,我认为附录中的操作码表包括了这一点

    这就是为什么大多数原始8086立即数指令,如
    和r/m,imm
    仍然只允许2个操作数,这与
    shrd eax、edx、4
    imul edx、[rdi],12345
    不同,其中两个ModRM字段都用于对操作数以及操作码隐含的立即数进行编码。SHRD/SHLD和添加386和imul立即。可能不幸的是,copy and and(
    和eax,edx,0xf
    )不可编码,但至少x86可以使用LEA进行复制和添加/sub


    每个指令都有自己的文档,例如显示编码,如
    REX.W+83/0 ib
    对于
    添加r/m64,imm8
    ,这就是您所拥有的

    0xc4=0B11000000,因此reg字段=0。因此,我们的操作码是用英特尔的符号表示的
    83/0

    其余的ModRM字段为:

    • mode=0b11,因此rm字段编码的是寄存器操作数,而不是寻址模式的基址寄存器
    • rm=0b100。reg#4=SPL/SP/ESP/RSP。(在本例中是RSP,因为它是64位操作数大小)。请参阅英特尔手册或表格
    因此,指令是添加rsp,0x38

    ndisam-b64
    同意:

    $ cat > foo.asm
    db 0x48, 0x83, 0xC4, 0x38
    $ nasm foo.asm     # create a flat binary with those bytes, not an object file
    $ ndisasm -b64 foo
    00000000  4883C438          add rsp,byte +0x38
    

    我在一页上看到字母a,这可能是许多不同的单词,后面的字母是n。这可能是一个,答案,任何字数,所以我继续

    x86和那个时代的其他机器代码就是这样工作的,特别是它直接派生的指令集

    首先,也是最重要的一点,如果你只是把一个程序的所有字节都放在中间,这是没有任何意义的,很容易出错“快速棕色狐狸”“快速棕色信息”“ickbrow”这是什么?处理器根据指令集的规则启动和继续,处理器相当愚蠢,因为它遵循处理器手册中定义或至少记录的规则。只要
    mov eax,0x12345678
    mov ebx,0x12345678
    mov ecx,0x12345678
    mov edx,0x12345678
    
    Disassembly of section .text:
    
    00000000 <.text>:
       0:   b8 78 56 34 12          mov    eax,0x12345678
       5:   bb 78 56 34 12          mov    ebx,0x12345678
       a:   b9 78 56 34 12          mov    ecx,0x12345678
       f:   ba 78 56 34 12          mov    edx,0x12345678
    
    mov eax,eax
    mov eax,ebx
    mov eax,ecx
    mov eax,edx
    
    
       0:   89 c0                   mov eax,eax
       2:   89 d8                   mov eax,ebx
       4:   89 c8                   mov eax,ecx
       6:   89 d0                   mov eax,edx
    
    a = 0
    if(a == 0) goto somewhere
    b = 7
    
    1 a = 0;
    2
    1 if(a == 0) goto somewhere
    2
    3
    1 b = 7.
    2
    3
    1
    2
    3
    
    1 b = 7.
    2 
    3  <--- is a branch destination
    1
    2
    3