Assembly 8086内存到内存指令。他们存在的目的是什么?
据我所知,8086指令有3种关于数据移动的指令集:Assembly 8086内存到内存指令。他们存在的目的是什么?,assembly,x86,intel,x86-16,Assembly,X86,Intel,X86 16,据我所知,8086指令有3种关于数据移动的指令集: 要注册的内存 寄存器到内存 登记 然而,昨天我发现了一些指令集,如and, 在使用这些指令时,内存对内存(M2M)操作是可能的 现在,我很好奇为什么会有M2M指令存在。 我发现使用它们有很多限制 这些指令消耗大量CPU周期 这些指令要求使用段寄存器作为操作数。 这些M2M操作也可以通过组合上述1、2、3种指令来运行 问题: 我很难同意这些M2M指令的存在。 这些是否仅用于生成较短的装配代码 movs*和cmps*指令非常方便,因为它们允许
在使用这些指令时,内存对内存(M2M)操作是可能的 现在,我很好奇为什么会有M2M指令存在。
我发现使用它们有很多限制
- 这些指令消耗大量CPU周期
- 这些指令要求使用段寄存器作为操作数。
我很难同意这些M2M指令的存在。
这些是否仅用于生成较短的装配代码 movs*和cmps*指令非常方便,因为它们允许您执行复制数据和比较数据等常见任务
ins*
和out*
本质上类似于mov*
,它们只是在内存和I/O设备之间移动数据。它们对于在完整扇区(通常为512字节)中读取/写入磁盘特别有用。当然,DMA消除了这些,因为基于DMA的I/O效率更高,但在当时,它们并不像今天那样普遍
模拟这些指令(特别是它们的重复形式(查找rep
prefix))需要更多的代码,速度也会更慢。因此他们的存在
顺便说一句,目标在内存中的xchg
指令和任何其他读-修改-写指令(例如add
)也是有效的内存对内存指令。并非所有CPU都有这些功能,许多CPU主要提供从内存读取或写入内存的指令,但并非两者都有(例外情况是用于实现对内存的独占/原子访问的指令,比如xchg
,xadd
,cmpxchg8/16
)。具有此类指令集的CPU属于所谓的负载存储体系结构
另外,push
和pop
指令可能会让它们的显式操作数指定内存位置。这是另一种形式的内存对内存指令
至于段,几乎所有读取或写入内存的指令都涉及段(某些系统指令的工作方式不同),因此,如果您决定不使用您提到的指令,而选择其他指令,则段管理和开销不是您可以避免的。架构师已经论证,一些常见的高级功能可以在硬件中得到支持。因此,
movsb
可以实现memcpy
和friends,outsb
在对缺少足够辅助硬件的哑设备执行IO时非常有用(这在过去是常见的情况)。当然,这不是一个原创的想法或东西-在RISC运动出现之前,这种指令在任何地方都很常见(除了非常小的8位“micro”)。注意:只有8088/8086有内存移动,早期PC时代的8237 DMA芯片包括内存到内存的传输功能,使用频道0作为源,频道1作为目标。@rcgldr哦,哇,我不知道。有人真的用过这个功能吗?@fuz-我没用过。我似乎记得它在我工作的一家公司进行测试,可能是在20世纪80年代对各种台式机上的dma内存移动和/或cpu内存移动进行基准测试,以了解内存带宽。所有内存操作数都有一个段寄存器,无论是显式指定的还是隐式的。相关:列出具有两个独立内存操作数的指令,不是同一操作数的RMW。少数加载存储ISA也有原子交换(例如)和/或CA,但大多数RISC ISA只支持solock add
转换为重试循环。(仅compare_exchange_weak不需要循环,因为它允许在争用时失败,而不仅仅是数据差异)。LL/SC在中断延迟方面具有优势,因为它基本上使原子事务可中止。您可以(在一个位置上)实现任何原子操作,但也可以对CAS重试循环执行相同的操作。LL/SC确实可以更容易地避免ABA问题。。。不管怎么说,别谈这个话题了。LL/SC仍然是两条单独的指令,每一条指令只加载或只存储。但是它们链接在一起作为RMW事务提交,因此它们解决了与8086xchg
或更高版本的x86lock-cmpxchg
/lock-add
/lock-xadd
/etc相同的问题,使同时处理2个段变得容易,而不会使用段覆盖前缀使代码膨胀。代码大小对8086的性能至关重要。