X86指令基本格式


本文属于《 X86架构指令基础系列教程》之一,欢迎查看其它文章。

1 什么是机器码

机器码是CPU可以识别,并执行的二进制数据。
通常使用高级语言,如C/C++编写的代码,经过编译之后,生成的可执行文件中,就包含了机器码,可以被CPU执行。
如果你熟悉X86机器码,具体的定义,那么你可以在文件中,徒手直接编写机器码,这样也可以被CPU执行,只不过难度很大,没有我们使用高级语言编写,然后编译为机器码,来的简单。

机器码,是我们通俗的叫法。在X86架构下,机器码就是指一条一条的X86指令,这些指令的集合,就叫做X86指令集

2 X86指令基本格式

所有的X86架构指令编码,都是基于一个基本指令格式来构成的。
基本指令,由以下组成:

  • Instruction Prefixes(指令前缀),可选,最多四个前缀,每个前缀1字节。
  • Opcode(操作码),必须,1或2字节。
  • ModR/M与SIB(地址形式说明符),可选,由ModR/M字节和SIB(Scale-Index-Base)字节组成。Mod R/M 字段指定寻址模式和操作数,符号 “R/M” (register/memory) 代表的是寄存器和模式。伸缩索引字节(scale index byte, SIB)用于计算数组索引偏移量。
  • Displacement(地址位移),可选,地址位移为1、2、4字节或无。地址位移字段保存了操作数的偏移量,在 “基址-偏移量” 或 “基址-变址-偏移量” 寻址模式中,该字段还可以与 “基址或变址寄存器” 相加。
  • Immediate(立即数),可选,立即数为1、2、4字节或无。立即数字段保存了常量操作数。
    在这里插入图片描述

3 指令前缀

X86指令集中的指令前缀(Instruction Prefix)是一种特殊的标记,用于指示紧随其后的指令应该如何被解释。指令前缀并不会改变指令的本质,但可能会改变指令的操作。
指令前缀分为四组:封锁和重复执行前缀、段前缀、修改操作数默认长度、修改默认地址长度,每组都有一组允许的前缀代码。
对于每条指令,可以从每一组中使用一个前缀,并以任意顺序放置。冗余前缀(来自一组的多个前缀)的影响是未定义的,并且可能因处理器而异。

3.1 第一组:封锁和重复执行前缀

  • F0H: LOCK前缀,封锁总线。在有数的指令(如ADD,ADC)前方时,使指令变为原子操作,并与被修饰的指令一起提供内存屏障效果。
  • F2H:REPNE/REPNZ前缀(只位于字符串指令前)。
  • F3H:REP前缀(只位于字符串指令前)。
  • F3H:REPE/REPZ前缀(与REP前缀同码)。

3.2 第二组:段前缀

在32位汇编中,有8个段寄存器:ES、CS、SS、DS、FS、GS、LDTR、TR(顺序固定),不再用段寄存器寻址而只做权限控制。前缀和寄存器对应如下:

  • 2EH:CS段覆盖前缀
  • 36H:SS段覆盖前缀
  • 3EH:DS段覆盖前缀
  • 26H:ES段覆盖前缀
  • 64H:FS段覆盖前缀
  • 65H:GS段覆盖前缀

使用前缀修饰后,指令(opcode)的默认段寄存器会被修改,如默认的MOV操作从DS段拿数据,加上36前缀后会基于SS段地址取数据。

3.3 第三组:修改操作数默认长度

66H,用来“反转”默认的16位或32位操作数宽度。例如,当默认的操作数宽度是32位时,可以用这个前缀选择16位宽度的操作数,或者反之。如下指令码和汇编对照:

50:  PUSH EAX
6650: PUSH AX

当一个66前缀出现在指令的开始处时,它告诉CPU,接下来的指令应该被视为一个16位指令,而不是32位指令。

3.4 第四组:修改默认地址长度

67H,用来“反转”默认的16位或32位地址宽度。例如,当默认的地址宽度是32位时,可以用这个前缀选择16位宽度的地址,或者反之。如下指令码和汇编对照:

8801:   MOV DS:[ECX],AL
678801: MOV DS:[BX+DI], AL

67H前缀是X86指令集中的一个指令前缀,用于改变指令的地址空间。
当67H前缀出现在一个指令前面时,它会告诉CPU,该指令的操作数应该被视为在16位地址空间中,而不是32位地址空间中。这个前缀通常用于在32位和16位模式之间切换。

