gri*_*m14 1 x86 assembly cpu-architecture
这是在合并流水线和您需要的必要NOP时实现mov和通过x86添加的正确方法.
mov $10, eax
NOP
NOP
NOP
add $2, eax
Run Code Online (Sandbox Code Playgroud)
如果我想用mov更改eax,我可以立即用另一个mov覆盖它,因为你只是覆盖已经存在的内容,或者我是否需要再次写3个NOP才能完成WMEDF循环?
mov $10, eax
mov $12, eax
Run Code Online (Sandbox Code Playgroud)
要么
mov $10, eax
NOP
NOP
NOP
mov $12, eax
Run Code Online (Sandbox Code Playgroud)
这是在合并流水线和您需要的必要NOP时实现mov和通过x86添加的正确方法.
x86完全不正确.在x86 1上永远不需要NOP 来保证正确性.
如果输入没有为指令做好准备,它将等待它准备就绪.(乱序执行可以隐藏这个并行等待多个依赖链...
我想我已经读过一些架构有一些指令,如果你太快阅读结果,你会得到不可预测的值.这只是针对一些指令(可能是多次),并且许多架构没有任何在架构上需要NOP(或对其他寄存器有用的工作)的情况.
简单的有序流水线上的正常情况(如缓存未命中负载)通过流水线互锁来处理,如果需要,可以在硬件中有效地插入NOP,而无需软件包含会降低高性能(无序)的无用指令运行相同二进制文件的相同体系结构的实现.
或者我是否需要再次写3个NOP才能完成WMEDF循环?
x86 ISA不是围绕经典RISC管道设计的(如果这是缩写应该表示的话).因此,即使是标量的有序流水线x86实现,如i486,它们在内部类似于你所想的,必须处理不使用NOP来创建延迟的代码.即他们必须自己检测数据依赖性.
当然,现代x86实现都至少有2个超标量(旧的Atom pre-Silvermont,或第一代Xeon Phi,或P5 Pentium).这些CPU是按顺序的,但其他CPU是完全寄存器重命名(Tomasulo的算法)乱序,这避免了像你所说的那样的写后写入危险.例如,Skylake可以运行
mov $10, %eax
mov $11, %eax
mov $12, %eax
mov $13, %eax
...
eventually jcc to make a loop
Run Code Online (Sandbox Code Playgroud)
mov每个周期4个指令,即使它们都写入相同的寄存器.
但请注意,mov $1, %al合并到%rax除Intel P6系列之外的CPU(PPro/PII到Core2/Nehalem),以及Sandybridge(但不是后来的像Haswell这样的CPU).在具有部分寄存器重命名为低8的CPU上,mov $1, %al每个周期可以运行多个指令(受ALU端口限制).不过别人,它就像一个add到%rax.请参阅Haswell/Skylake上的部分寄存器究竟如何执行?写AL似乎对RAX有假依赖,而AH是不一致的.(有趣的是,mov %bl, %ahSkylake每次重复运行4次,mov $123, %ah每次重复运行1次.)
进一步阅读:
脚注:
| 归档时间: |
|
| 查看次数: |
105 次 |
| 最近记录: |