首页 > 其他分享 >x86指令集 字节大小

x86指令集 字节大小

时间:2024-12-16 22:30:57浏览次数:7  
标签:x86 prefix 指令 指令集 override 字节 ModRM size

x86指令集 字节大小

https://bbs.kanxue.com/thread-190127.htm

最近对x86_32架构下的许多程序进行了指令长度统计,结果表明所有程序所涉及的指令长度范围均为:1~11字节。
而根据INTEL 开发者手册上介绍的指令的最大长度限制为15字节。
但是,在什么情况或者架构上才会有12~15字节长度的指令呢?
还有,是否可以断定在X86_32架构下指令的最大长度为:11字节?如果是,有木有计算依据?

 

lock add dword ptr es:[eax+ecx*8+0x11223344], 0x12345678
在16 位模式下是15 bytes:
26 66 67 F0 81 84 C8 44 33 22 11 78 56 34 12

 

lock add dword ptr es:[eax+ecx*8+0x11223344], 0x12345678

仅仅在 16 位模式下,这条汇编语句的 encode 是 15 bytes

因为:它在 16 位模式下,需要进行 operand size override 和 address size override,因此能达到 prefix 的饱和

从而每个部分除了 opcode 外,都达到了饱和状态。刚刚好是 15 bytes:26 66 67 F0 81 84 C8 44 33 22 11 78 56 34 12

4 group 的 prefix 都使用上了,ModRM 和 SIB 都需要,displacement 和 immediate 都是 4 bytes 的,只有 opocde 是 1 byte

这条指令在 32 位是:26 F0 81 84 C8 44 33 22 11 78 56 34 12 (13 bytes)

在 64 位下:26 67 F0 81 84 C8 44 33 22 11 78 56 34 12 (14 bytes)

那是因为 32 位下缺省的 operands size 和 address size 是 32 位,不需要作 operand size override 和 address size override

在 64 位下缺省的 operands size 是 32 位,而 address size 是 64 位,因此不需要作 operand size override,但是需要做 address size override

 

disassembler 的反汇编的指令边界与真实执行指令边界可能会不一致。当然造成这种不一样的人为的,实际上这是对 disassembler 的一种考验。

不要期望编译器会产生大于 15 bytes 的指令编码!除非它有错。不要认为 disassmbler(反汇编器)的结果就是真实执行指令结果,有可能会不一致!

现在:我们可以回答前面提到的三个疑问:

  • 真实的指令长度确实为 15 bytes
  • processor 会给我们保证这一点
  • 当加载超过 15 bytes 长度的指令时,processor 会给我们抛出 #GP 异常,它通过这种方式保证了 15 bytes 指令长度

 

x86指令集 :
16位,最大长度15字节
32位,最大长度13字节
64位,最大长度14字节

 

 

INSTRUCTION PREFIXES (前缀只有固定的这几个)
The instruction prefixes are divided into four groups, each with a set of allowable prefix codes:
• Lock and repeat prefixes.
— F0H—LOCK prefix.
— F2H—REPNE/REPNZ prefix (used only with string instructions).
— F3H—REP prefix (used only with string instructions).
— F3H—REPE/REPZ prefix (used only with string instructions).
• Segment override.
— 2EH—CS segment override prefix.
— 36H—SS segment override prefix
— 3EH—DS segment override prefix.
— 26H—ES segment override prefix.
— 64H—FS segment override prefix.
— 65H—GS segment override prefix.
• Operand-size override, 66H
• Address-size override, 67H
For each instruction, one prefix may be used from each of these groups and be placed in any
order. The effect of redundant prefixes (more than one prefix from a group) is undefined and may
vary from processor to processor.

 

 

32位

 

 

 

例2:随便找一个机器码如:FF 15 D4 81 DF 00

那么它的汇编语句是什么呢?

解码器会依次读入第 1 个字节,第 2 个字节等 ... 进行判断:

