Intel X86架构数据的运算主要由通用寄存器处理,但浮点数例外,浮点数的运算由专门的FPU寄存器处理。二进制浮点数由三部分组成:符号,有效数字和阶码。这些格式都出自由IEEE组织制定的标准754-1985:以下是三种浮点数的格式:
●32位单精度数值包含1位符号、8位阶码,以及23位有效数字的小数部分。
●64位双精度数值包含1位符号、11位阶码,以及52位有效数字的小数部分。
●80 位扩展双精度数值包含1位符号、16 位阶码,以及 63 位有效数字的小数部分。
本篇介绍浮点数处理与指令编码。

12.3 x86指令编码

若要完全理解汇编语言操作码和操作数,就需要花些时间了解汇编指令翻译成机器语言的方法。由于Intel 指令集使用了丰富多样的指令和寻址模式,因此这个问题相当复杂。首先以实地址模式的8086/8088为例来说明,之后,再展示32 位处理器带来的变化。

Intel 8086处理器是第一个使用复杂指令集计算机(Complex Instruction Set Computer CISC)设计的处理器。这种指令集中包含了各种各样的内存寻址、移位、算术运算、数据传送和逻辑操作。与RISC(精简指令集计算机,Reduced Instruction Set Computer)指令相比,Intel 指令在编码和解码方面有些复杂。指令编码(encode)是指将汇编语言指令及其操作数转换为机器码。指令解码(decode)是指将机器指令转换为汇编语言。对 Intel 指令编码和解码的逐步解释至少将有助于唤起对MASM 作者们辛苦工作的理解和欣赏。

12.3.1 指令格式

一般的x86机器指令格式(图12-6)包含了一个指令前缀字节、操作码、Mod R/M 字节、伸缩索引字节(SIB)、地址位移和立即数。指令按小端顺序存放,因此前缀字节位于指令的起始地址。每条指令都有一个操作码,而其他字段则是可选的。少数指令包含了全部字段,平均来看,绝大多数指令都有2个或3个字节。下面是对指令字段的简介:

●指令前缀 覆盖默认操作数大小。

●操作码 (操作代码)指定指令的特定变体。比如,按照使用的参数类型,指令 ADD有 9种不同的操作码。

●Mod R/M 字段指定寻址模式和操作数。符号“R/M”代表的是寄存器和模式。表12-18列出了Mod字段,表12-19给出了当Mod=10b时16 位应用程序的R/M 字段。

●伸缩索引字节 (scale indexbyte,SIB)用于计算数组索引偏移量。

●地址位移 字段保存了操作数的偏移量,在基址-偏移量或基址-变址-偏移量寻址模式中,该字段还可以与基址或变址寄存器相加。

●立即数 字段保存了常量操作数。

表12-18 Mod字段取值

Mod

位移

00

DISP=0,位移低半部分和高半部分都无定义(除非r/m=110)

01

DISP=位移低半部分符号扩展到16位,位移高半部分无定义

10

DISP=位移高半部分和低半部分都有效

11

R/M 字段包含的是寄存器编号

表12-19 16位R/M字段取值(Mod=10)

R/M

有效地址

R/M

有效地址

000

[BX+SI]+D16

100

[SI]+D16

001

[BX+DI]+D16

101

[DI]+D16

010

[BP+SI]+D16

110

[BP]+D16

011

[BP+DI]+D16

111

[BX]+D16

D16表示偏移量是16位的。

12.3.2 单字节指令

没有操作数或只有一个隐含操作数的指令是最简单的指令。这种指令只需要操作码字段,字段值由处理器的指令集预先确定。表12-20列出了几个常见的单字节指令。在这些指令中,INCDX指令好像是不应该出现的,它出现的原因是:指令集的设计者决定为某些常用指令提供独特的操作码。其结果是,为了代码量和执行速度要对寄存器增量操作进行优化。

表12-20 单字节指令

