NOP 指令作用

nop指令的作用:

1)就是通過nop指令的填充(nop指令一個字節),使指令按字對齊,從而減少取指令時的內存訪問次數。(一般用來內存地址偶數對齊,比如有一條指令,佔3字節,這時候使用nop指令,cpu 就可以從第四個字節處讀取指令了。)

2)通過nop指令產生一定的延遲,但是對於快速的CPU來說效果不明顯,可以使用rep前綴,多延遲幾個時鐘;-->具體應該說是佔用了3個時鐘脈衝!
3)i/o傳輸時,也會用一下 nop,等待緩衝區清空,總線恢復; 
4)清除由上一個算術邏輯指令設置的flag位; 
5)破解:)對於原程序中驗證部分使用nop來填充,使驗證失效; 
6)有一個朋友說的比較厲害--在航天飛機控制程序中防止程序跳飛! 
解釋如下:在空間放射性環境下,放射性子粒很容易使內存位元改變(呵呵,有點基因突變的感覺),這樣如果改變的是jump,call指令的存貯位置的話,就會導致程序跳轉到一個不可以預置的位置,對於關鍵系統來說的確是災難性的。所以就在被調用程序之前填充nop指令,這樣即使跳轉到稍前或者稍後的位置,也不會造成影響。 
這讓我想起《C Traps and Pitfalls》中舉的那個導彈軟件中的致命錯誤:因爲導彈是以0.1s爲單位進行記時的,但是由於浮點數沒有辦法精確的表示0.1,造成了舍尾誤差,這個誤差在導彈開啓3天的之後逐漸的積累,結果誤差了一秒。


以下來自http://wapedia.mobi/zh/NOP

計算機科學中,NOP或NOOP(No Operation或No Operation Performed的縮寫,意爲無操作)是彙編語言的一個指令,一系列編程語句,或網絡傳輸協議中的表示不做任何有效操作的命令。

目錄:
1. NOP機器指令
2. NOP代碼
3. NOP協議命令
4. 破解
5. 安全問題
6. 參見
7. 參考文獻

1. NOP機器指令

有的計算機指令集包含一條指令,其主要目的是不改變任何程序可訪問的寄存器,處理器狀態標誌或主存,而且可能需要特定的時鐘週期來執行。在其它指令集中,NOP是用執行一條具有操作數,具有相同效果的指令來模擬的(例如SPARC處理器推薦使用sethi 0, %g0模擬NOP)。

NOP指令通常用於控制時序的目的,強制內存對齊,防止流水線災難(en:Hazard (computer architecture)),佔據分支指令造成的延遲(delay slot),或是作爲佔位符以供程序的改善(或替代被移除的指令)。在某些情況中,NOP指令會產生副作用;例如在摩托羅拉 68000處理器中,NOP操作碼會產生流水線同步。

下表顯示了部分CPU架構上NOP指令的特徵:

CPU架構

助憶碼

字長

操作碼

備註

Intelx86系列CPU

NOP

1; i686中爲1-9

0x90; 0x0f 0x1f [2]

x86 CPU上的NOP指令實質上是XCHG EAX, EAX(操作碼同爲0x90)--無任何作用的指令。

Intel 8051 /MCS-51系列

NOP

1

0x00

 

MIPS

NOP

4

0x00000000

 

MOS科技 65xx

NOP

1

0xea

65C02處理器發佈時,之前多數的無效指令都被定義成了具有不同字長和需時的NOP指令。

PowerPC

NOP

4

0x60000000 (ori r0,r0,0的擴展操作碼)

 

2. NOP代碼

NOP有時可以描述函數或一系列編程語句的作用,若部分沒有作用(也可以稱爲冗餘代碼)。常見的編譯器優化的作用就包括檢測和去除這樣的代碼。

下面是一個起NOP作用的C語言語句的例子(評判標準在於語句是否影響程序輸出,而非編譯器是否爲語句產生代碼): <source lang="C">

i+1;

</source> (該語句執行了一個加法,但結果被丟棄。)

C語言中最簡單的NOP塊被稱爲空語句;其只包括一個分號。(標準沒有要求編譯器在這個例子中生成NOP指令;通常這個語句會直接爲編譯器所忽略。) <source lang="C">

;

</source>

雖然空語句自身沒有用處,但在某些情況下可以啓動佔位符的作用,例如在循環中: <source lang="C">

while (ReadChar() != '/n') ;

</source>

以上代碼一直調用ReadChar函數,直到函數返回一個/n(NL,新行)字符。

Python中的pass語句不會產生作用,可以作爲NOP使用。它的主要目的是保證語法正確,由於Python的縮進敏感語法。

3. NOP協議命令

許多協議,比如telnet,包含NOP指令,該指令允許客戶端可以在不會引起其它操作的情況下向服務器請求迴應。NOP指令可以用於檢測連接是否斷開,或服務器是否可以響應操作。下列協議中包含NOOP指令(不完全列表):

· telnet

· FTP

· SMTP

· X11

· POP3

· NNTP

· finger

· IMAP4

· BitTorrent

注意:與其它協議不同,IMAP4的NOP命令允許客戶端響應服務器發送由其它客戶端反應的操作信息。

雖然大多數telnet和FTP服務器用OK或+OK迴應NOOP指令,有的程序員在對客戶端的迴應中加入了特別的內容。例如MINIX的ftpd守護進程會以以下消息迴應NOOP:[3]

[[FTP服務器返回值列表|200]] NOOP to you too!

