Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在流水线过程中,您可以连续地将mov写入同一寄存器,还是像add一样需要3个NOP?_Assembly_X86_Cpu Architecture - Fatal编程技术网

Assembly 在流水线过程中,您可以连续地将mov写入同一寄存器,还是像add一样需要3个NOP?

Assembly 在流水线过程中,您可以连续地将mov写入同一寄存器,还是像add一样需要3个NOP?,assembly,x86,cpu-architecture,Assembly,X86,Cpu Architecture,这是通过x86实现mov和add的正确方法,可用于合并管道和所需的NOP mov $10, eax NOP NOP NOP add $2, eax 如果我想用mov更改eax,我是否可以立即用另一个mov覆盖它,因为您正在覆盖已经存在的内容,或者我是否需要再次写入3个NOP,以便它可以完成WMEDF循环 mov $10, eax mov $12, eax 或 这是通过x86实现mov和add的正确方法,可用于合并管道和所需的NOP mov $10, eax NOP NOP

这是通过x86实现mov和add的正确方法,可用于合并管道和所需的NOP

 mov $10, eax
 NOP 
 NOP
 NOP
 add $2, eax
如果我想用mov更改eax,我是否可以立即用另一个mov覆盖它,因为您正在覆盖已经存在的内容,或者我是否需要再次写入3个NOP,以便它可以完成WMEDF循环

mov $10, eax
mov $12, eax

这是通过x86实现mov和add的正确方法,可用于合并管道和所需的NOP

 mov $10, eax
 NOP 
 NOP
 NOP
 add $2, eax
对于x86完全不正确。x861上的正确性永远不需要NOP

如果输入未准备好接受指令,它将等待指令准备就绪。(无序执行可能会隐藏等待多个并行依赖链的情况

我想我已经读到一些架构有一些指令,如果你太快读取结果,你会得到不可预测的值。这只适用于少数指令(比如乘法),而且许多架构没有架构上需要NOP(或对其他寄存器有用的工作)的情况

处理简单有序管道上的正常情况(如缓存未命中加载)时,可以在需要时在硬件中有效插入NOP,而不需要软件包含无用的指令,这将降低运行相同二进制文件的相同体系结构的高性能(无序)实现


或者我需要再次写入3个NOP,这样它才能完成WMEDF循环

mov $10, eax
mov $12, eax
x86 ISA并不是围绕着设计的(如果这是缩写的意思的话)。因此,即使是像i486这样的标量顺序流水线x86实现,它们内部与您所想的类似,也必须处理不使用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
在每个周期4个
mov
指令时,即使它们都写入相同的寄存器

但请注意,
mov$1,%al
合并到除Intel P6系列(PPro/PII到Core2/Nehalem)以外的CPU上的
%rax
,也可能是Sandybridge(但不是像Haswell这样的更高版本的CPU)。在那些为低8进行部分寄存器重命名的CPU上,
mov$1,%al
可以在每个周期运行多条指令(受ALU端口的限制).但在其他人身上,它就像是一个
添加到
%rax
。请参见。(有趣的是,重复
mov%bl,%ah
在Skylake上每时钟运行4次,重复
mov$123,%ah
每时钟运行1次。)


进一步阅读:

  • x86上的寄存器重命名使用Tomasulo的算法,这种情况下OP的代码很慢,因为它们避免了寄存器重用,没有为累加器留下足够的寄存器来隐藏FP add/FMA的延迟
  • 我的回答更多地说明了现代x86缺乏WAW和战争危险,包括内存

脚注:

  • 在您不知道确切跳转目标地址的攻击中,可能需要一个NOP底座来确保正确性,以便该区域的任何跳转都将执行NOPs,直到它到达您的有效负载
  • 这是通过x86实现mov和add的正确方法,可用于合并管道和所需的NOP

     mov $10, eax
     NOP 
     NOP
     NOP
     add $2, eax
    
    对于x86来说完全不正确。对于x861来说,正确性永远不需要NOP

    如果一条指令的输入没有准备好,它会等待它准备好。(无序执行可能会隐藏这种等待多个并行依赖链的情况。)

    我想我已经读到一些架构有一些指令,如果你太快读取结果,你会得到不可预测的值。这只适用于少数指令(比如乘法),而且许多架构没有架构上需要NOP(或对其他寄存器有用的工作)的情况

    处理简单有序管道上的正常情况(如缓存未命中加载)时,可以在需要时在硬件中有效插入NOP,而不需要软件包含无用的指令,这将降低运行相同二进制文件的相同体系结构的高性能(无序)实现


    或者我需要再次写入3个NOP,这样它才能完成WMEDF循环

    mov $10, eax
    mov $12, eax
    
    x86 ISA并不是围绕着设计的(如果这是缩写的意思的话)。因此,即使是像i486这样的标量顺序流水线x86实现,它们内部与您所想的类似,也必须处理不使用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
    
    在每个周期4个
    mov
    指令时,即使它们都写入相同的寄存器

    但请注意,
    mov$1,%al
    合并到除Intel P6系列(PPro/PII到Core2/Nehalem)以外的CPU上的
    %rax
    ,也可能是Sandybridge(但不是像Haswell这样的更高版本的CPU)。在那些为低8进行部分寄存器重命名的CPU上,
    mov$1,%al
    可以在每个周期运行多条指令(受ALU端口的限制)但在其他人身上,这就像是一个
    添加到
    %rax
    。请参阅。(有趣的事实,重复
    mov%bl,%ah
    在Skylake上每时钟运行4次,重复