初学8086汇编时,绝大多数同学对NOP 的印象只有一句话:空指令、啥也不干

做电子琴延时、做简单时序填充时随手写几句 NOP,却从来不知道:

为什么 NOP 能延时?

为什么工程、驱动、逆向工程里大量充斥 NOP?

它机器码为什么是 0x90

看似无用的指令,为什么 CPU 要专门设计它?

一、NOP 到底是什么

1. 全称

NOP = No Operation 空操作指令

2. 核心特性

不修改任何寄存器(AX、BX、标志位全部不变)

不读写内存

只占用 1 个字节机器码 0x90

消耗 1 个 CPU 时钟周期,然后继续往下执行

一句话总结:NOP 不改变程序数据,只改变程序时间与内存布局。

很多人误解:NOP 是空的、没用的。

真相:不做事,本身就是它最大的用处。

二、为什么 CPU 要设计一条“啥也不干”的指令?

高级语言没有“空操作”,因为高级语言只管逻辑。

但汇编、硬件、CPU 流水线、时序控制必须要有空操作

CPU 运行是连续、匀速、逐周期的,不能暂停、不能跳空。

如果需要“等一会”“对齐地址”“留白占位”,就必须用 NOP 填充周期/空间。

三、NOP 做软件延时(电子琴实验)

1. 我们做过的电子琴代码原理

单纯 loop 循环速度极快,喇叭震动时间太短,人耳完全听不到声音

所以需要在循环里插入 NOP,强行拖长时钟周期,拉长发声时长。

2. 延时模板

delay:

nop

nop

nop

loop delay

3. 原理拆解

每一条 NOP = 卡住 1 个时钟周期

NOP 越多 → 单次循环越慢 → 延时越长 → 音符清晰可闻

四、NOP 的四大专业用途

用途1:精准软件延时

适合短延时、硬件时序匹配、蜂鸣器、LED 闪烁、端口稳定等待。

优点:周期固定、误差极小、不破坏寄存器

用途2:代码地址对齐

CPU 读取指令时,地址对齐的代码执行效率更高

如果一段代码结束地址不规整,编译器会自动填充多条 NOP,让下一段程序从整地址开始执行。

用途3:代码占位、预留修改空间

开发调试时,如果后续可能需要新增指令,可以先写多条 NOP 占位。

后续直接把 NOP 替换成新指令,不用整体移动代码地址,避免程序崩地址偏移。

用途4:逆向工程破解、NOP 雪橇原理)

在软件逆向、漏洞利用中,大量填充 NOP 形成 NOP 雪橇,让程序错误执行滑入目标代码段。

同时逆向中常用 NOP 覆盖跳转指令,干掉验证逻辑、破解弹窗、去除注册判断。

五、NOP 机器码 0x90 冷知识

在 x86 架构中:
NOP 本质等价于:XCHG EAX, EAX
自己和自己交换数据,等于啥也没做,但是占用周期、占用字节。
所以机器码固定为 0x90,单字节指令,极其轻量。

写在最后

很多汇编知识点看起来平平无奇,比如 NOP、寻址、中断、进位标志。

但正是这些不起眼的底层指令,撑起了操作系统、驱动、嵌入式、逆向安全的整个技术体系。

看懂 NOP,你就已经从 只会抄代码的初学者,变成了 懂底层原理的学习者

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