指令

操作码

指令

操作码

AAA

37

LODSB

AC

AAS

3F

XLAT

D7

CBW

98

INC DX

42

12.3.3 立即数送寄存器

立即操作数(常数)按照小端顺序(起始地址为最低字节)添加到指令。首先关注的是立即数送寄存器指令,暂不考虑内存寻址的复杂性。将一个立即字送寄存器的MOV指令的编码格式为:B8+rw dw,其中操作码字节的值为B8+rw,表示将一个寄存器编号(0~7)与B8相加;dw为立即字操作数,低字节在低地址。(表12-21列出了操作码使用的寄存器编号。)下面例子中出现的所有数值都为十六进制。

表12-21 寄存器编号(8/16位)

寄存器

编号

寄存器

编号

AX/AL

0

SP/AH

4

CX/CL

1

BP/CH

5

DX/DL

2

SI/DH

6

BX/BL

3

DI/BH

7

示例: PUSH CX 机器指令为51。编码步骤如下:

1)带一个16位寄存器操作数的PUSH指令编码为50。

2)CX的寄存器编码为1,因此1+50得到操作码为51。

示例: MOV AX,1 机器指令为B8 01 00(十六进制)。编码过程如下:

1)立即数送16位寄存器的操作码为 B8。

2)AX的寄存器编号为0,将0加上B8(参见表12-21)。

3)立即操作数(0001)按小端顺序添加到指令(01,00)。

示例: MOV BX,1234h 机器指令为BB 34 12。编码过程如下:

1)立即数送16位寄存器的操作码为B8。

2)BX 的寄存器编号为3,将3加上 B8 得到操作码BB。

3)立即操作数字节为34 12。

从实践的角度出发,建议手动汇编一些MOV立即数指令来提高能力,然后通过MASM的源列表文件中的生成代码来检查汇编结果。

完整代码测试笔记

;12.3.3.asm         12.3.3 立即数送寄存器
;将一个立即字送寄存器的MOV指令的编码格式为:B8+rw dw,其中操作码字节的值为B8+rw,
;表示将一个寄存器编号(0~7)与B8相加;dw为立即字操作数,低字节在低地址。INCLUDE Irvine32.inc.code
main PROC;push指令编码为50, DX的寄存器编码为2,因此2+50得到操作码52push dx;立即数送16位寄存器的操作码为B8,DX的寄存器编号为2,相加得到操作码BA;立即操作数22h按小端顺序添加到指令(22 00),所以机器码为 BA 22 00mov dx, 22h;立即数送16位寄存器的操作码为B8,CX的寄存器编号为1,相加得到操作码B9;立即操作数1234h按小端顺序添加到指令(34 12),所以机器码为 B9 34 12mov cx, 1234hINVOKE ExitProcess, 0
main ENDP
END main

查看反汇编:

12.3.4 寄存器模式指令

在使用寄存器操作数的指令中,ModR/M字节用一个3位的标识符来表示寄存器操作数。表12-22列出了寄存器的位编码。操作码字段的位0用于选择8位或16位寄存器1表示16位寄存器,0表示8位存器。

表12-22 Mod R/M字段标识寄存器

R/M

寄存器

R/M

寄存器

000

AX or Al

100

SP or AH

001

CX or CL

101

BP or CH

010

DX or DL

110

SI or DH

011

BX or BL

111

DI or BH

比如,MovAx,Bx的机器码为89D8。寄存器送其他操作数的16位MOV指令的Intel编码为89r,其中/r表示操作码后面带一个Mod R/M字节。Mod R/M字节有三个字段(mod、reg和r/m)。例如,若 Mod R/M 的值为D8,则它包含如下字段:

mod

reg

r/m

11

011

000

●6~7是mod字段,指定寻址模式。mod字段为11表示r/m字段包含的是一个寄存器编号。

●位3~5是reg字段,指定源操作数。在本例中,BX就是编号为011的寄存器。

