11

A program I'm investigating has the following code (disassembled by IDA with some light censorship by me):

__text:....B9                 call    <redacted>
__text:....BE                 nop
__text:....BF                 nop     dword ptr [rax+00h]

I have two questions. First, why would the compiler have inserted these nops? They don't appear to be for any alignment purpose.

Second, what is that nop with a relative addressing argument? Its hex is 0F 1F 40 00. Looking at http://ref.x86asm.net/, this does appear to be an instruction called "hintable NOP", but I'm having trouble finding relevant information about it.

By the way, the next instruction starts at ....C3 and is a real/productive instruction (that is, not a nop or anything morally equivalent to a nop).

2 Answers 2

11

These are multi byte nop instructions.
From http://www.felixcloutier.com/x86/NOP.html

Description

This instruction performs no operation. It is a one-byte or multi-byte NOP that takes up space in the instruction stream but does not impact machine context, except for the EIP register.

The multi-byte form of NOP is available on processors with model encoding:

The multi-byte NOP instruction does not alter the content of a register and will not issue a memory operation. The instruction’s operation is the same in non-64-bit modes and 64-bit mode.

Operation

The one-byte NOP instruction is an alias mnemonic for the XCHG (E)AX, (E)AX instruction.

The multi-byte NOP instruction performs no operation on supported processors and generates undefined opcode exception on processors that do not support the multi-byte NOP instruction.

The memory operand form of the instruction allows software to create a byte sequence of “no operation” as one instruction. For situations where multiple-byte NOPs are needed, the recommended operations (32-bit mode and 64-bit mode) are:

+---------+--------------------------------+------------------------------+
| LENGTH  |           ASSEMBLY             |         BYTE SEQUENCE        |
+---------+--------------------------------+------------------------------+
|         |                                |                              |
| 2 bytes |  66 NOP                        |  66 90H                      |
|         |                                |                              |
| 3 bytes |  NOP DWORD ptr [EAX]           |  0F 1F 00H                   |
|         |                                |                              |
| 4 bytes |  NOP DWORD ptr [EAX + 00H]     |  0F 1F 40 00H                |
|         |                                |                              |
| 5 bytes |  NOP DWORD ptr [EAX + EAX*1 +  |  0F 1F 44 00 00H             |
|         | 00H]                           |                              |
|         |                                |                              |
| 6 bytes |  66 NOP DWORD ptr [EAX + EAX*1 |  66 0F 1F 44 00 00H          |
|         |  + 00H]                        |                              |
|         |                                |                              |
| 7 bytes |  NOP DWORD ptr [EAX + 00000000 |  0F 1F 80 00 00 00 00H       |
|         | H]                             |                              |
|         |                                |                              |
| 8 bytes |  NOP DWORD ptr [EAX + EAX*1 +  |  0F 1F 84 00 00 00 00 00H    |
|         | 00000000H]                     |                              |
|         |                                |                              |
| 9 bytes |  66 NOP DWORD ptr [EAX + EAX*1 |  66 0F 1F 84 00 00 00 00 00H |
|         |  + 00000000H]                  |                              |
+---------+--------------------------------+------------------------------+
2
  • Nitpick: this same table appears in Intel's official reference (and unless my memory deceives me, the description is very similar). Perhaps it's better to point OP to that instead.
    – Jongware
    Feb 9, 2016 at 9:28
  • 1
    @Jongware: the linked site is generated from Intel docs
    – Igor Skochinsky
    Feb 9, 2016 at 12:53
5

Regarding your first question, NOPs are issued by the compiler when it's interested in aligning the code following it, usually because that code is target of a jump (such as in a loop) and it's beneficial for it to be aligned to a paragraph (16-byte boundary) or a cache line (32-byte boundary).

In other words, it does so to increase performance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.