自己动手构造编译系统:编译、汇编与链接2.2x86指令格式

    xiaoxiao2024-06-19  110

    2.2  x86指令格式

      

          编译系统的汇编器需要把编译器生成的汇编语言程序转化为x86格式的二进制机器指令序列,然后将这些二进制信息存储为ELF格式的目标文件。因此需要先了解二进制机器指令的基本结构。

      如图2-10所示,在x86的指令结构中,指令被分为前缀、操作码、ModR/M、SIB、偏移量和立即数六个部分。本书设计的编译器生成的汇编指令中不包含前缀,这里暂时不介绍它的含义。操作码部分决定了指令的含义和功能,ModR/M和SIB字节为扩充操作码或者为指令操作数提供各种不同的寻址模式。如果指令含有偏移量和立即数信息,就需要把它们放在指令后边的对应位置。

     

    图2-10  x86指令格式

      这里使用一个简单的例子与表2-2说明x86指令结构的含义,例如汇编指令:

    add eax,ebx

    表2-2  二进制指令编码

    指令格式

    操作码

    mod字段

    reg字段

    r/m字段

    指令编码

    add r/m32,reg

    0x01

    11

    011

    000

    0000 0011 1100 0011

    add reg,r/m32

    0x03

    11

    000

    011

    0000 0001 1101 1000  查阅Intel的指令手册,当操作数为32位寄存器时,add指令的操作码是0x01或者0x03,它们对应的指令格式是add r/m32,reg和add reg,r/m32。在ModR/M字节的定义中,高两位mod字段为0b11时表示指令的两个操作数都是寄存器,低三位表示r/m操作数寄存器的编号,中间三位表示reg操作数寄存器的编号。Intel定义eax寄存器编号为0b000,ebx寄存器编号为0b011。如果我们采用操作码0x01,reg应该记录ebx的编号0b011,r/m32记录eax编号0b000,mod字段为0b11。因此该指令的ModR/M字节为:

    11 011 000  =>  0xd8

      同理,若采用操作码0x03的话,ModR/M字节应该是:

    11 000 011  =>  0xc3

      指令不再含有其他信息,因此不存在SIB和偏移量、立即数字段。这样“add eax,ebx”指令就有两种二进制表示形式:0x01d8与0x03c3。

      通过这个例子可以得出结论:在汇编器语法分析阶段,应该记录生成的二进制指令需要的信息。指令的名称决定操作码,指令的寻址方式决定ModR/M和SIB字段,指令中的常量决定偏移量和立即数部分。

      由于本书设计的编译器所生成的汇编指令的种类有限,因此降低了汇编器对指令信息分析的复杂度,但是还有大量的其他类型的指令需要具体分析,这些内容会在以后章节中阐述。

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)