(1)第 1 个字节是什么? prefix 还是 opcode

(2)同样再判断第 2 个字节是不是 prefix,如果不是 prefix ,那么它就是 opcode 码

(3)如果第 2 个字节是 opcode 码,再判这个 opcode 需不需 ModRM 字节,如果需要,第 3 个字节就是 ModRM 字节

(4)根据 ModRM 字节判断需不需要 SIB 字节,第 4 个字节如果需它就是 SIB 字节

(5)判断 ModRM 字节是否需要 displacment 字节和 immediate 字节

根据上面的逻辑,得出:

FF:这个字节是个具有 Group 属性的 Opcode 码,它进行什么操作需要依赖于 ModRM 字节的 Reg 域。

换句话来说,FF 并不是完整独立的 Opcode 码,它要联合 ModRM 才能确定具体的操作。

15:这个是 ModRM 字节(mod-reg-r/m): ModRM.mod = 00,ModRM.reg = 010,ModRM.r/m = 101。

其中 ModRM.reg 域被 FF(opcode) 作为确定具体操作码的参考。

● Opcode + ModRm.reg : FF /010 最终确定为:Call 指令。

● ModRM.mod:00 表示操作数是 memory

● ModRM.r/m:这是一个 32 位的 displacement 值。

所以,这个机器码最终被解码为: call dword ptr [00DF81D4]

下面的直观的图表

 

下面来看看 x86/x64 指令 encode 的 2 个例子:

mov word ptr es:[eax + ecx * 8 + 0x11223344], 0x12345678

例子1:在当前 32 位系统下,有下面汇编语句(Intel 格式):

这是一条** mov** 指令,目标操作数是** memory**,源操作数是 immediate

注意:

我特地将目的操作数的大小定为是 word(2个字节),而不是 dword。但是,源操作数却是一个 dword 大小的 0x12345678。

那么:对于这条汇编语句,编译器应该如何处理呢?

  • 应该怎样处理 immediate 部分
  • 应该选择哪条 mov 指令
  • operand size 是多少
  • 在 32 位环境下,如何生成 16 位 operand 或 address 的代码
  • 寻址模式是什么

这些问题是我们最终需要掌握的知识,这是本栏目的最终目的。

实际上,它最终形成的机器编码是:26 66 c7 84 c8 44 33 22 11 78 56

(1)dword 大小的源操作数,会被编译器截断为 word 大小

(2)选择 MOV Ev, Iz 指令,它的 opcode 是 C7

(3)它的 operand size 是 word 大小,取决于 first operand 的 size

(4)在 32 位下,通过使用 operand size override 可以造型为 16 位 operands size,使用 address size override 可以造型为 16 位 address size

(5)它的寻址模式是:基址+变址寻址,它需要提供 SIB 字节

下面的图直观的分解这条指令的组成部分:

26:在指令序列里是:prefix 部分,它是 semgent overrride prefix ,作用是调整内存操作数的段选择子

66:在指令序列里是:prefix 部分,它是 operand size override prefix ,作用是调整操作数的缺省大小

C7:在指令序列里是:Opcode 部分,是 mov 指令是操作码

84:在指令序列里是:ModRM 值,定义操作数的属性

C8:在指令序列里:SIB 值定义内存操作数的属性

44332211:在指令序列里是: displacement 值

7856:在指令序列里是:immediate 值

这 2 个例子,作为对学习 x86/x64 指令编码的一个感性认识。

 

======== End

 

标签:x86,prefix,指令,指令集,override,字节,ModRM,size
From: https://www.cnblogs.com/lsgxeva/p/18611249

