Talk:NOP (code)

Latest comment: 2 months ago by Guy Harris in topic NOPs that aren't really

Talk

edit

Note: NOOP Protocol Commands section is based off a section I wrote, original article noop. --Rgb9000

i++ statement

edit

The i++ statement does have a net effect- therefore making it a bad candidate for an example of NOOP. This has been replaced with i + 1; which does not change any values in memory, and simply returns its value into nothingness.

Indeed it does, but here it was followed by i--, which means that there is no net effect unless there's something weird going on in the background that I don't know about. --Aurochs
No, the person above is absolutely right. Either operation, i++ or ++i will affect the value of i! These are not the same as a NOOP, this are the same as "INC i" where INC would be an increment operator in the CPU. Like you said in your edit comment, i+1 effectively does nothing. (Actually, without optimization, it LOADS the value of i into a register, increments it by one, and then forgets about the value. Optimizing compilers see this, ignore the operation, and replace it with a NOOP.) i+1 is STILL valid c++! Much in the same way i=j=k=m+1 is! Try it! You'll see that it will compile and everything. More to the point, if i have a function int dosomething(), i can just call dosomething() and ignore the return value because c/c++ allows this for all functions. i+1 is such a function.--Stux 15:33, 9 November 2005 (UTC)Reply
I think you're missing the point. The following code:
i++;
i--;

