2012-09-24 7 views
22

Was ist die Funktion von NOPL in x86-Maschine? Es fühlt sich an, als würde es nichts tun, aber warum ist es immer im Assembler-Code?Was macht NOPL im x86-System?

+5

Sie fragen "warum ist es immer in der Assembler-Code?" - Normalerweise finden Sie nicht viele NOPs im Assembler-Code. Hat ein bestimmter Code, den Sie betrachten, viele NOPs? – ugoren

+5

Mann, ich wünschte, ich könnte fühlen, was Code tut! –

+0

http://stackoverflow.com/questions/6776385/what-is-faster-jmp-or-string-of-nops/6777644 –

Antwort

31

NOP ist eine Ein-Byte- "nichts tun" -Operation, buchstäblich "keine Operation". NOPW, NOPL, etc .. sind die äquivalenten Do-Nothings, aber nehmen Wort und lange Bytes auf.

z.B.

NOP // 1byte opcode 
NOP // 1byte opcode 

entspricht

tun
NOPW // 2byte opcode. 

Sie sind sehr praktisch für die Polsterung Dinge so eine Codesequenz beginnt an einem bestimmten Speichergrenze, um ein paar Bytes Unterrichts Platz wegnimmt, noch nicht tatsächlich etwas tun.

alleinige Wirkung des NOP auf der CPU ist IP/EIP um 1. Die NOPx Äquivalente von 2, 4 tut so zu erhöhen, etc ...

+1

Ich habe nie von der Operation NOPW und NOPL in der Instruktion von einem x86 .. nor gehört sie erscheinen in der Intel Instruction Set Reference :) Vielleicht mischen Sie verschiedene Architekturen – Jack

+4

@Jack riecht wie AT & T-Syntax zu mir – harold

+0

@harold Weiß nicht .. gcc beschwert sich, wenn ich nopw/nopl statt nop – Jack

28

Edit: hinzugefügt Verweise auf gas Dokumentation und gas Codierungen für verschiedene nop Formen:

nach John Fremlin's blog: Operands to NOP on AMD64, nopw, nopl usw. sind gas Syntax, nicht AT & T-Syntax.

Unten sind Befehlskodierungen von gas für verschiedene nop von gas source für Befehlslängen von 3 bis 15 Bytes generiert. Beachten Sie, dass einige der von Intel empfohlenen Formate nop (siehe unten) entsprechen, jedoch nicht alle. Insbesondere bei längeren nop ‚s gas verwendet mehr (bis zu 5) aufeinander folgenden 0x66 Operanden Präfixe in verschiedenen Formen nop, während Intel nop Formen empfohlen nie mehr als einen Operanden 0x66 Präfix in jeder einzelnen empfohlenen nop Anweisung verwenden.

nop Kodierungen von gas source (zur besseren Lesbarkeit umformatiert):

/* nopl (%[re]ax) */ 
static const char alt_3[] = {0x0f,0x1f,0x00}; 
/* nopl 0(%[re]ax) */ 
static const char alt_4[] = {0x0f,0x1f,0x40,0x00}; 
/* nopl 0(%[re]ax,%[re]ax,1) */ 
static const char alt_5[] = {0x0f,0x1f,0x44,0x00,0x00}; 
/* nopw 0(%[re]ax,%[re]ax,1) */ 
static const char alt_6[] = {0x66,0x0f,0x1f,0x44,0x00,0x00}; 
/* nopl 0L(%[re]ax) */ 
static const char alt_7[] = {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; 
/* nopl 0L(%[re]ax,%[re]ax,1) */ 
static const char alt_8[] = {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* nopw 0L(%[re]ax,%[re]ax,1) */ 
static const char alt_9[] = {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_10[] = {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* data16 
nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_long_11[] = {0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* data16 
data16 
nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_long_12[] = {0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* data16 
data16 
data16 
nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_long_13[] = {0x66,0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* data16 
data16 
data16 
data16 
nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_long_14[] = {0x66,0x66,0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* data16 
data16 
data16 
data16 
data16 
nopw %cs:0L(%[re]ax,%[re]ax,1) */ 
static const char alt_long_15[] = {0x66,0x66,0x66,0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 
/* nopl 0(%[re]ax,%[re]ax,1) 
nopw 0(%[re]ax,%[re]ax,1) */ 
static const char alt_short_11[] = {0x0f,0x1f,0x44,0x00,0x00,0x66,0x0f,0x1f,0x44,0x00,0x00}; 
/* nopw 0(%[re]ax,%[re]ax,1) 
nopw 0(%[re]ax,%[re]ax,1) */ 
static const char alt_short_12[] = {0x66,0x0f,0x1f,0x44,0x00,0x00,0x66,0x0f,0x1f,0x44,0x00,0x00}; 
/* nopw 0(%[re]ax,%[re]ax,1) 
nopl 0L(%[re]ax) */ 
static const char alt_short_13[] = {0x66,0x0f,0x1f,0x44,0x00,0x00,0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; 
/* nopl 0L(%[re]ax) 
nopl 0L(%[re]ax) */ 
static const char alt_short_14[] = {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; 
/* nopl 0L(%[re]ax) 
nopl 0L(%[re]ax,%[re]ax,1) */ 
static const char alt_short_15[] = {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; 

Intel unterschiedliche Syntax verwendet, und es gibt nop ‚s für alle Befehlslängen von 1 bis 9 Byte. Es gibt mehrere verschiedene nop 's, da alle nop' s länger als zwei Bytes 1 Operanden akzeptieren. Ein Byte nop (0x90) ist gleichbedeutend mit xchg (e)ax,(e)ax.

Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2 (2A, 2B & 2C): Instruction Set Reference, A-Z, CHAPTER 4: INSTRUCTION SET REFERENCE, M-Z Listen empfohlen nop Formen für verschiedene Anweisungen Längen:

Table 4-12. Recommended Multi-Byte Sequence of NOP Instruction 

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 + 00H]   0F 1F 44 00 00H 
6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H]  66 0F 1F 44 00 00H 
7 bytes NOP DWORD ptr [EAX + 00000000H]   0F 1F 80 00 00 00 00H 
8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H 
9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H 

So zusätzlich zu diesen nop 'von Intel empfohlen s, gibt es viele andere nop' zu s. Zusätzlich zum Ausrichten eines Befehls auf eine bestimmte Speichergrenze, wie Marc B in seiner Antwort erwähnt, sind nop auch sehr nützlich beim selbstmodifizierenden Code, beim Debuggen und Reverse-Engineering.

+7

Beachten Sie, dass 'nop' auf amd64 nicht länger mit' xchg eax, eax' synonym ist. 'nop' löscht nicht die oberen 32 Bits von' eax', sondern 'xchg eax, eax'. – fuz

5

Tatsächlich wird NOP im Assemblercode verwendet, wenn der Code gepatcht werden muss.

Da die Größe der neuen Anweisungen von denen der alten abweichen kann, ist Padding erforderlich.

Der Padding-Befehl sollte genauso wie NOP funktionieren, obwohl er mehrere Bytes belegen kann.

Der Grund, dass wir eine komplexere Anweisung wie 66 90 statt mehrerer NOPs einfügen, ist, dass eine Anweisung im Allgemeinen schneller ausgeführt wird als mehrere NOPs.