为什么LOOP在8086上比DEC,JNZ快?

2023-12-31

我的教授声称 LOOP 在 8086 上更快,因为只获取一条指令而不是两条指令,就像dec cx, jnz。所以我认为我们通过避免每次迭代的额外获取和解码来节省时间。

但在讲座的早些时候,他还提到 LOOP 在底层与 DEC、JNZ 做同样的事情,我认为它的解码也应该更复杂,所以速度差异应该可以平衡。那么,为什么LOOP指令更快呢?我经历了这个帖子 https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently,并且那里的答案与比 8086 更现代的处理器有关,尽管one https://stackoverflow.com/a/43846925答案(及其链接的页面)确实指出在 8088(与 8086 密切相关)上,LOOP 更快。

后来教授用同样的推理来解释为什么rep字符串操作可能比 LOOP + 单独的移动指令更快,但由于我并不完全相信以前的方法,所以我在这里问了这个问题。


这不是解码的问题,通常是在 8086 上获取。

启动两个单独的指令解码操作可能比仅为一个获取更多微代码更昂贵loop操作说明。我猜这就是下表中不包括代码获取瓶颈的数字的原因。

同样或更重要的是,8086 经常受到内存访问(包括代码获取)的瓶颈。 (8088 几乎总是如此,它的 8 位总线像吸管一样呼吸,这与 8086 的 16 位总线不同)。

dec cx是1个字节,jnz rel8是2个字节。
总共 3 个字节,而 2 个字节loop rel8.

8086性能可以通过计算内存访问次数并乘以四来近似 https://retrocomputing.stackexchange.com/questions/3255/when-specifying-intel-80x86-instruction-execution-time-what-is-included-in-the/3292#3292,因为其 6 字节指令预取缓冲区允许其将代码获取与其他指令的解码和执行重叠。 (除了非常慢的指令,例如mul这将使缓冲区在最多 3 次 2 字节读取后填满。)

也可以看看提高 8086 二进制 -> 格雷码的效率 https://stackoverflow.com/questions/67400133/increasing-efficiency-of-binary-gray-code-for-8086有关针对 8086 进行优化的示例,以及指向更多资源(例如指令时序表)的链接。

https://www2.math.uni-wuppertal.de/~fpf/Uebungen/GdR-SS02/opcode_i.html https://www2.math.uni-wuppertal.de/%7Efpf/Uebungen/GdR-SS02/opcode_i.html有 8086 的指令时序(我认为取自英特尔手册,如 njuffa 的答案中引用的那样),但这些是only当获取不是瓶颈时执行。 (即仅从预取缓冲区进行解码。)

解码/执行时序,不包括获取:

DEC     Decrement

    operand     bytes   8088    186     286     386     486     Pentium
    r8           2       3       3       2       2       1       1   UV
    r16          1       3       3       2       2       1       1   UV
    r32          1       3       3       2       2       1       1   UV
    mem       2+d(0,2)  23+EA   15       7       6       3       3   UV

Jcc     Jump on condition code

    operand     bytes   8088    186     286     386     486     Pentium
    near8        2      4/16    4/13    3/7+m   3/7+m   1/3     1    PV
    near16       3       -       -       -      3/7+m   1/3     1    PV
LOOP    Loop control with CX counter

      operand   bytes   8088    186     286     386     486     Pentium
      short      2      5/17    5/15    4/8+m   11+m    6/7     5/6  NP

因此,即使忽略代码获取差异:

  • dec+ 采取jnz在 8086 / 8088 上解码/执行需要 3 + 16 = 19 个周期。
  • taken loop在 8086 / 8088 上解码/执行需要 17 个周期。

(采取的分支在 8086 上很慢,并且丢弃预取缓冲区;没有分支预测。我不知道这些计时是否包括任何这种惩罚,因为它们显然不适用于其他指令和非采取的分支。)