●位0~2是r/m字段,指定目的操作数。本例中,AX是编号为000的寄存器。

表12-23 列出了更多使用8位和16位寄存器操作数的例子,

表 12-23 MOV 指令编码和寄存器操作数的示例

指令

操作码

mod

reg

r/m

mov ax, dx

8B

11

000

010

mov al,dl

8A

11

000

010

mov cx,dx

8B

11

001

010

mov cl,dl

8A

11

001

010

12.3.5 处理器操作数大小前缀

现在将注意力转回到x86处理器(IA-32)的指令编码。有些指令以操作数大小前缀开始,覆盖了其修改指令的默认段属性。问题是,为什么有指令前缀?在编写8088/8086 指令集时,几乎所有 256 个可能的操作码都用于处理带有8位和 16 位操作数的指令。当 Intel 开发32位处理器时,就需要想办法发明新的操作码来处理32位操作数,而同时还要保持与之前处理器的兼容性。对于面向 16 位处理器的程序,所有使用 32位操作数的指令都添加一个前缀字节。对于面向 32 位处理器的程序,默认为 32 位操作数,因此所有使用 16 位操作数的指令添加一个前缀字节。8 位操作数不需要前缀。

示例:16位操作数 现在对表 12-23 中的 MOV 指令进行汇编,以此为例来看看在16位模式下前缀字节是如何起作用的。.286 伪指令指明编译代码的目标处理器,确保不使用32位寄存器。下面的每条MOV指令都给出了其指令编码:

.model small
.286
.stack 100h
.code
main PROCmov ax, dx				;8B C2mov al, dl				;8A C2

现在对32位处理器汇编相同的指令,使用.386 伪指令,默认操作数为 32 位。指令将包括16 位和 32 位操作数。第一条MOV指令(EAX、EDX)使用的是32 位操作数,因此不需要前缀。第二条MOV(AX、DX)指令由于使用的是16位操作数,因此需要操作数大小前缀(66):

.model small
.386
.stack 100h
.code
main PROCmov eax, edx			;8B C2mov ax, dx				;66 8B C2mov al, dl				;8A C2

12.3.6 内存模式指令