例如:

8B08:   mov ecx,[eax]	;32位程序中,通过32位寄存器中地址寻址内存,无指令前缀
678B08:  mov ecx,[eax]	;64位程序中,通过32位寄存器中地址寻址内存,有67指令前缀

3.5 指令前缀存在的意义

3.5.1 不同的指令会有相同的机器码

比如第二组指令,他们的目的操作数都是内存地址,源操作数都是寄存器。因为形式上相同,所有会生成相同的机器码。同时这些指令 MODR/M 字段是相同的,全都是 31,相同意味这这些指令的源操作数都隶属于同一组寄存器,并且操作形式相同。
在这里插入图片描述
以前 8086 16 位时期,8 位和 16 位操作码不同,就对应着 88 和 89。后来 intel 设计出 32 位处理器,为了不增加指令的复杂性,所有后面类似的操作都用相同的操作码 89。
相同的操作码,处理器怎么知道要执行什么操作呢?

3.5.2 默认操作尺寸

➢ 32 位处理器支持 16 位和 32 位操作尺寸

➢ 但是, 在同一时刻,处理器只能按一种操作尺寸工作,要么选择 16 位操作尺寸,要么选择 32 位操作尺寸,这叫做处理器的默认操作尺寸

  • (1)当处理器工作时,如果默认的操作尺寸是 16 位的,则假定它使用的机器指令都是 8 位或者 16 位操作数,以及 16 位有效地址。如果想操作 32 位数据,需要添加指令前缀 66,66 将反转操作数的尺寸,从默认的 16 反转到 32。如果有效地址是 32 位的,则必须添加指令前缀 67。
    在这里插入图片描述
  • (2)处理器工作时,如果默认的操作尺寸是 32 位的,则假定它使用的机器指令都是 8 位或者 32 位操作数,以及 32 位有效地址。如果想操作 16 位数据,需要添加指令前缀 66,66 将反转操作数的尺寸,从默认的 32 反转到 16。如果有效地址是 16 位的,则必须添加指令前缀 67。
    在这里插入图片描述

4 操作码

Opcode主操作码为1或2字节。此外在ModR/M字节中,还有额外的3位操作码字段,可以在主操作码中定义较小的编码字段。这些字段定义了操作的方向、位移的大小、寄存器编码、条件码或符号扩展。操作码中字段的编码根据操作的类别而变化。
如果主操作码是0x0f开头则需要取第二字节,如果主操作码开头是0x0f38,0x0f3a开头则再取第三字节。

5 ModR/M与SIB

在这里插入图片描述

5.1 ModR/M字节

大多数引用内存中操作数的指令,在主操作码后面都有一个寻址形式说明符字节(称为ModR/M字节)。ModR/M字节包含三个信息字段:

  • Mod字段与R/M字段组合形成32个可能的值:8个寄存器和24种寻址模式。
  • Reg/Opcode字段指定一个寄存器号或三个以上的操作码信息。Reg/Opcode字段的目的在主操作码中指定。
  • R/M字段可以指定一个寄存器作为操作数,或者可以与Mod字段组合以编码寻址模式。

5.2 SIB字节

ModR/M字节的某些编码需要第二个寻址字节,即SIB字节,以完全指定寻址形式。32位寻址的base-plus-index(基本加索引)和scale-plus-index(缩放加索引)形式需要SIB字节。SIB字节包括以下字段:

  • Scale字段指定比例因子。
  • Index字段指定index register的寄存器号。
  • Base字段指定base register的寄存器号。

6 地址位移

一些寻址形式包括紧跟在ModR/M或SIB字节之后的位移。如果需要一个位移,它可以是1、2或4字节。如果指令指定了一个直接操作数,则该操作数总是跟随任何位移字节。直接操作数可以是1、2或4字节。

7 立即数

在X86指令集中,立即数(Immediate)是指直接在指令中给出的常数或者立即值。这些值直接嵌入到指令中,不需要从内存中读取,也不需要计算。
例如,以下是一条ADD指令,它将寄存器A中的值与立即数5相加:

ADD A, 5

在这个例子中,5就是立即数。这条指令将寄存器A中的值与5相加,并将结果存回寄存器A。立即数在指令编码中直接给出,不需要在执行时从内存中读取。
立即数可以用在各种需要固定数值的指令中,例如算术运算、逻辑运算、位移等。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值