2014-12-31 2 views
2

작은 기억에서 x86 아키텍처는 0x0F 0x1F [mod R/M]을 다중 바이트 NOP로 정의합니다. x86 멀티 바이트 NOP 및 명령어 접두어

는 지금은 8 바이트 NOP의 특정한 경우에 찾고 있어요 : 나는 지난 5 바이트가 임의의 값을 가지고있다
0x0F 0x1F 0x84 0x__ 0x__ 0x__ 0x__ 0x__ 

을 가지고있다. 분할

제 3 바이트, [mod R/M]는 범 :

modrm http://www.swansontec.com/smodrm.png

  • mod = 10b : 인자이다 reg1 + A DWORD 크기 변위
  • reg2 = 000b는 (우리는 신경 쓰지 않는다)
  • reg1 = 100b : 인수가 대신 SIB 바이트 + DWORD 크기의 위치 변경임을 나타냅니다.

지금은 추가 할 DWORD :

이제 구체적인 예로서, 나는

0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A 

를 수강하면이

  • SIB = 0x12
  • displacement = 0x9A785634있어 0x66 instr uction 접두사는 변위 대신 DWORD의 단어를해야한다고 나타냅니다 :

    0x66 0x0F 0x1F 0x84 0x12 0x34 0x56 0x78 0x9A 
    

    나는 0x78 0x9A가 '차단'하는 새로운 명령으로 처리 될 것으로 예상된다. 그러나이 파일을 컴파일하고 실행 결과에 objdump을 실행하면 모든 4 바이트 (DWORD)가 여전히 위치 변경으로 사용됩니다.

    나는이 맥락에서 '변위'의 의미를 오해하니? 또는 0x66 접두어가 멀티 바이트 NOP 명령어에 아무런 영향을 미치지 않습니까?

+2

0x66 접두사는 변위 크기에 영향을 미치지 않으며 피연산자 크기에만 영향을줍니다. –

+0

명령어의 구성 요소가 Prefix, Opcode, Mod R/M, SIB, Displacement, Immediate이면 0x66이 * Immediate * 값에 영향을 줍니까? 좋아요, 그것은 일종의 의미가 있습니다 : 멀티 바이트 NOP는 즉각적인 가치를 가지지 않으므로 0x66은 아무런 효과가 없습니다. 고맙습니다! – ayekat

답변

2

접두사 66H 접두어는 피연산자의 크기를 16 비트보다 우선합니다.
사용하려는 경우 주소 크기를 무시하지 않습니다. 67H

다음은 모든 피연산자 목록입니다.

 F0h = LOCK -- locks memory reads/writes 
     String prefixes 
     F3h = REP, REPE 
     F2h = REPNE  
     Segment overrides 
     2Eh = CS 
     36h = SS 
     3Eh = DS 
     26h = ES 
     64h = FS 
     65h = GS 
     Operand override 
     66h. Changes size of data expected to 16-bit 
     Address override 
     67h. Changes size of address expected to 16-bit 

그러나 자신의 nop 명령어를 만들지 말고 권장 (멀티 바이트) nop을 사용하는 것이 가장 좋습니다.

표 4-9를 다음과 같이 AMD 권장 멀티 바이트의 NOP를에 따르면

입니다.11 바이트까지 NOP 년대는과 같이 구성 할 수 있도록 NOP 명령

bytes sequence    encoding 

1  90H       NOP 
2  66 90H       66 NOP 
3  0F 1F 00H      NOP DWORD ptr [EAX] 
4  0F 1F 40 00H     NOP DWORD ptr [EAX + 00H] 
5  0F 1F 44 00 00H    NOP DWORD ptr [EAX + EAX*1 + 00H] 
6  66 0F 1F 44 00 00H    NOP DWORD ptr [AX + AX*1 + 00H] 
7  0F 1F 80 00 00 00 00H   NOP DWORD ptr [EAX + 00000000H] 
8  0F 1F 84 00 00 00 00 00H  NOP DWORD ptr [AX + AX*1 + 00000000H] 
9  66 0F 1F 84 00 00 00 00 00H NOP DWORD ptr [AX + AX*1 + 00000000H] 

의 권장 멀티 바이트 시퀀스는 인텔, 최대 3 중복 접두사를 상관하지 않습니다.

10  66 66 0F 1F 84 00 00 00 00 00H  NOP DWORD ptr [AX + AX*1 + 00000000H] 
11  66 66 66 0F 1F 84 00 00 00 00 00H NOP DWORD ptr [AX + AX*1 + 00000000H] 

당연히 여분의 접두사가있는 일반 지침 앞에 접두어를 붙임으로써 nop을 제거 할 수도 있습니다.

rep mov reg,reg //one extra byte 

또는 강제로 동일한 명령어의 더 긴 버전을 사용하십시오.

test r8d,r8d is one byte longer than: test edx,edx 

즉각적인 피연산자가있는 명령어에는 짧고 긴 버전이 있습니다.

and edx,7 //short 
and edx,0000007 //long 

대부분의 어셈블러는 지연을 초래하지 않고도 점프 목표를 정렬하는 데 도움 수있는 전략적 위치에있는이 산재 db

를 사용하여 더 이상 설명을 직접 코딩해야하므로 유용하게 당신을 위해 모든 지침을 단축 nop의 디코딩 또는 실행으로 인해

대부분의 CPU가 실행중인 nop가 여전히 리소스를 사용하고 있음을 기억하십시오.

+0

[yasm docs] (http://www.tortall.net/projects/yasm/manual/html/manual.html#nasm-immediate)에서는'add rax, dword 1'을 써서 32 비트를 즉시 강제 실행한다고합니다 그러나 실제로는 작동하지 않습니다. (우분투 패키지에서'yasm 1.3.0'을 사용하면 imm8로 단축됩니다.) 또한 명령어가 레지스터를 필요로하지 않더라도 REX 접두어로 덧붙일 수 있습니다. 'db 0x40' /'test edx, edx'는 여전히'test edx, edx'로 디코딩됩니다. 비트가 설정되지 않은 REX는 AH/BH/CH/DH를 사용하는 insn의 의미 만 변경합니다. (SIL 등으로, 어떤 순서로보아야 할 것입니다.) –

+1

업데이트 : YASM :'add rax, strict dword 1'은 32 비트를 강제 실행합니다. NASM :'add rax, strict qword 1'은 32 비트를 즉각적으로 강제합니다. NASM과 YASM은 크기에 대해 불평하면서 다른 하나를 질식시킵니다. 하지만 어쨌든, '엄격한'은 즉각적이고 주소 지정이 가능한 치환을위한 NASM 구문의 핵심 키워드입니다. –

+0

인텔은 나중에 새로운 의미를 부여하기 때문에 'rep'접두어를 사용하지 않는 것이 좋습니다. 예를 들어'rep mov '는 인텔 HLE에서 의미가 있습니다. – fuz