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