has no net effect. It incerments i and then immediately decrements it, so i has returned to its original value and there was no intervening code to use the incermented variable. It is effectively an nop, though the amount of time it takes to execute differs from your i + 1 example. --Aurochs
Oh! My apologies! Now I understand what the example was saying! At first I thought (and I'm sure the user that originally changed the i++ to an i+1 probably thought as well), that the example was listing two individual statements. Upon more careful reading (of the text and of your comments) I realized now what it meant. Since it seemed rather easy for passers-by to misinterpret that example (much in the same way I did), I changed the example back to the original, but added brackets and wording to make it clear that it is meant to be understood as one group of instructions. I also added the i+1 example back in as an alternative. If you feel the wording needs to be improved, please do so! Again, thanks for pointing out the error. (Thank you for your politeness and understanding as well! It seems nowadays that is lacking from the users of this wiki.) --Stux 22:08, 9 November 2005 (UTC)Reply
I'm going to remove this example. As i++; i--; changes values in memory, it's not really a no-op. (I realize the probability is unlikely, but what happens if another thread raises an exception before i--; gets called? - Chardish 16:11, 6 December 2006 (UTC)Reply
No, i++; i--; is not a NOP. Let's assume the compiler translates it to this pseudo-assembly code:
1: INC i
2: DEC i
On most (all?) CPUs, these two instructions are not atomic. Let's assume the program containing this code is running two threads and a context switch occurs between instructions 1 and 2. The value of i is now one more than the original value. If the second thread attempts to read i at it point, it will read the wrong value. — 71.155.235.243 00:39, 31 March 2006 (UTC)Reply
i++; i-- can cause an overflow trap depending on the type of i. An unsigned int will never trap, but a plain (signed) int or a float may do so. If adding the declaration is deemed too distracting, I suggest changing the example to i += 4711 * 0 or similar. Kjetilho 07:51, 4 October 2006 (UTC)Reply

NOPs that aren't really

edit

I think that this article should cover the fact that not all processors have an opcode that is truly set aside as a NOP. The most obvious example is the x86. Opcode 90 really means "xchg eax, eax". MIPS's NOP is really "sllv zero, zero, zero" if I remember right.

Of course, this can change over time. When the x86 became pipelined, "nop" stopped being "xchg eax, eax". It's special cased for performance reasons; "xchg" is a somewhat expensive instruction. Also, "xchg eax, eax" implies to the instruction scheduler that the instruction depends on the previous value of EAX.

x86-64 further differentiates it. "xchg eax, eax" actually does something - it now truncates RAX to 32 bits, as in "movzx rax, eax". Assemblers don't encode "xchg eax, eax" as 90. -- 68.228.65.220 06:48, 10 October 2006 (UTC)Reply

The fact that `xchg eax,eax` does something does not matter in this case, since it only translates to `0x90` in `32bit` x86 CPU's.
The base opcode for `xchg` is `0x87`. Thus, when translating `xchg eax,eax` we get `0x87c0`, which `does` indeed truncate `rax`, since it operates on `0b11 000 000`, i.e. operating on 2 registers with the magical value 0(eax is the first register internaly).
`xchg rax,rax` would usually still be translated as `0x4890`, i.e. REX prefix plus `NOP` operation.
When instructing the assembler to `literally` translate `xchg rax,rax`, of course `0x4890` does not equal `xchg rax, rax`, instead, we get: `0x4887c0`(64 bit operation on the 2 registers of index 0).
This *does* still do the same though, not truncating the `rax` value.
Hence, there is no `xchg rax,rax` instruction in modern x86_64 assembly anymore. Instead, when using it, your compiler is going to `infer`you wanted just a `NOP`.
Hence, `0x90` is technically REALLY `NOP`, which `does` exist, quite in contrast, it is `xchg rax,rax`, which seems not to exist anymore, since your assembler is usually smart enough to figure out that what you wanted was a 64-bit `NOP`.
This technically means that the posts of the people before mine are `ALL` more or less wrong.
`xchg eax,eax` gets interpreted as `NOP` when assembling 32-bit programs, of course it `does` something in `long` mode. You wouldn't use `xchg ax,ax` in 32bit environments as NOP's either.
Ans anyway. xchg has the base-opcode of `0x87`, which is true for all x86 based processors.
Hence, whoever believes there is no `NOP` instruction, must be `wrong`, even though your assembler knows what you're trying to do when using `xchg rax,rax`, and will hence not assemble it literally, instead replacing it with the `NOP` instruction, same goes for `xchg eax, eax` in32bit and, probably `xchg ax,ax` in 16bit mode.
Technically, that does NOT mean that `xchg rax,rax` or `xchg eax,eax` are the same as `NOP`!
0x87 != 0x90.
Q.e.d. 2001:9E8:C7E7:600:F552:1A8A:91A1:C082 (talk) 19:09, 16 May 2024 (UTC)Reply
Note that I forgot signing in before posting this & my edits. Don't be confused, both changes were made by me :D FelixHx (talk) 19:28, 16 May 2024 (UTC)Reply
Not quite sure what your point is here? Opcode 0x87 is not the only way to encode XCHG in the x86 instruction set - opcode 0x90+r is in general a 1-byte XCHG where one argument is (E)AX and the other argument is a register. E.g. in 32-bit mode, opcode 0x91 is a single-byte encoding of "XCHG EAX,ECX" and 0x97 is a single-byte "XCHG EAX,EDI" - as such, describing the r=0 case (opcode 0x90 "NOP") as an alias of "XCHG AX,AX" or "XCHG EAX,EAX" for 16/32-bit x86 seems perfectly fine to me? I mean, it pretty much *is* how both Intel and AMD are describing it in their official reference documentation for the x86 "XCHG" and "NOP" instructions[1][2] (although they do note that the opcode is treated specially in 64-bit mode when used to exchange EAX with itself.) Punpcklbw (talk) 03:06, 18 May 2024 (UTC)Reply
The assembler is completely irrelevant here; the table shows machine encodings of NOPs. 0x90 is the one-byte encoding of XCHG AX,AX in 16-bit code and XCHG EAX,EAX in 32-bit and 64-bit code. If the assembler generates 0x90 for XCHG AX,AX in 16-bit code and XCHG EAX,EAX in 32-bit and 64-bit code, that's because it sees no reason to use any encoding other than the 1-byte encoding, as multi-byte encodings waste memory, instruction cache space, and instruction-fetch bandwidth with no performance benefit, not because it "infers you wanted a 64-bit NOP". For any register/register XCHG instruction in which one of the registers is EAX, there is no reason to use 0x86 or 0x87 as the opcode rather than 0x9x (all three of which are XCHG opcodes). Guy Harris (talk) 08:13, 16 August 2024 (UTC)Reply

References

  1. ^ Intel, Software Developer's Manual, order no. 325462-083, pages 1386 and 2715, https://cdrdv2-public.intel.com/819723/325462-sdm-vol-1-2abcd-3abcd-4.pdf
  2. ^ AMD, AMD64 Architecture Programmer’s Manual, volume 3, pub.no. 34594, rev 3.36, pages 262 and 360, https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24594.pdf

Optimising compilers

edit

I recently added the following text to the NOP code section:

Note that in code which is compiled using an optimizing compiler, it is likely that any such redundant statements will be removed before they get a chance to be executed.

It was removed with the edit comment "There are no redundant statements in the example given". Perhaps the intent of this sentence was not clear, so I'll explain it here and perhaps we can work out a better way of putting it. My point is that in a non-optimising compiler, the given instructions may well be compiled into the binary (e.g. the source code i + 1; might result in machine code that performs an ADD and discards the results), but in an optimising compiler the whole instruction will be recognised as redundant and removed. Therefore in an optimising compiler, main() { } and main { int i; i+1; } should produce exactly the same binary code. --HappyDog 08:54, 23 May 2007 (UTC)Reply

  • Firstly compiler optimization is a continuum, all that can be said is optimizing compilers do more optimizations than non-optimizing compilers. In the context of the code fragment it was not clear that that optimization of dead code was being discussed. But my main point is that this article is about NOP, not compilers removing unnecessary code. Ok, unnecessary code may be regarded as effectively a nop, but that is a rather indirect connection for an article like this to make. Derek farn 10:59, 23 May 2007 (UTC)Reply
That's all true, but reading that section, the implication is that the example code will compile into NOP instructions. The paragraph begins An example of a single C statement that would also produce a NOP:, which is not true in optimising compilers that (as you rightly qualified) detect this kind of redundancy. However, as this is such a basic optimisation to make, I would suspect (based on no actual research :-)) that most such compilers would manage this. Perhaps the introduction to this section needs rewording, because it is unclear whether you are saying that this kind of instruction is called a NOP by C programmers (which in my experience it never is - 'void' is a more common term, if anything) or whether it compiles to a NOP, in which case a note about optimising compilers is required, imho. --HappyDog 11:30, 24 May 2007 (UTC)Reply
I recently added something to this effect, which was reverted. Two points. There is no compiler I'm aware of, which at any optimisation level, ever, added in NOPs for empty lines of C code. That just isn't how compilers work. Why would they want to put in the extra work to output a NOP, when instead they could simply output nothing? Just because a compiler doesn't optimise well, doesn't mean it goes around purposefully spending extra work slowing things down. I think we do need a line which says that the NOPs of code are not directly related to NOPs of assembler itself, as too many people (including some people here, no offense), think that C compilers might output NOPs for empty instructions which isn't true at any optimisation level Mrjeff 09:55, 7 June 2007 (UTC)Reply
For some architectures, a compiler will generate a NOP for some occurrences of a null statement. For instance, it may be necessary to fill the delay slot of a branch instruction on a MIPS processor. This is a rather unusual edge case and mentioning it will only complicate the issue. Do people actually think that in normal operation, a compiler goes round purposely generating NOPs when it detects redundant code?. Derek farn 10:40, 7 June 2007 (UTC)Reply
In this instance the compiler is inserting its own NOPs where necessary. It still won't convert null statements into NOPs. --HappyDog 14:19, 7 June 2007 (UTC)Reply

Behaviour/output.

edit

The word 'behaviour' was changed to 'output' in this edit with the edit summary Behavior can include things other than output. However, surely the point of NOP is that it has no effect, whether to behaviour or output, so I am unsure why the change was made. Perhaps I misunderstand the purpose of the sentence. Can you explain what you are trying to say with it? --HappyDog 17:06, 27 May 2007 (UTC)Reply

A construct considered to be a NOP can exhibit behavior if actual instructions are generated/executed. Time and power (electrical) will be consumed. Yes, this behavior will require sensitive equipment to detect, but it is still behavior. You are right in that it is a rather picky point. But in many cases the essence of a NOP is that it is often something that happens (in other cases nothing at all happens) that has no consequences at the human level (I use the term program output when perhaps "no external effect noticeable human level" might be technically more accurate, if somewhat long winded). Derek farn 19:33, 27 May 2007 (UTC)Reply

Null statements and style

edit

Another use of a null statement in C is for a goto label at the end of a block, e.g.:

if (a_condition)
{
    for (;;)
    {
        if (some_condition)
            goto endloop;
        ...
    }
endloop: ;
}

I should point out that using the continue statement is a better way to write empty loop bodies in C:

while (ReadChar() != '\n')
    continue;

Except for a few rare exceptions, the use of null statements is generally considered bad programming style, especially in languages like C where a single ";" character can be easily misplaced or overlooked. A more visible approach is to use an empty block:

if (condition_1)
{ }    // Do nothing
else if (condition_2)
    do_something();
else
    do_something_else();

Loadmaster 17:11, 30 May 2007 (UTC)Reply

Let's not be C specific. Are there any kinds of NOP 'statements; that appear in other languages and perhaps are not found in C? Derek farn 17:30, 30 May 2007 (UTC)Reply

Comments

edit

Does a comment count as a NOP? --HappyDog 02:36, 31 May 2007 (UTC)Reply

A comment is not intended to be an operation. A NOP is an instruction that looks like it might do something (of course it does, it wastes cpu time and takes up storage). Derek farn 11:15, 31 May 2007 (UTC)Reply
A C compiler will discard a null statement and a comment in the same way - neither will be converted into executable code. Both are lines in the source code that do nothing. I don't quite see the distinction. --HappyDog 12:05, 31 May 2007 (UTC)Reply
Perhaps I am being overly keen to create a distinction. I guess one definition of NOP is something that is not an operation (or a vegetable, or a rock, or a etc...) The usage I am familiar with is when a construct is normally an operation, but for some reason it is written in such a way that no operation actually takes place. Now this may just be splitting hairs, but to me a comment is obviously not a NOP. Perhaps somebody else can describe it better than me (or perhaps people do regard a comment as a NOP and I am just out of touch). Derek farn 15:38, 31 May 2007 (UTC)Reply
I meant that a null statement in C is not something I would consider a NOP - I wasn't trying to imply that a comment was. My point was that in a compiled language the whole concept of a NOP is somewhat nebulous, and that in C the relationship between a null statement or a comment and the resulting source code is the same - they are both discarded by the compiler. Therefore defining a NOP in terms of the resulting machine code does not work. --HappyDog 23:37, 31 May 2007 (UTC)Reply
Comments are known to execute very fast. ;-) — Loadmaster 23:35, 31 May 2007 (UTC)Reply
I don't read the text as defining NOP in terms of the resulting machine code. I think it reads as being in terms of intent. Derek farn 10:33, 7 June 2007 (UTC)Reply

NOP-outing of IV

edit

In Watermark attack article there's statement that IV is "NOP-outed", referencing to NOP. Why is it called NOP-outing? —Preceding unsigned comment added by 212.98.185.58 (talk) 17:13, 7 May 2009 (UTC)Reply

Very early copy prevention systems for software could be defeated by overwriting part of the executable instructions with NOP instructions -- the instructions that decided whether this was a validly-licensed copy (and so continue) or not (and so branch to an error handler). Slightly more sophisticated systems checked their own code -- both the above license-detection code, and the code-checking code itself -- with a checksum to detect such NOP overwriting. Those systems could be defeated by a slightly more sophisticated attack that overwrote the code with NOPs, and then adjusted the checksum value to directly cancel out; or other parts of the program to indirectly cancel out; the effect of those modifications -- an attack continuing to be called "NOP-outing". The watermark attack would be easy if it could simply zero-out all the IVs -- even though it can't directly cancel them out, some early FDE software was vulnerable to a carefully crafted a chosen plaintext file designed to indirectly cancel out some of the effects of those IVs. That indirect-cancellation attack is apparently mathematically similar enough to the above "NOP-outing" attack that some people called it "NOP-outing", even though it doesn't actually involve NOP instructions or any other executable instructions. Merely the *idea* of one thing cancelling out another thing, so net effectively no-effect, much like the NOP instruction effectively has no effect.
Should a few more details be mentioned in this NOP (code) article or the watermark attack article or both? --DavidCary (talk) 18:51, 24 October 2018 (UTC)Reply

Not "nothing at all"

edit

I take issue with the statement at the top of the page that says NOP "effectively does nothing at all." Some processors drop to a lower power state on NOPs (saving power while they have "nothing" to do). The 2nd section also talks about how NOP takes a specific number of clock cycles to execute, which means NOP could be used to synchronize code between multiple cores or CPUs, etc. Call me a pedant, but these things matter in computer science Fry-kun (talk) 22:42, 1 September 2010 (UTC)Reply

NOPs with side-effect

edit

Usually NOPs do "nothing". Well, there is some discussion as what actually is something and what's nothing, but well, they usually don't change registers or memory or something like that. Well, that's what I thought until I had to work on a TI TMS320C28x CPU. NOP has two optional parameters there:

nop *, ARP2 ; set arp pointer to xar2

So that's actually not a no-op. Source: http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=spru430&track=no See page 407 for a description of NOP, and 135 for an example using it that way. --212.18.210.70 (talk) 16:40, 15 January 2013 (UTC)Reply

Java return?

edit

The Java language has a return; statement, which does nothing.

In the Java I learned, this exits from the function in which it appears, just as it does in C and other derived languages. As such, I'm removing it. — Smjg (talk) 23:27, 22 September 2014 (UTC)Reply

x86 PAUSE instruction

edit

The PAUSE instruction is encoded as "F3 90", so it is like a "REP NOP" but is handled differently on CPUs that supports the special PAUSE command, but I do not know how "different".
I think the PAUSE command should be mentioned here. What do you think? --RokerHRO (talk) 12:22, 30 April 2015 (UTC)Reply

The pause instruction has been encoded as rep nop because that combination—although technically invalid—had the same effect as a nop instruction on previous chips. pause behaves like a nop with a hint to the processor that this is a spin-lock and the processor should divert resources to other threads running on the same core (e.g. with hyperthreading) or slow down and safe energy. I think it might be a good idea to write something about hinting nops in general. --16:58, 30 April 2015 (UTC) — Preceding unsigned comment added by FUZxxl (talkcontribs)
edit

Hello fellow Wikipedians,

I have just modified one external link on NOP. Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:

When you have finished reviewing my changes, you may follow the instructions on the template below to fix any issues with the URLs.

This message was posted before February 2018. After February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}} (last update: 5 June 2024).

  • If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
  • If you found an error with any archives or the URLs themselves, you can fix them with this tool.

Cheers.—InternetArchiveBot (Report bug) 23:46, 10 February 2018 (UTC)Reply