我想知道什么是装配中的“语义NOP”?大会:什么是语义NOP?
8
A
回答
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;
}
0
语义NOP是具有在所有或几乎没有影响没有影响机器语言指令的集合(大部分的操作变化条件代码),其唯一目的是混淆程序实际正在做的事情。
0
代码执行但没有任何意义。这些也被称为“不透明的谓词”,最常用的是obfuscators。
1
它们是不起作用的指令,如NOP,但占用更多的字节。用于获取与高速缓存行边界对齐的代码。一个像lea edi [edi + 0]这样的指令就是一个例子,需要7个NOP来填充相同数量的字节,但只需要1个周期而不是7个。
0
真正的“语义nop”除了花费一些时间和推进程序计数器之外,没有任何效果。许多寄存器到寄存器移动的机器不会影响标志,例如,有许多指令会将寄存器移动到它自己。在8088,例如,以下任一会是语义的NOP:
mov al,al mov bl,bl mov cl,cl ... mov ax,ax mob bx,bx mov cx,cx ... xchg ax,ax xchg bx,bx xchg cx,cx ...
注意,所有除了上述的“XCHG斧,斧”是两个字节指令。因此,英特尔声明,当需要一个字节的NOP时,应该使用“xchg ax,ax”。确实,如果组装“mov ax,ax”并拆卸它,它将会拆解为“NOP”。
请注意,在某些情况下,指令或指令序列可能具有潜在的副作用,但仍然比通常的“nop”更令人满意。例如,在6502上,如果需要7个周期的延迟并且堆栈指针有效但堆栈顶部的值不相关,那么PHP和PLP将仅使用两个字节的代码来杀死7个周期。如果栈顶值不是RAM的备用字节,则序列将失败。