相关文章

  • PVE系统下——OpenWRT一键扩容脚本(x86下EXT4&SquashFS)
    扩容了x86上的OpenWrt根分区和文件系统。1.PVE上增加硬盘大小2.执行脚本安装依赖opkgupdateopkginstallpartedlosetupresize2fs下载脚本并一键执行wget-U""-Oexpand-root.sh"https://openwrt.org/_export/code/docs/guide-user/advanced/expand_root?......
  • x86下的tsc计时器
    tic-toc.s对外提供两个接口,voidtic(void),uint64_ttoc(void),用法基本类似matlab的tictoc函数,toc函数返回的是cycles,转换成时间需要除cputsc的频率,tsc频率一般不是cpu主频,而是最大频率的1/2,(cpu有最大和睡眠频率),获取tsc的频率可以通过接口dmesg|greptscbash命令查看。......
  • 分区对齐(Partition Alignment)是指磁盘分区表中的分区起始位置与硬盘的物理扇区(或磁盘
    分区对齐(PartitionAlignment)是指磁盘分区表中的分区起始位置与硬盘的物理扇区(或磁盘块)进行对齐的技术。具体来说,分区的起始位置会与磁盘的物理块大小对齐,通常是以512字节、4KB等为单位的。为什么分区需要对齐?提高性能:现代硬盘(尤其是固态硬盘,SSD)通常具有更大的扇区大小(例如4KB......
  • 有效的括号(字节面试题 最优解)
    题目来源20.有效的括号-力扣(LeetCode)题目描述给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。示例1:输入:s......
  • 转载:【AI系统】CPU 指令集架构
    我们知道,计算机指令是指挥机器工作的指示和命令,程序就是一系列指令按照顺序排列的集合,执行程序的过程就是计算机的工作过程。从微观上看,我们输入指令的时候,计算机会将指令转换成二进制码存储在存储单元里面,然后在即将执行的时候拿出来。那么计算机是怎么知道我们输入的是什么指令,......
  • 工作三年,字节让我java转go,怎么选择?
    在面临从Java转向Go的语言选择时,以下是一些考虑因素,可以帮助你做出决定:技术栈匹配:灵动Ai:了解灵动Ai的技术栈和项目需求。如果Go在该公司的项目中更为常见或更受青睐,那么转向Go可能会对你的职业发展更有利。个人兴趣和擅长领域:考虑你对Java和Go哪一种语言有更大的兴趣。......
  • 网络字节序本地字节序点分十进制转换函数总结&&两种初始化socket并bind的步骤
    网络字节序本地字节序点分十进制转换函数总结&&两种初始化socket并bind的步骤文章目录网络字节序本地字节序点分十进制转换函数总结&&两种初始化socket并bind的步骤1.网络字节序、本地字节序和点分十进制的数据长啥样1.点分十进制2.本地字节序(主机字节序)和网络字节序3.......
  • 【Docker】Docker如何在x86_64平台构建arm64镜像
    Buildx是DockerCLI的一个用于增强构建能力的扩展插件,旨在扩展和改进Docker的原生dockerbuild命令。Buildx允许开发人员构建跨平台镜像、多架构镜像,支持更灵活的构建配置,并且集成了许多现代构建工具和技术。安装使用Buildx需要Docker的版本>=19.03。WindowsandmacOSBuildx......
  • 转载:【AI系统】CPU 指令集架构
    我们知道,计算机指令是指挥机器工作的指示和命令,程序就是一系列指令按照顺序排列的集合,执行程序的过程就是计算机的工作过程。从微观上看,我们输入指令的时候,计算机会将指令转换成二进制码存储在存储单元里面,然后在即将执行的时候拿出来。那么计算机是怎么知道我们输入的是什么指令,......
  • 转载:【AI系统】CPU 指令集架构
    我们知道,计算机指令是指挥机器工作的指示和命令,程序就是一系列指令按照顺序排列的集合,执行程序的过程就是计算机的工作过程。从微观上看,我们输入指令的时候,计算机会将指令转换成二进制码存储在存储单元里面,然后在即将执行的时候拿出来。那么计算机是怎么知道我们输入的是什么指令,......