除代码预取缓冲区外,8088/8086 不采用流水线方式。完成一条指令的执行并开始下一条指令的解码/执行需要一些时间;即使是最便宜的说明(例如mov reg,reg/ 移动 / 旋转 /stc/std/等)需要2个周期。奇怪的是超过nop(3 个周期)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么LOOP在8086上比DEC,JNZ快? 的相关文章

  • VirtualStringTree 正确/推荐使用

    我已经使用 virtualstringtree 一段时间了 我将它用于两个不同的用途 第一个是用于选择 显示数据的普通树 第二个是作为网格来显示 SQL 语句的输出 我加载到树中的所有数据都来自数据库 对于树示例 我有一个 ParentId
  • php 日期函数和 Carbon 哪个更快?

    Carbon 是 DateTime 的简单 PHP API 扩展 我想知道我们可以通过 Composer 安装 Carbon 来使用日期时间函数 php 日期时间函数和 Carbon 哪个更快 我对您的评论做了一些测试 比较了 DateTi
  • 将 XMM 寄存器压入堆栈

    有没有办法将打包双字整数从 XMM 寄存器推送到堆栈 然后在需要时将其弹出 理想情况下 我正在寻找通用寄存器的 PUSH 或 POP 之类的东西 我已经检查了英特尔手册 但我要么错过了命令 要么没有 或者我是否必须将值解压到通用寄存器然后推
  • 为什么 mov %ax, %ds 汇编+反汇编为 mov %eax,%ds,与原来不一致?

    test S text global start start xor ax ax mov ax ds mov ax ss mov ax es mov ax fs mov ax gs 我通过这样做得到了反汇编代码文件 x86 64 elf g
  • 如何提高Canvas渲染性能?

    我必须画很多Shape http msdn microsoft com en us library system windows shapes shape aspx 约 1 20 万 作为 Canvas 2 的子级 我在 WPF 应用程序中
  • 嵌入式系统:使用汇编语言时的内存布局

    根据我的理解 嵌入式系统运行机器代码 有多种方法可以生成此代码 一种是用 C 等高级语言编写程序 然后使用编译器获得这样的代码 另一种方法是用汇编语言为该嵌入式系统编写指令 并使用汇编器将其转换为机器代码 现在我们得到了加载到系统并执行的机
  • C++,最佳实践,int 还是 size_t? [复制]

    这个问题在这里已经有答案了 可能的重复 何时使用 std size t https stackoverflow com questions 1951519 when to use stdsize t hello 假设使用模式相同 即没有负数
  • 您使用什么来通过其自定义协议来测试(功能/负载/压力)您的网络服务?

    我最近创建了一个回合制游戏服务器 可以接受数十万个并发客户端连接 长话短说 Linux 上的 epoll 通信基于简单 定制 基于线路的协议 该服务器允许客户端连接 寻找游戏比赛中的其他玩家 玩所述游戏 发送动作 聊天消息等 并在游戏结束时
  • 为什么 LED 保持亮起而不是闪烁?

    这是使用 pic16f676 中的 TIMER0 中断使 LED 闪烁的 MPASM 代码 端口 A 的引脚 0 RA0 未切换至关闭位置 请帮忙 我是图片组装的新手 我想掌握图片 有没有高手帮我学习一下 我需要以 1 秒的间隔眨眼 代码是
  • 方法与管道

    在 Angular 应用程序中的模板插值中使用管道和方法有区别吗 例如 h1 name toLowerCase h1 vs h1 name lowercase h1 就性能而言 是有真正的收获还是只是个人喜好 我知道调用模板中的方法通常会降
  • 在 qemu 中将扇区加载到 RAM

    我编写了一个简单的程序 将扇区 扇区编号 2 加载到 RAM 但什么也没打印 首先 我尝试了以下引导扇区代码 org 0x7c00 mov ax 0x1000 ES BX 1000 0000 mov es ax mov bx 0x00 Lo
  • mclapply 用户时间大于已用时间

    我正在尝试使用mclapply的功能parallel封装在R 该函数通过计算对数似然距离将值分配给序列矩阵 这是一个 CPU 密集型操作 所结果的system time价值观令人困惑 gt system time mclapply work
  • 如何优化 R 中的 sapply 来计算数据帧上的运行总计

    我在 R 中编写了一个函数来按月份计算累积总数 但随着数据集变大 我的方法的执行时间呈指数增长 我是一名 R 程序员新手 你能帮我提高效率吗 该函数以及我调用该函数的方式 accumulate lt function recordnum d
  • NASM:如何正确访问SSD驱动器?

    我需要使用 NASM 16 位代码访问 SSD 驱动器 访问普通硬盘时 需要设置寄存器AX DX CX来选择柱面 磁道 扇区 扇区数 AH 选择读扇区功能 DL 选择驱动器号 CH 选择气缸 DH 选择磁盘上的一侧 CL 选择步入正轨的部门
  • 如何在汇编中使用 ReadString?

    mov edx offset Prompt1 call WriteString mov ecx 32 mov edx offset String1 call ReadString 现在 我该如何访问String1 如何将其移入寄存器以便对其
  • 在共享库中不使用 PLT 的情况下调用另一个目标文件中的函数?

    我有两个汇编代码 code1 s and code2 s我想从这两个构建一个可重定位 使用 fPIC 开关 共享库 I want code2 s调用一个函数 名为myfun1 其定义在code1 s 当我使用call myfun1 PLT
  • C++ OpenCV imdecode 慢

    我将图像的字节数组从 C 发送到 C 库 我使用 OpenCV 版本 3 3 1 解码图像 BMP 图像解码速度很快 但 JPEG 图像解码速度很慢 如何加快 JPEG 图像的解码时间 多线程 GPU 解码性能 Resolution For
  • 由于内容不可压缩,谷歌浏览器中出现了新的复合层

    当 chrome profiler 说 图层是单独合成的 因为它无法被挤压 时 它到底意味着什么 我正在对我的 html 进行更改 并在相对 div 内引入了一个固定位置 div 并给出了will change transform在上面 完
  • 如何使用 Java2D 创建硬件加速图像?

    我正在尝试创建一个快速图像生成器 它可以执行大量 2d 转换和形状渲染 因此我尝试使用 BufferedImage 然后获取 Graphics2D 对象来执行所有绘图 我现在主要关心的是 make 速度非常快 所以我创建一个像这样的 Buf
  • 用 OpenCL C 编写快速线性系统求解器

    我正在编写一个 OpenCL 内核 它将涉及求解线性系统 目前我的内核太慢了 提高线性系统部分的性能似乎是一个不错的起点 我还应该注意 我并没有尝试使我的线性求解器并行 我正在研究的问题在宏观层面上已经是令人尴尬的并行 以下是我编写的 C

