爱技术 & 爱分享
爱蛋蛋 & 爱生活

处理器指令

处理器指令

在操作的最底层,所有计算机处理器都按照制造商在处理器芯片内部定义的二进制代码操作数据。这些代码定义处理器应该利用程序员提供的数据完成什么样的功能。这些预置的代码被称为指令码(instruction code)。不同类型的处理器包含不同类型的指令码。通常按照处理器芯片支持的指令码的数量和类型对它们进行分类。

虽然不同类型的处理器可能包含不同类型的指令码,但是他们处理指令码程序的方式是类似的。

当计算机处理器芯片运行时,它读取内存中的指令码。每条指令码集合可能包含一个或者多个字节信息,这些信息指示处理器完成特定的任务。每条指令码都是从内存中读取的,指令码所需的数据也是存储在内存中并且从内存中读取。包含指令码的内存字节和包含处理器使用的数据的字节没有区别。

为了区分数据和指令码,要使用专门的指针(pointer)帮助处理器跟踪数据和指令码存储在内存中的什么位置。

指令指针(instruction pointer)用于帮助处理器了解哪些指令码已经处理过了,以及接下来要处理的是那条指令码。当然,有些专门的指令能改变指令指针的位置,比如跳转到程序的特定位置。

数据指针(data pointer)用于帮助处理器了解内存中数据区域的起始位置是哪里。这个区域称为堆栈(stack)。当新的数据元素被放入堆栈时,指针在内存中”向下”移动。当数被读取出堆栈时,指针在内存中”向上”移动。

指令码处理

每条指令码都包含一个或多个字节的处理器要处理的信息。例如,下面这些指令码字节(十六进制格式)

c7 45 fc 01 00 00 00

通知 Intel IA-32系列处理器把十进制值1加载到一个处理器寄存器定义的内存便宜地址。指令码包含若干信息片段,它们明确地定义处理器要完成什么操作。处理器完成一个指令码集合的处理后,它读取内存中的下一个指令码集合(即指令指针所指向的地方)。在内存中,指令必须按照争取的格式和顺序放置,使处理器能正确地按照顺序执行程序代码。

每条指令都必须包含至少一个字节的操作码(operation code,简写opcode)。操作码定义处理器应该完成什么操作。每个处理器系列都有自己预定义好的操作码,它们定义所有可用的功能。

Intel IA-32指令格式:

Intel IA-32指令格式

IA-32指令码格式由四个主要的部分构成:

  • 可选的指令前缀
  • 操作码(opcode)
  • 可选的修饰符
  • 可选的数据元素

操作码:

IA-32指令码格式中唯一必须的的部分是操作码。每个指令码都必须包含操作码,它唯一地定义由处理器执行的基本功能或者任务,其长度在1到3字节之间。

例如,2字节的操作码 OF A2定义IA-32 CPUID指令。当处理器执行到这个指令码时,它返回不同寄存器中关于微处理器的特定信息。然后,程序员可以使用其他的指令码从处理器寄存器中提取信息,以便确定运行程序的处理器的类型和型号。

指令前缀:

指令前缀可以包含1个到4个修改操作码行为的1字节前缀。按照前缀的功能,这些前缀被分为4个组。修改操作码时,每个组的前缀只能使用一个(因此最多有4个前缀字节)。这4个前缀组如下:

  • 锁定前缀和重复前缀
  • 段覆盖前缀和分支提示前缀
  • 操作数长度覆盖前缀
  • 地址长度覆盖前缀

锁定前缀标识指令将独占地使用共享内存区域。这对于多处理器和超线程系统非常重要。重复前缀用于表示重复的功能(常常在处理字符串时使用)

段覆盖前缀定义可以覆盖定义了的端寄存器值的指令。分支提示前缀尝试向处理器提供程序在条件跳转语句中最可能的路劲的线索(这同分支预测硬件一起使用)

操作数长度覆盖前缀通知处理器,程序将在这个操作码内切换16位和32位操作数长度,这使得程序可以在使用大长度的操作数时警告处理器,帮助加快寄存器的数据赋值。

地址长度覆盖前缀通知处理器,程序将切换16位和32位的内存地址。这两种长度都可以被声明为程序的默认长度,这个前缀通知处理器程序切换到另一种长度。

修饰符:

一些操作码需要另外的修饰符来定义执行的功能中涉及到什么寄存器和内存位置。修饰符包含在3个单独的值中:

  • 寻址方式说明(ModR/M)字节
  • 比例-索引-基址(SIB)字节
  • 1、2或4个地址移位字节

(1)ModR/M字节:

ModR/M字节由3个字段的信息构成,如下图所示:

"ModR/M"

mod字段和r/m字段一起使用,用于定义指令中使用的寄存器或寻址模式。在指令中可能的寻址模式有24个,加上8个可以使用的通用寄存器,所以有32个可能的值。

reg/opcode 字段用于允许使用更多的3位进一步定义操作码功能(比如操作码子功能),或者可以用于定义寄存器的值。

r/m字段用于定义用作该功能的操作数的另一个寄存器,或者可以把它和mod字段组合在一起定义指令的寻址模式。

(2)SIB字节

SIB字节也由3个字段的信息构成,如下图所示:

"SIB"

比例字段指定操作的比例因子。索引字段指定内存访问中用作索引寄存器的寄存器。基址字段指定用作内存访问的基址寄存器的寄存器。

ModR/M和SIB字节的组合创建一个表,它可以定义用于访问数据的众多可能的寄存器组合和内存模式。Intel处理器的规范说明书中定义了ModR/M和SIB字节可以使用的所有可能的组合。

(3)地址移位字节

地址移位字节用来指定对于ModR/M和SIB字节中定义的内存位置的偏移量。可以使用它作为基本内存位置的索引,用于存储或者访问内存之内的数据。

数据元素:

指令码的最后一部分是该功能使用的数据元素。一些指令码从内存位置或者处理器寄存器读取数据,而一些指令码在其本身内包含数据。这个值经常被用于表示静态数字值(比如要加的数字)或者内存位置。根据数据长度,这个值可以包含1、2或者4字节的信息。

例如:c7 45 fc 01 00 00 00

它定义操作码c7,这个操作码是把值传到内存位置的指令。内存位置由修饰符45 fc 定义(它定义从EBP寄存器中的值(值45)指向的内存位置开始的4字节(值fc))。最后4字节定义放到这个内存位置的整数值(在这个例子中这个值是1)

从这个例子可以看出,值1被写为4字节的十六进制01 00 00 00。数据流中的字节顺序取决于使用的处理器类型。IA-32平台处理器使用”little-endian“表示法,其中低地址值的字节首先出现(从低地址—>高地址)。其他处理器使用”big-endian“顺序,其中高地址值字节首先出现。在汇编语言中指定数据和内存位置时,字节序的概念非常重要。

大端小端:

举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:

1)大端模式:
低地址 -----------------> 高地址
0x12  |  0x34  |  0x56  |  0x78

2)小端模式:
低地址 ------------------> 高地址
0x78  |  0x56  |  0x34  |  0x12

赞(1)
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。编程日志 » 处理器指令
分享到: 更多 (0)

游戏 && 后端

传送门传送门