2012-09-24 10 views
22

jaka jest funkcja NOPL na maszynie x86? Wydaje się, że nic nie robi, ale dlaczego zawsze jest w kodzie montażowym?Co robi NOPL w systemie x86?

+5

Pytasz "dlaczego jest zawsze w kodzie zespołu?" - zazwyczaj nie znajdujesz wielu NOP-ów w kodzie zespołu. Czy jakiś konkretny kod, który przeglądasz, ma wiele NOPów? – ugoren

+5

Człowieku, chciałbym móc "poczuć", co robi kod! –

+0

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

Odpowiedz

31

NOP to jednobajtowa operacja "do niczego", dosłownie "brak operacji". NOPW, NOPL itd. Są równoważnymi do-nothings, ale przyjmują słowo i długie bajty.

np.

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

jest równoważna robi

NOPW // 2byte opcode. 

Są bardzo przydatne dla dopełnienia rzeczy więc sekwencja kodu zaczyna się na konkretnej granicy pamięci, podejmując się kilka bajtów przestrzeni instrukcji, jeszcze nie właściwie robiąc cokolwiek.

jedynym efektem NOP w sprawie CPU jest przyrost IP/EIP przez 1. ekwiwalenty NOPx zrobi to przez 2, 4, itd ...

+1

Nigdy nie słyszałem o operacji NOPW i NOPL w zestawie instrukcji x86 .. ani pojawiają się w zestawie instrukcji Intel Instruction :) Może mieszasz różne architektury – Jack

+4

@Jack pachnie jak składnia AT & T do mnie – harold

+0

@harold Nie wiem .. gcc narzeka, jeśli używam nopw/nopl zamiast nop – Jack

28

Edit: Dodano odniesienia do dokumentacji i gasgas kodowań dla różnych nop formach:

Według John Fremlin's blog: Operands to NOP on AMD64, nopw, nopl itp są gas składni, a nie na & składni T.

Poniżej instrukcja kodowania generowane przez gas dla różnych nop „s od gas source instrukcji dla długościach od 3 do 15 bajtów. Zauważ, że niektóre z nich są takie same jak zalecane przez Intela formularze nop (patrz poniżej), ale nie wszystkie. W szczególności, już nop „s gas wykorzystuje wiele (do 5) kolejnych 0x66 operandów prefiksy w różnych formach nop, natomiast Intel zaleca nop formy nigdy nie używać więcej niż jednego 0x66 prefiks argumentu w jakiejkolwiek pojedynczej zalecanej instrukcji nop.

nop kodowania z gas source (przekształcony dla czytelności):

/* 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 używa innej składni, a istnieją nop „s dostępne dla wszystkich długościach instrukcje od 1 do 9 bajtów. Istnieje kilka różnych nop, ponieważ wszystkie nop dłuższe niż dwa bajty akceptują 1 operand. One-byte nop (0x90) jest równoznaczne z 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 list polecany nop formy dla różnych długościach instrukcje:

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 

Więc oprócz tych nop 's rekomendowanych przez firmę Intel, istnieje wiele innych nop' s zbyt. Oprócz dopasowania instrukcji do określonej granicy pamięci, jak wspomina Marc B w swojej odpowiedzi, nop są również bardzo użyteczne w korygowaniu samego kodu, debugowaniu i inżynierii wstecznej.

+7

Zauważ, że na amd64 'nop' nie jest już równoznaczny z' xchg eax, eax'. 'nop' nie wyzerowuje 32 najlepszych bitów' eax', ale 'xchg eax, eax' robi. – fuz

5

W rzeczywistości NOP zostanie użyty w kodzie zespołu, gdy kod będzie wymagał poprawki.

Ponieważ rozmiar nowej instrukcji może różnić się od starej, konieczne jest wypełnienie.

Instrukcja wypełniania powinna zachowywać się tak samo, jak NOP, chociaż może zajmować kilka bajtów.

Powodem, dla którego wstawiamy bardziej złożoną instrukcję, np. 66 90, zamiast kilku NOP, jest jedna instrukcja generalnie wykonywana szybciej niż kilka NOP.