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).

Brennan Vincent
  • 293
  • 1
  • 2
  • 9

2 Answers2

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]                  |                              |
+---------+--------------------------------+------------------------------+
0xec
  • 6,090
  • 3
  • 23
  • 33
  • 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 09 '16 at 09:28
  • 1
    @Jongware: the linked site is generated from Intel docs – Igor Skochinsky Feb 09 '16 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.

Watcom
  • 151
  • 1
  • 2