为什么我们不能将数据直接从内存位置移动到另一个内存位置。
请原谅我,如果我问一个愚蠢的问题,但我认为这是一个真实的情况,至少对于我遇到的问题(8085,8086 n 80386)
我并不是在寻找移动数据的解决方案(例如,使用movs n all),但实际上是造成这种异常的原因。
答案 0 :(得分:5)
MOVS怎么样?它将esi寻址的8/16/32位值移动到edi。
寻址的位置答案 1 :(得分:4)
基本原因是大多数指令集允许一个寄存器操作数和一个内存操作数,并且坚持这种格式使得设计指令解码器更容易。它还使CPU内部的执行引擎更容易,因为该指令通常只能向一个存储器位置发出存储器操作,并且最多只能读取或写入一个寄存器块。
直接执行内存到内存指令需要指定两个内存位置。鉴于寄存器/存储器指令格式,这很尴尬。鉴于机器的性能,没有理由为此修改指令格式。
更现代的CPU使用的hack是提供某种类型的块移动指令,其中源和目标位置位于寄存器中(对于X86,这分别是ESI和EDI)。然后一个指令可以指定两个寄存器(或者在x86的情况下,指令只是知道哪个寄存器)。这解决了解码指令的问题。
指令执行问题有点难,但人们有很多晶体管。组织一个读取间接从一个寄存器,并间接写入另一个寄存器,并增加两者是硅的尴尬,但这只是咀嚼一些晶体管。 现在你可以有一个从内存移动到内存的指令,就像你问的那样。 在X86中注意到的另一个海报中有一些指令(MOVB,MOVW,MOVS,......)正是这样做的,一次只有一个内存字节/字/ ....
移动块的内存将是理想的,因为CPU可以生成高带宽读写。 x86使用MOV上的REP(重复)前缀来移动更大的块。
但是,如果单个操作可以做到这一点,那么你可能需要花费很长时间才能执行(移动1Gb需要多长时间? - >数百万个时钟周期!)并且会破坏中断响应率CPU。
x86通过允许REP MOV-中断来解决这个问题,将PC设置回指令的开头。通过在移动期间适当更新寄存器,可以中断并重新启动具有快速块移动和高中断响应速率的REP MOV指令。管内有更多晶体管。
RISC人员发现块移动指令的所有这些复杂性大多不值得。你可以编写一个哑循环(甚至是x86):
copy: MOV EAX,[ESI]
ADD ESI,4
MOV [EDI],EAX
ADD EDI,4
DEC ECX
JNE copy
与REP MOV-具有相同的基本功能。几乎现代的CPU(x86,其他)执行这个所以快速(超标量等),总线就像自定义移动指令一样,但现在你不需要浪费所有这些晶体管(或相应的热量)。
答案 2 :(得分:3)
大多数CPU品种不允许内存到内存的移动。通常情况下,CPU一次只能访问一个内存位置,这意味着在移动它时需要一个临时点来存储该值(通常是通用寄存器)。如果你考虑一下,直接从一个内存位置移动到另一个内存位置需要CPU能够同时访问RAM中的两个不同位置 - 这意味着至少有两个完整的内存控制器,即使这样,他们“玩”的机会也是如此很好“足以访问相同的RAM将是非常糟糕的。芯片设计人员可能已经能够采用一些技巧来允许从一个RAM芯片直接复制到另一个RAM芯片,但这将是一种非常特殊的应用类型的功能,只会增加成本和复杂性来解决一个非常罕见的问题。
您可能可以使用一些特殊的DMA硬件来使其适合您的程序,例如在没有临时存储的情况下移动内存,至少从CPU的角度来看。
答案 3 :(得分:2)
您有一组地址线,一组数据线,以及CPU和RAM之间的一些控制线。如果没有第二组地址线和RAM内部的大量复杂逻辑,则无法直接从内存移动到内存。因此,我们必须暂时将其存储在注册表中。
你可以制作一个加载和存储在一起的指令,看起来像程序员的一条指令,但还有其他考虑因素,如指令大小,有效地址计算逻辑的非重复,流水线等,这些都是令人满意的保持简单。
答案 4 :(得分:1)
内存内存机器通常比负载存储机器慢。这是由RISC研究人员在1980年左右推断/发明/发明的。因此,旧架构(VAX / OS360)往往具有内存内存架构;较新的机器会加载存储。
另一个有趣的变体是堆叠机器;他们似乎永远是少数人。