我想知道汇编中的“语义NOP”是什么?
5 回答
不是实际 nop 但不影响程序行为的代码。
在 C 中,可以将以下序列视为语义 NOP:
{
// Since none of these have side affects, they are effectively no-ops
int x = 5;
int y = x * x;
int z = y / x;
}
它们是无效的指令,如 NOP,但占用更多字节。使代码与缓存行边界对齐很有用。像 lea edi,[edi+0] 这样的指令就是一个例子,它需要 7 个 NOP 来填充相同数量的字节,但只需要 1 个周期而不是 7 个周期。
语义 NOP 是完全没有效果或几乎没有效果(大多数指令更改条件代码)的机器语言指令的集合,其唯一目的是混淆程序实际在做什么。
真正的“语义 nop”是一条除了花费一些时间并推进程序计数器之外没有任何作用的指令。例如,许多寄存器到寄存器移动不影响标志的机器有许多指令可以将寄存器移动到自身。例如,在 8088 上,以下任何一项都是语义 NOP:
移动, al mov bl,bl mov cl, cl ... 移动斧头,斧头 暴徒bx,bx mov cx,cx ... xchg 斧头,斧头 xchg bx,bx xchg cx,cx ...
请注意,除“xchg ax,ax”之外的所有上述都是两字节指令。因此,Intel 声明当需要单字节 NOP 时应使用“xchg ax,ax”。事实上,如果组装“mov ax,ax”并拆解它,它将被拆解为“NOP”。
请注意,在某些情况下,指令或指令序列可能具有潜在的副作用,但仍然比通常的“nop”更可取。例如,在 6502 上,如果需要 7 个周期的延迟并且堆栈指针有效但堆栈顶部的值无关紧要,则 PHP 后跟 PLP 将仅使用两个字节的代码杀死 7 个周期。但是,如果栈顶值不是 RAM 的备用字节,则序列将失败。
执行但没有做任何有意义的事情的代码。这些也称为“不透明谓词”,并且最常被混淆器使用。