4. 破解

NOP通常在破解軟件時有特殊用途,例如檢查序列號,特定硬件或軟件需求,加密狗等的軟件。這是通過更改函數和/或子程序以跳過安全檢查,直接返回期望的檢測值實現的。由於大多數安全檢查子程序中的指令會被廢棄,它們會被NOP所代替。

5. 安全問題

NOP操作碼可以被用於組成一個NOP slide,允許在指令指針值未定義時執行代碼,例如緩存溢出導致棧上的函數返回地址被更改。

6. 參見

· 計算機系統結構

· HLT

· 指令集

· x86

· 恆等函數,函數式編程語言中NOOP的等效函數

· xyzzy,一個有時用來代替NOOP的命令

7. 參考文獻

 

1 ^ Motorola 68000 Programmer's Reference Manual.

2 ^ Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual [2007-07-13].


16進制機器碼   x86彙編指令   指令意義   可能影響的寄存器或標誌位 
--------------   -------------   -------------------   --------------------------- 
06   PUSHL   %es   es進棧   esp 
0E   PUSHL   %cs   cs進棧   esp 
16   PUSHL   %ss   ss進棧   esp 
1E   PUSHL   %ds   ds進棧   esp 
27   DAA   加法小數位調整   AF   CF   PF   SF   ZF   AL 
2F   DAS   減法小數位調整   AF   CF   PF   SF   ZF   AL 
37   AAA   加法的ASCII調整   AF   CF   AL 
3F   AAS   減法小數位調整   AF   CF   AL 
40   INC   %eax   %eax加1   AF   OF   PF   SF   ZF   eax 
41   INC   %ecx   %ecx加1   AF   OF   PF   SF   ZF   ecx 
42   INC   %edx   %edx加1   AF   OF   PF   SF   ZF   edx   
43   INC   %ebx   %ebx加1   AF   OF   PF   SF   ZF   ebx 
44   INC   %esp   %esp加1   AF   OF   PF   SF   ZF   esp 
45   INC   %ebp   %ebp加1   AF   OF   PF   SF   ZF   ebp 
46   INC   %esi   %esi加1   AF   OF   PF   SF   ZF   esi 
47   INC   %edi   %edi加1   AF   OF   PF   SF   ZF   edi 
48   DEC   %eax   %eax減1   AF   OF   PF   SF   ZF   eax 
49   DEC   %ecx   %ecx減1   AF   OF   PF   SF   ZF   ecx 
4A   DEC   %edx   %edx減1   AF   OF   PF   SF   ZF   edx 
4B   DEC   %ebx   %ebx減1   AF   OF   PF   SF   ZF   ebx 
4C   DEC   %esp   %esp減1   AF   OF   PF   SF   ZF   esp 
4D   DEC   %ebp   %ebp減1   AF   OF   PF   SF   ZF   ebp 
4E   DEC   %esi   %esi減1   AF   OF   PF   SF   ZF   esi 
4F   DEC   %edi   %edi減1   AF   OF   PF   SF   ZF   edi 
50   PUSHL   %eax   eax進棧   esp 
51   PUSHL   %ecx   ecx進棧   esp 
52   PUSHL   %edx   edx進棧   esp 
53   PUSHL   %ebx   ebx進棧   esp 
54   PUSHL   %esp   esp進棧   esp 
55   PUSHL   %ebp   ebp進棧   esp 
56   PUSHL   %esi   esi進棧   esp 
57   PUSHL   %edi   edi進棧   esp 
90   NOP   (NULL)   (NULL) 
91   XCHG   %ecx,%eax   交換寄存器內容   eax,ecx 
92   XCHG   %edx,%eax   交換寄存器內容   edx,eax 
93   XCHG   %ebx,%eax   交換寄存器內容   ebx,eax 
95   XCHG   %ebp,%eax   交換寄存器內容   ebp,eax 
96   XCHG   %esi,%eax   交換寄存器內容   esi,eax 
97   XCHG   %edi,%eax   交換寄存器內容   edi,eax 
98   CBW   將byte的AL轉換成word的EAX   EAX 
9B   WAIT   等待CPU處理完數據   (NULL) 
D6   無效指令   (NULL)   (NULL) 
F5   CMC   轉換CF標誌位(開關)   CF 
F8   CLC   清CF位(CF=0)   CF 
F9   STC   設置CF位(CF=1)   CF 
FC   CLD   設置DF位(DF=1)   DF 
FD   STD   清理DF位(DF=0)   DF 


1.   上面利用XCHG/PUSHL/INC/DEC的方法程序應該不會出錯, 可以正常到目的,   但寄存器內容被改變了.inc  eax就改變了eax的值, 只能算無奈的辦法. 
2.   利用改變標誌寄存器位是個不錯的想法,   基本上不會影響流程,   但看到還是改變了CPU的東西還是不滿意. 
3.   /x90(NOP),/x9b(wait),/xd6(bad)   這三個指令不錯,   都不會改變程序的流程,   又不會改變寄存器的東東. 
這裏尤其指明的是/xd6指令,   在intel手冊上沒查到對應什麼指令,   但在linux下和windows下發現系統對於這個是繼續 
執行下一條指令,和NOP相似. 
在我看來,上面這些指令利用順序優先級最好是: 

/x90(NOP)   >   /xd6   >   /x9b   >   改變標誌寄存器的操作指令   >   INC/DEC/PUSHL/XCHG 

還有http://www.zhihu.com/question/21122634


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章