LOOP, LOOPcc

根据 ECX 计数器循环

stableVMJITAOTinstruction

编码

操作码指令Op/En64 位兼容/传统说明
E2 cbLOOP rel8D有效有效减值计数; 如果计数为 0 则跳短 。
E1 cbLOOPE rel8D有效有效减值计数;如果计数0则跳短,ZF=1.
E0 cbLOOPNE rel8D有效有效减值计数;如果计数0则跳短,ZF=0.

操作数编码

每个模式对应上表 Op/En 列的一个取值,说明各操作数按书写顺序分别编码在指令的哪个字段,以及指令对它是读、是写还是两者兼有。

D

  1. offset操作码后的位移

实测开销

正在从 arch-data 加载实测数据...

说明

使用 RCX, ECX 或 CX 寄存器作为计数器进行循环操作(取决于地址大小是64位,32位,还是16位). 注意LOOP指令忽略了REX.W;但64位地址大小可以使用67H前缀被覆盖.

每次执行 LOOP 指令时,计数寄存器都会减少,然后检查为 0. 如果计数为0,则循环终止,程序执行继续按照LOOP指令执行指令. 如果计数不为零,则对目的地(目标)操作数进行近距离跳跃,这大概是循环开头的指令.

目标指令以相对偏移(相对于IP/EIP/RIP登记册中的指令指针的当前值,一个签名偏移)来指定. 这种偏移一般在组装码中被指定为标签,但在机器编码级别上,它被编码为一个签名的,8位的即时值,它被添加到指令指针中. 本指令允许128至+127的偏移。

一些形式的循环指令(LOOPcc)也接受ZF旗作为在计数达到零前终止循环的一个条件. 使用这些指示形式,每个指示都附有一个条件代码(cc),以说明所测试的条件。 在此,LOOPcc指令本身不影响ZF旗的状态;ZF旗由环中的其他指令更改.

行动

IF (AddressSize = 32)

    THEN Count is ECX;
ELSE IF (AddressSize = 64)

    Count is RCX;
ELSE Count is CX;
FI;

Count := Count  1;

IF Instruction is not LOOP
    THEN
          IF (Instruction := LOOPE) or (Instruction := LOOPZ)

             THEN IF (ZF = 1) and (Count  0)

                            THEN BranchCond := 1;
                            ELSE BranchCond := 0;
                      FI;

             ELSE (Instruction = LOOPNE) or (Instruction = LOOPNZ)
                  IF (ZF = 0 ) and (Count  0)

                            THEN BranchCond := 1;
                            ELSE BranchCond := 0;
                      FI;


          FI;

   ELSE (* Instruction = LOOP *)
        IF (Count  0)

                THEN BranchCond := 1;

                ELSE BranchCond := 0;

          FI;

FI;

IF BranchCond = 1

    THEN
          IF in 64-bit mode (* OperandSize = 64 *)
                THEN
                      tempRIP := RIP + SignExtend(DEST);
                      IF tempRIP is not canonical
                            THEN #GP(0);
                      ELSE RIP := tempRIP;
                      FI;
                ELSE
                      tempEIP := EIP SignExtend(DEST);
                      IF OperandSize 16
                            THEN tempEIP := tempEIP AND 0000FFFFH;
                      FI;
                      IF tempEIP is not within code segment limit
                            THEN #GP(0);
                            ELSE EIP := tempEIP;
                      FI;
          FI;

    ELSE
          Terminate loop and continue program execution at (R/E)IP;

FI;

受影响的旗帜

None.

异常

保护模式
#GP(0)如果冲抵跳跃到CS部分的极限之外.
#UD如果使用 LOCK 前缀 。
实地址模式
#GP如果跳转到 CS 段的界限以外, 或者在 0 到 FFFFH 的有效地址空间之外, 如果使用 32 位地址大小覆盖前缀, 则会发生此条件 。
#UD如果使用 LOCK 前缀 。
虚拟 8086 模式
与真实地址模式相同的例外 。
兼容模式
与保护模式中的例外相同.
64 位模式
#GP(0)如果被跳跃到一个非冠状形式。
#UD如果使用 LOCK 前缀 。

来源