随机推荐

  • 使用 Qt C++ QWebView 会导致 GUI 运行缓慢。

    当页面通过 QWebView 加载时 我注意到程序的其他元素开始运行缓慢 特别是 GUI 解决这个问题的最佳解决方案是什么 我不能说在使用时用户界面的其余部分有任何明显的减慢QWebView 即使是在动力相当不足的 SBC 上 我想知道是否
  • 对 Amazon S3 的写入是否是原子的(全有或全无)?

    我正在向 S3 读取和写入大量文件 我只是想知道是否需要针对文件 写了一半 的情况进行编码 例如S3 PUT Write 仅 一半 有效 或者写入 S3 是全有还是全无 我知道存在读写最终一致性问题 我认为 这在很大程度上是一个单独的问题
  • 如何使SeparatedListAdapter的节标题在滚动时推动上一节?

    我正在使用分离列表适配器 下一个节的标题到达顶部时 节标题突然发生变化 对于 iOS 应用程序 下一个部分的标题会向上推旧的部分标题并占据其位置 如何在Android应用程序中实现它 有什么帮助吗 Here http code google
  • 可以在源代码中添加有关错误修复的注释吗?

    如果是这样 你在哪里划清界限 我和我的同事在这个问题上存在分歧 我见过这样的事情 fixes bug 22 to fixed bug shouldnt be decrementing i 如果更改相当显着并且从根本上改变了该方法的编写目的
  • 调试器不会因错误而停止

    我正在使用 Visual Studio 2012 开发 Asp net MVC4 项目 当调试过程中出现错误时 它通常会在错误处停止 但突然间 调试器并没有停止 只是吐出如下错误信息网页 应用程序中的服务器错误 字典中不存在给定的键 描述
  • 使用jedis管道获取值

    我有一个 id 列表 我想用它来使用 java 客户端 jedis 从 Redis 服务器检索哈希值 正如文档中提到的 Jedis 提供了一种通过声明 Response 对象来使用管道的方法 然后同步管道以获取值 Pipeline p je
  • Active Storage Rails 5.2 出现 Blob 错误

    我刚刚升级了5 1 4 应用程序升级到 5 2 并尝试将 Paperclip 替换为 ActiveStorage 目前 当尝试使用图像更新现有记录时 出现以下错误 无法自动加载常量 ActiveStorage Blob Analyzable
  • 如何将 unicode 数字转换为整数?

    阿拉伯语和中文有自己的数字字形 int适用于所有不同的数字书写方式 我无法重现该行为 python 3 5 0 gt gt gt from unicodedata import name gt gt gt name RUMI DIGIT F
  • sql中如何存储树形结构?

    这是我使用 sqlite 的模式 我不确定这是否是在 sql 中创建树结构的好方法 因为我必须遍历很多次才能获取整个树 而不是根据顶部注释提取整个树并构建python 中的树 有人可以给我一些建议吗 BEGIN CREATE TABLE t
  • 如何使用 Castle ActiveRecord 在保存或更新期间自动填充字段

    问题 我们数据库中的所有表都有 CreatedDate CreatedBy ChangedDate ChangedBy 字段 我希望在保存 更新 ActiveRecord 实体时自动设置这些字段 我的第一次尝试是重写 Save 和 Upda
  • 订购 PHP 数组

    我有一个 php 数组 带有注释 必须以不同的方式排序 数组内容的顺序应该是这样的 parent child child child parent child child etc 父评论有 parent 0 子评论具有其父评论的 ID 例如
  • 如何在 Ubuntu 上的 GTK3 (GI) 和 Python 3 中获取剪贴板内容

    在 Python 2 中 通过我的机器 Ubuntu 12 10 中安装的内容 我可以执行以下操作 import gtk cb gtk clipboard get content cb wait for text 从剪贴板获取文本 然而 在
  • 规避“catch_warnings”上下文管理器错误,该错误会重置警告注册表,导致无限打印警告

    在我正在使用的模块深处 xarray 但这并不重要 catch warnings上下文管理器导致警告被一遍又一遍地打印 而不是像它应该的那样只打印一次 如果没有这样的上下文管理器 行为将如预期 cat mwe py usr bin env
  • 如何将 g++ 从 MinGW 添加到 PATH

    我在 Windows 10 上使用 Visual Studio Code 并尝试构建一个程序 称为Bus从源文件Bus cpp 与来自 MinGW 的 g 我使用从之前的线程中读取的各种方法修改了tasks json 文件 我提供了task
  • PHP 和“打开”mysqli

    我无法找到有关如何 打开 mysqli 的文档 我正在运行 OS X SL 据我了解 由于安装了 php5 mysqli 扩展也应该已经存在 这就像在 php ini 中添加 LoadModule 行一样简单吗 如果我需要重新编译 php
  • 使用 Google API 的 Chrome 清单

    我需要一些关于如何获取扩展的 chrome 清单以允许服务器和应用程序之间进行 Google API 对话的建议 当我直接指向应用程序 而不是扩展 时 应用程序加载正常 但是我的问题是 当我将其作为扩展加载时 出现以下错误 Refused
  • Oracle 查询作为 SSIS 中的源定义了错误的数据类型

    我有一个有点复杂的查询 我想将其用作 SSIS 包中的源 我创建 OLE DB 源 将访问模式指定为 SQL 并将查询粘贴到命令文本框中 当我单击 预览 时 示例数据会返回 一切看起来都很好 但是 当我尝试运行该包时 我收到 外部列与数据源
  • 当我使用 -std=gnu99 编译时,我还应该定义 _GNU_SOURCE 吗?

    我使用了一些 GNU 扩展 并意识到如果我将 gnu99 设置为 C 标准来使用 我可以省略 define GNU SOURCE gnu99 是否暗示 GNU SOURCE 或者使用它是否仍然更安全或强制以避免问题 您应该区分语言和库功能
  • IE7 中的开发人员工具可查看控制台日志消息

    在 IE 8 中 我看到了一个开发人员工具部分 并且能够访问其 javascript 控制台并查看我在其中编写的控制台日志 但我在 IE 7 中找不到这样的东西 它在哪里 有吗 我只想在 IE 7 中查看控制台日志命令的输出 开发人员工具已
  • 为什么LOOP在8086上比DEC,JNZ快?

    我的教授声称 LOOP 在 8086 上更快 因为只获取一条指令而不是两条指令 就像dec cx jnz 所以我认为我们通过避免每次迭代的额外获取和解码来节省时间 但在讲座的早些时候 他还提到 LOOP 在底层与 DEC JNZ 做同样的事