如果 Mod R/M 字节只用于标识寄存器操作数,那么 Intel 指令编码就会相对简单。实际上,Intel 汇编语言有着各种各样的内存寻址模式,这就使得Mod R/M 字节编码相当复杂。(指令集的复杂性是RISC设计支持者常见的批评理由。

Mod R/M 字节正好可以指定256 个不同组合的操作数。表 12-24 列出了Mod 00 时的Mod R/M字节(十六进制)。(完整的表格参见《Intel 64and IA-32 Architectures SoftwareDeveloper's Manual》,卷2A。)Mod R/M 字节编码的作用如下:Mod 列中的两位指定寻址模式的集合。比如,Mod 00 有 8 种可能的 R/M 数值(000b~111b),有效地址列给出了这些数值标识的操作数类型。

假设想要编码MOV AX,[SI],Mod位为00b,R/M位为100b。从表12-19可知 AX的寄存器编号为000b,因此完整的Mod R/M 字节为00 000 100b 或04h:

mod

reg

r/m

00

000

100

十六进制字节 04 在表12-24 的AX列第5 行。

MOV [SI],AL 的Mod R/M 字节还是一样的(04h),因为寄存器AL 的编号也是000。现在对指令MOV [SI],AL进行编码。8 位寄存器的传送操作码为88。Mod R/M 字节为04h,则机器码为88 04。

MOV 指令示例

表12-25列出了8位和16位MOV指令所有的指令格式和操作码。表 12-26 和表 12-27给出了表 12-25 中缩写符号的补充信息。手动汇编 MOV指令时可以用这些表作为参考。(更多细节请参阅Intel 手册。)

表12-28列出了更多的MOV指令,这些指令能手动汇编,且可以与表中的机器代码比较。假设myWord的起始地址偏移量为0102h

12.3.7 本节回顾

1.写出下列 MOV 指令的操作码:

.data
myByte BYTE ?
myWord WORD ?
.codemov ax, @datamov ds, ax					;a. 8Emov ax, bx					;b. 8Bmov bl, al					;c. 8Amov al, [si]				;d. 8Amov myByte, al			    ;e. A2mov myWord, ax			    ;f. A3

2.写出下列 MOV 指令的 Mod R/M 字节:

.data
array WORD 5 DUP(?)
.codemov ax, @datamov ds, ax					;a. D8mov dl, bl					;b. D3mov bl, [di]				;c. 1Dmov ax, [si+2]				;d. 44mov ax, array[si]			;e. 84mov array[di], ax			;f. 85

12.4 本章小结

二进制浮点数由三部分组成:符号、有效数字和阶码。Intel处理器使用了三种浮点数一进制存储格式,这些格式都出自由IEEE组织制定的标准754-1985:二进制浮点数运算:

●32位单精度数值包含1位符号、8位阶码,以及23位有效数字的小数部分。

●64位双精度数值包含1位符号、11位阶码,以及52位有效数字的小数部分。

●80 位扩展双精度数值包含1位符号、16 位阶码,以及 63 位有效数字的小数部分。

若符号位为 1,则数值为负数;若该位为 0,则数值为正数。

浮点数的有效数字由小数点左右两边的十进制数字构成。

并非所有处于0到1之间的实数都可以在计算机内表示为浮点数,其原因是有效位的个数是有限的。

规格化有限数是指,能够编码为0到无穷之间的规格化实数的所有非零有限数值。正无穷(+∞)代表最大正实数,负无穷(-∞)代表最大负实数。NaN 为位模式,不表示有效浮点数。

Intel 8086 处理器被设计为只处理整数运算,因此 Intel 提供了独立的 8087 浮点数协处理器(floating-pointcoprocessor)芯片与8086一起置于计算机的主板上。随着Intel486的出现,浮点操作被整合到主 CPU 内,称为浮点单元(FPU)。

FPU 有 8 个相互独立的可寻址的 80 位寄存器,分别命名为RO~R7,它们构成一个寄存器堆栈。在计算时,浮点操作数以扩展实数的形式保存在FPU 堆栈中。内存操作数也可以用于计算。FPU 在把算术运算操作的结果保存到内存时,会把结果转换为下述格式之一:整数、长整数、单精度数、双精度数或者 BCD 码。

Intel 浮点指令助记符用字母F开始,以区别于 CPU 指令。指令的第二个字母(通常为B或I)表示如何解释内存操作数:B表示为操作数为二进制编码的十进制数(BCD 码),I表示操作数为二进制整数。如果没有指定,那么内存操作数就假设为实数格式。

Intel 8086 是第一个使用复杂指令集计算机(CISC)设计的处理器。其庞大的指令集包含了各种各样的内存寻址、移位、算术运算、数据传送和逻辑操作。

指令编码是指把汇编语言指令及其操作数转换为机器码。指令解码是指将机器码指令转换为汇编语言指令及操作数。

x86机器指令格式包含一个可选的前缀字节、一个操作码字段、一个可选的Mod R/M字节、若干可选的立即数字节,以及若干可选的内存偏移量字节。具备全部这些字段的指令很少。前缀字节覆盖了目标处理器默认的操作数大小。操作码字段是指令独一无二的操作编码。Mod R/M 字段指定了寻址模式和操作数。在使用寄存器操作数的指令中,Mod R/M 字节用一个3位标识符来表示每个寄存器操作数。

12.5 关键术语

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94738.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94738.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/94738.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3通过按钮实现横向滚动、鼠标滚动横坐标滚动

效果图&#xff1a;可点击左右文字进行滚动、或通过滚动鼠标 内容左右滚动<template><div class"Home"><div style"display: flex;height: 100%;align-items: center;"><div click"scrollLeft()" style"width: 80px;t…

【Agent】AutoGen:LLM驱动的多Agent对话框架

文章目录一、AutoGen简介1.1 AutoGen的特点1.2 AutoGen的实现1.2.1 可对话Agent1.2.2 对话编程二、基于AutoGen构建多智能体系统2.1 构建步骤2.1 协作模式2.2 通信模型2.3 人机协同2.4 具体示例参考资料一、AutoGen简介 AutoGen是微软推出的一个Multi-Agent框架&#xff0c;允…

乙巳年闰六月十六凌晨感怀

乙巳年闰六月十六凌晨感怀 一段历程一段情&#xff0c;儿郎峥嵘儿郎行。 岁月流金建功业&#xff0c;春秋风尚能潮赢。 路途苦乐人生度&#xff0c;评说成败当下名。 百年孤寂留水墨&#xff0c;千载独步守安宁。

Redis 分布式Session

一、引入依赖引入spring-session-data-redis依赖&#xff0c;不需要指定version&#xff0c;默认和springboot的version保持一致<!-- Spring Session Redis --> <dependency><groupId>org.springframework.session</groupId><artifactId>spring…

JAVA实现附件分片上传

项目需求由于文件服务器的限制&#xff0c;单次调用文件上传接口上传的附件的大小不能超过500MB&#xff0c;对于超过500MB的附件需要分片上传程序示例private Boolean uploadFile(File uploadFile, String uploadUrl, List<Object> fileList) {final long CHUNK_SIZE 5…

PyTorch环境安装

pytorch安装 建议&#xff08;非常强烈的那种&#xff09;用Anaconda创建一个虚拟环境&#xff0c;用于运行安装你的PyTorch conda create -n universal python3.9 1. 基础认知 cuDNN&#xff08;CUDA Deep Neural Network library&#xff09;是 NVIDIA 开发的用于深度学习…

机场风云:AI 云厂商的暗战,广告大战一触即发

文 | 大力财经机场广告牌背后&#xff0c;一场决定云计算未来格局的隐形战争已悄然打响。当你匆匆走过首都机场T3航站楼的通道&#xff0c;巨幅屏幕上“阿里云&#xff1a;开源的力量”与不远处“百度智能云&#xff1a;AI落地领导者”的广告交相辉映。它们精准锁定着日均10万的…

MLE-STAR:谷歌AI推出的机器学习工程新范式,一种搜索驱动、精准优化的智能代理

最近看到 Google AI 发布了一个叫 MLE-STAR&#xff08;Machine Learning Engineering via Search and Targeted Refinement&#xff09;的新系统&#xff0c;说实话&#xff0c;第一眼看完论文和相关介绍后&#xff0c;我是有点震撼的。这不只是一次简单的“LLM 自动化”拼凑…

3-防火墙

防火墙 一 防火墙概述防火墙概述防火墙是一个位于内部网络与外部网络之间的安全系统&#xff08;网络中不同区域之间&#xff09;&#xff0c;是按照一定的安全策略建立起来的硬件或软件系统&#xff0c;用于流量控制的系统&#xff08;隔离&#xff09;&#xff0c;保护内部网…

python opencv 调用 海康威视工业相机(又全又细又简洁)

1.准备工作 准备一个海康相机 下载MVS 和SDK 海康机器人-机器视觉-下载中心 2.python MVS示例 &#xff08;说明&#xff1a;MVS里有很多python示例&#xff0c;可以直接运行&#xff0c;但没有用opencv&#xff09; 下载完MVS后&#xff0c;我们打开路径安装路径 我的&#…

计算机基础·linux系统

Finalshell 用于远程操控vmware中的linux系统 获取虚拟机的IP地址 ifconfig命令&#xff0c;重启系统后IP地址可能会变化&#xff01;问题&#xff1a;vmware子系统没有网络连接 winRservices.msc启动这些服务问题&#xff1a;配置正确但是finalshell连接失败 更新子系统中的ss…

8.结构健康监测选自动化:实时数据 + 智能分析,远超人工

第一次接触结构健康自动化监测系统&#xff0c;感觉成本很高&#xff0c;比人工好在哪里&#xff1f; 人工检测是依靠目测检查或借助于便携式仪器测量得到的信息&#xff0c;但是随着整个行业的发展&#xff0c;传统的人工检测方法已经不能满足检测需求&#xff0c;从人工检测到…

【慕伏白】Android Studio 配置国内镜像源

文章目录配置HTTP代理修改 gradle 镜像地址修改 maven 镜像源重新同步配置HTTP代理 进入File --> Settings --> Appearance & Behavior --> System Settings --> HTTP Proxy 勾选 Auto-detect proxy settings --> Automatic proxy configuration URL &…

Spring Cloud系列—LoadBalance负载均衡

上篇文章&#xff1a; Spring Cloud系列—Eureka服务注册/发现https://blog.csdn.net/sniper_fandc/article/details/149937589?fromshareblogdetail&sharetypeblogdetail&sharerId149937589&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link …

如何使用 pnpm创建Vue 3 项目

✅ 一、什么是 pnpm&#xff1f; pnpm 是一种更快、更高效的 Node 包管理工具&#xff0c;替代 npm 或 yarn&#xff0c;具有&#xff1a; 更快的安装速度更节省磁盘空间&#xff08;包复用&#xff09;严格的依赖管理二、使用 pnpm 创建 Vue 项目的完整流程 ✅ 第一步&#xf…

Vite vs. vue-cli 创建 Vue 3 项目的区别与使用场景

Vite vs. vue-cli 创建 Vue 3 项目的区别与使用场景 Vite 和 vue-cli 都是 Vue 官方推荐的脚手架工具&#xff0c;但它们的架构、构建方式和适用场景有所不同。以下是它们的对比&#xff1a;1. 核心区别对比项Vite (推荐&#x1f525;)vue-cli (传统)构建工具基于 ESM Rollup基…

VC6800智能相机:赋能智能制造,开启AI视觉新纪元

在工业自动化与智能化浪潮奔涌的今天&#xff0c;精准、高效、智能的视觉检测已成为提升生产力和品质的关键核心。VC6800智能相机应运而生&#xff0c;它不仅仅是一部相机&#xff0c;更是一个集强大视觉硬件与前沿AI算法于一身的 “工业智眼”&#xff0c;正深刻改变着各个领域…

(Python)Python爬虫入门教程:从零开始学习网页抓取(爬虫教学)(Python教学)

一、爬虫基础概念 什么是爬虫&#xff1f; 网络爬虫&#xff08;Web Crawler&#xff09;是一种自动获取网页内容的程序&#xff0c;它像蜘蛛一样在互联网上"爬行"&#xff0c;收集和提取数据。 爬虫应用场景&#xff1a; 搜索引擎&#xff08;Google、百度&#…

dify前端源码部署详细教程

这两天突发奇想&#xff0c;能不能dify源码部署我只部署个前端&#xff0c;后端、数据库什么的还是原来docker部署dify的本地部署和遇到的问题。按逻辑来说应该是行得通的&#xff0c;我就亲自操作了下试下。 我这边就以我以前使用docker部署好的1.3.1版本为例。docker安装参考…

Web地图服务规范,WMS服务是什么

Web地图服务规范&#xff0c;WMS服务是什么&#xff1f; WMS&#xff0c;全称 Web Map Service (网络地图服务)&#xff0c;是有OGC(开放地理空间信息联盟)制定的一项标准化协议。他的核心功能是允许客户端&#xff08;比如网页浏览器或者GIS桌面软件&#xff09;通过互联网或者…