2012-09-24 31 views
22

qual è la funzione di NOPL in macchina x86? Sembra che non faccia nulla, ma perché è sempre nel codice assembly?Che cosa fa NOPL nel sistema x86?

+5

Si chiede "perché è sempre nel codice assembly?" - Normalmente non si trovano molti NOP nel codice assembly. Alcuni codici specifici che stai guardando hanno molti NOP? – ugoren

+5

Uomo, vorrei poter "sentire" che codice fa! –

+0

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

risposta

31

NOP è un one-byte "non fare nulla" operazione, letteralmente "nessuna operazione". NOPW, NOPL, ecc. Sono gli equivalenti a nulla, ma occupano la parola e i byte di dimensione estesa.

ad es.

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

equivale a fare

NOPW // 2byte opcode. 

Sono molto utile per le cose imbottitura fuori così una sequenza di codice inizia su un particolare confine della memoria, prendendo un paio di byte di spazio di istruzioni, ma non in realtà facendo qualsiasi cosa.

unico effetto di NOP sulla CPU è quello di incrementare IP/EIP di 1. Gli equivalenti NOPX faranno da 2, 4, ecc ...

+1

Non ho mai sentito parlare dell'operazione NOPW e NOPL nel set di istruzioni di un x86 .. né appaiono nel Riferimento del set di istruzioni Intel :) Forse stai mescolando architetture diverse – Jack

+4

@Jack odora sintassi AT & T per me – harold

+0

@harold Non so .. gcc si lamenta se uso nopw/nopl invece di nop – Jack

28

Edit: riferimenti aggiunti a gas documentazione e gas codifiche per diverse forme: nop

Secondo John Fremlin's blog: Operands to NOP on AMD64, nopw, nopl ecc sono gas sintassi, non AT & sintassi T.

Questi sono codifiche corsi generati da gas per diverse s nop' da gas source per lunghezze istruzione da 3 a 15 byte. Nota che alcuni sono uguali ai moduli raccomandati da Intel nop (vedi sotto), ma non tutti. In particolare, in più nop s' gas utilizza più (fino a 5) consecutivi 0x66 prefissi operando in diverse forme nop, mentre Intel consiglia nop forme non usare mai più di un 0x66 prefisso operando in ogni singola consigliata nop istruzioni.

nop codifiche da gas source (riformattato per migliorare la leggibilità):

/* 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 utilizza sintassi diversa, e ci sono nop 's disponibili per tutte le lunghezze di istruzioni da 1 a 9 byte. Ci sono diversi 's, come tutte le nop' diverse nop s di lunghezza superiore a due byte accettano 1 operando. Un byte nop (0x90) è sinonimo di 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 liste raccomandati nop forme per le istruzioni diverse lunghezze:

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 

Quindi, oltre a questi nop 's raccomandate da Intel, ci sono molti altri nop' s troppo. Oltre ad allineare l'istruzione di uno specifico confine della memoria, come Marc B cita nella sua risposta, nop 's sono anche molto utili in sé la modifica del codice, debugging e reverse-engineering.

+7

Si noti che su amd64, 'nop' non è più sinonimo di' xchg eax, eax'. 'nop' non azzera i primi 32 bit di' eax', ma 'xchg eax, eax' fa. – fuz

5

In realtà, NOP verrà utilizzato nel codice assembly quando ha bisogno di essere patchato il codice.

Poiché le dimensioni delle nuove istruzioni possono essere diverse da quelle precedenti, è necessario il riempimento.

L'istruzione di riempimento deve essere uguale a NOP, sebbene possa occupare diversi byte.

Il motivo per cui inseriamo un'istruzione più complessa, come 66 90, anziché diversi NOP, è che un'istruzione generalmente viene eseguita più rapidamente rispetto a diversi NOP.