2012-09-24 16 views
22

¿cuál es la función de NOPL en la máquina x86? Parece que no hace nada, pero ¿por qué siempre está en el código de ensamblaje?¿Qué hace NOPL en el sistema x86?

+5

Usted pregunta "¿por qué siempre está en el código de ensamblado?" - normalmente no se encuentran muchos NOP en el código de ensamblado. ¿Algún código específico que estás viendo tiene muchos NOP? – ugoren

+5

¡Hombre, desearía poder "sentir" lo que hace el código! –

+0

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

Respuesta

31

NOP es una operación de un byte "no hacer nada", literalmente "sin operación". NOPW, NOPL, etc. son equivalentes a nada, pero toman bytes de palabra y de largo tamaño.

p. Ej.

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

es equivalente a hacer

NOPW // 2byte opcode. 

Son muy útil para cosas de relleno fuera por lo que una secuencia de código comienza en un límite de memoria en particular, mediante la adopción de unos pocos bytes de espacio de instrucción, aún no en realidad haciendo cualquier cosa.

único efecto de NOP en la CPU es incrementar IP/EIP por 1. Los equivalentes NOPx lo harán por 2, 4, etc ...

+1

nunca oído hablar de la operación y NOPW NOPL en el conjunto de instrucciones x86 de un .. ni aparecen en Intel Instruction Set Reference :) Quizás mezcles diferentes arquitecturas – Jack

+4

@Jack huele como la sintaxis de AT & T – harold

+0

@harold No sé ... gcc se queja si uso nopw/nopl en lugar de nop – Jack

28

Editar: referencias añaden a gasgas documentación y codificaciones para diferentes nop formas:

Según John Fremlin's blog: Operands to NOP on AMD64, nopw, nopl etc. son gas sintaxis, no AT & sintaxis T.

A continuación se muestran las codificaciones de instrucciones generadas por gas para nop diferentes desde gas source para longitudes de instrucción de 3 a 15 bytes. Tenga en cuenta que algunos son iguales a los formularios recomendados por nop de Intel (consulte a continuación), pero no todos. En particular, en el más largo nop 's gas utiliza múltiples (hasta 5) consecutivos 0x66 prefijos de operando en diferentes formas nop, mientras que Intel recomienda nop formas nunca utilice más de un prefijo 0x66 operando en un solo nop instrucciones recomendadas.

nop codificaciones de gas source (reformateado para mejorar la legibilidad):

/* 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 utiliza una sintaxis diferente, y hay nop 's disponibles para todas las longitudes de instrucción de 1 a 9 bytes. Hay varios nop diferentes, ya que todos los nop tienen más de dos bytes y aceptan 1 operando. Un byte nop (0x90) es sinónimo de 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 listas recomienda nop formas para diferentes longitudes instrucciones:

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 

Así que además de estos nop 's recomendados por Intel, hay muchas otras nop' s también. Además de alinear una instrucción a un límite de memoria específica, como Marc B menciona en su respuesta, nop 's son también muy útiles en la auto-modificación del código, depuración y la ingeniería inversa.

+7

en cuenta que en AMD64, 'nop' ya no es sinónimo de' xchg eax, eax'. 'nop' no pone a cero los 32 bits superiores de' eax', pero 'xchg eax, eax' sí lo hace. – fuz

5

En realidad, NOP será utilizado en el código de montaje cuando el código necesita ser parcheado.

Debido a que el tamaño de las nuevas instrucciones puede ser diferente al de las anteriores, se necesita relleno.

La instrucción de relleno debe actuar igual que NOP, aunque puede ocupar varios bytes.

La razón por la que insertamos una instrucción más compleja, como 66 90, en lugar de varios NOP, es una instrucción que generalmente se ejecuta más rápidamente que varios NOP.