自己动手构造编译系统:编译、汇编与链接2.2 x86指令格式-阿里云开发者社区

开发者社区> 华章出版社> 正文
登录阅读全文

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

简介:

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字段,指令中的常量决定偏移量和立即数部分。

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接