日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

汇编级代码优化

發布時間:2025/3/21 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 汇编级代码优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

代碼優化的含義:
?
代碼優化的目標當然是體積小和速度快,但是在通常的情況下二者就象魚和熊掌一樣不能得
兼,我們通常尋找的是這二者的折中,究竟應該偏向何方,那就得具體看我們的實際需要.
但有些常識是我們應該牢記的,下面就結合我們最常遇到的具體情況來漫談一下:
?
1.寄存器清0
????????我絕對不想再看到下面的寫法:
????????1)??????mov?eax,?00000000h????????????????????;5?bytes
????????看起來上面的寫法很符合邏輯,但你應當意識到還有更加優化的寫法:
????????2)??????sub?eax,?eax??????????????????????????;2?bytes
????????3)??????xor?eax,?eax??????????????????????????;2?bytes
????????看看后面的字節數你就應該理解為什么要這么作了,除此之外,在速度上也沒有損
失,他們一樣快,但你喜歡xor還是sub呢?我是比較喜歡xor,原因很簡單,因為我數學不好..
..


????????不過Microsoft比較喜歡sub....我們知道windows運行的慢....(呵呵,當然是玩笑
這并不是真正原因X-D!)
?
2.測試寄存器是否為0
????????我也不希望看到下面的代碼:

????????1)??????cmp?eax,?00000000h????????????????????;5?bytes
????????????????je?_label_????????????????????????????;2/6?bytes?(short/near)
?
????????[*?注意很多指令針對eax作了優化,你要盡可能多地實用eax,比如CMP?EAX,?1234
5678h?(5?bytes)?如果你使用其他寄存器,就是6bytes?*]
?
????????讓我們看看,簡單的比較指令居然要用7/11?bytes,No?No?No,試試下面的寫法:
????????2)??????or?eax,?eax??????????????????????????;2?bytes
????????????????je?_label_????????????????????????????;2/6?(short/near)
????????3)??????test?eax,?eax????????????????????????;2?bytes
????????????????je?_label_????????????????????????????;2/6?(short/near)
????????呵呵,只有4/8?bytes,看看我們可節省多少字節啊3/4字節...那么接下來的問題是
你喜歡OR還是TEST呢,就我個人而言,比較喜歡TEST,因為test不改變任何寄存器,并不向任
何寄存器寫入內容,這通常能在pentium機上取得更快的執行速度.
?
????????別高興的太早,因為還有更值得我們高興的事情,假如你要判斷的的是eax寄存器,
那么看看下面的,是不是更有啟發?


????????4)??????xchg?eax,?ecx????????????????????????;1?byte
????????????????jecxz?_label_????????????????????????;2?bytes
????????在短跳轉的情況下我們比2)和3)又節省了1字節.oh....___...
?
3.測試寄存器是否為0FFFFFFFFh
????????一些API返回-1,因此如何測試這個值呢?看你可能又要這樣:
????????1)??????cmp?eax,?0ffffffffh??????????????????;5?bytes
????????????????je?_label_????????????????????????????;2/6?bytes
????????hey,不要這樣,寫代碼的時候想一想,于是有了下面的寫法:
????????2)??????inc?eax??????????????????????????????;1?byte
????????????????je?_label_????????????????????????????;2/6?bytes
????????????????dec?eax??????????????????????????????;1?byte
????????可以節省3?bytes并且執行速度會更快.
?
4.置寄存器為0FFFFFFFFh
????????看看假如你是Api的作者,如何返回-1?這樣嗎?
????????1)??????mov?eax,?0ffffffffh??????????????????;5?bytes
????????看了上面的不會再這么XXX了吧?看看下面的:
????????2)??????xor?eax,?eax?/?sub?eax,?eax??????????;2?bytes
????????????????dec?eax??????????????????????????????;1?byte
????????節省一個字!還有寫法:
????????3)??????stc??????????????????????????????????;1?byte


????????????????sbb?eax,?eax?????????????????????????;2?bytes
????????這有時還可以優化掉1?byte:
????????????????jnc?_label_
????????????????sbb?eax,?eax??????????????????????????;2?bytes?only!
??????_label_:?...
??????我們為什么用asm呢?這就是原因.
?
5.寄存器清0并移入低字數值
????????1)??????xor?eax,?eax??????????????????????????;2?bytes
????????????????mov?ax,?word?ptr?[esi+xx]????????????;4?bytes
????????????--->不會吧,這可能是最多初學者的寫法了,我當然原來也是,看了benny的文
章之后我決定改寫為:
????????2)??????movzx?eax,?word?ptr?[esi+xx]??????????;4?bytes
????????收獲2?bytes!
????????下面的
????????3)??????xor?eax,?eax??????????????????????????;2?bytes
????????????????mov?al,?byte?ptr?[esi+xx]????????????;3?bytes
????????就相應改為:
????????4)??????movzx?eax,?byte?ptr?[esi+xx]??????????;4?bytes
????????我們應當盡可能利用movzx
????????5)??????xor?eax,?eax??????????????????????????;2?bytes
????????????????mov?ax,?bx????????????????????????????;3?bytes


????????因為執行速度不慢并通常能節省字節...
????????6)??????movzx?eax,?bx????????????????????????;3?bytes
?
6.關于push,下面是著重代碼體積的優化,因為寄存器操作總要比內存操作要快.
????????1)??????mov?eax,?50h??????????????????????????;5?bytes
????????這樣就小了1?word
????????2)??????push?50h??????????????????????????????;2?bytes
????????????????pop?eax??????????????????????????????;1?byte
????????當操作數只有1字節時候,push只有2?bytes,否則就是5?bytes,記住!
?
????????下一個問題,向堆棧中壓入7個0
????????3)??????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
????????????????push?0????????????????????????????????;2?bytes
??????占用14字節,顯然不能滿意,優化一下
????????4)??????xor?eax,?eax??????????????????????????;2?bytes
????????????????push?eax??????????????????????????????;1?byte
????????????????push?eax??????????????????????????????;1?byte


????????????????push?eax??????????????????????????????;1?byte
????????????????push?eax??????????????????????????????;1?byte
????????????????push?eax??????????????????????????????;1?byte
????????????????push?eax??????????????????????????????;1?byte
????????????????push?eax??????????????????????????????;1?byte
????????可以更緊湊,但會慢一點的形式如下:
????????5)??????push?7????????????????????????????????;2?bytes
????????????????pop?ecx??????????????????????????????;1?byte
??????_label_:??push?0????????????????????????????????;2?bytes
????????????????loop?_label_??????????????????????????;2?bytes
????????可以節省7字節....
?
????????有時候你可能會從將一個值從一個內存地址轉移到另外內存地址,并且要保存所有
寄存器:
????????6)??????push?eax??????????????????????????????;1?byte
????????????????mov?eax,?[ebp?+?xxxx]??????????????????;6?bytes
????????????????mov?[ebp?+?xxxx],?eax??????????????????;6?bytes
????????????????pop?eax????????????????????????????????;1?byte
????????試試push,pop
????????7)??????push?dword?ptr?[ebp?+?xxxx]????????????;6?bytes
????????????????pop?dword?ptr?[ebp?+?xxxx]????????????;6?bytes
?


7.乘法
?
????????當eax已經放入被乘數,要乘28h,如何來寫?
????????1)??????mov?ecx,?28h??????????????????????????;5?bytes
????????????????mul?ecx??????????????????????????????;2?bytes
??????好一點的寫法如下:
????????2)??????push?28h??????????????????????????????;2?bytes
????????????????pop?ecx??????????????????????????????;1?byte
????????????????mul?ecx??????????????????????????????;2?bytes
????????哇這個更好::
????????3)??????imul?eax,?eax,?28h????????????????????;3?bytes
????????intel在新CPU中提供新的指令并不是擺設,需要你的使用.
?
8.字符串操作
????????你如何從內存取得一個字節呢?
????????速度快的方案:
????????1)??????mov?al/ax/eax,?[esi]??????????????????;2/3/2?bytes
????????????????inc?esi??????????????????????????????;1?byte
????????代碼小的方案:
????????2)??????lodsb/w/d????????????????????????????;1?byte
????????我比較喜歡lod因為他小,雖然速度慢了點.
?


????????如何到達字符串尾呢?
??????JQwerty's?method:
????????9)??????lea?esi,?[ebp?+?asciiz]??????????????;6?bytes
??????s_check:?lodsb????????????????????????????????;1?byte
????????????????test?al,?al??????????????????????????;2?bytes
????????????????jne?s_check??????????????????????????;2?bytes
????????Super's?method:
????????10)????lea?edi,?[ebp?+?asciiz]??????????????;6?bytes
????????????????xor?al,?al????????????????????????????;2?bytes
??????s_check:?scasb????????????????????????????????;1?byte
????????????????jne?s_check??????????????????????????;2?byte
??????選擇哪一個?Super的在386以下的更快,JQwerty的在486以及pentium上更快,體積一
樣,選擇由你.
?
9.復雜一點的...
????????假設你有一個DWORD表,ebx指向表的開始,ecx是指針,你想給每個doword加1,看看
如何作:
????????1)??????pushad????????????????????????????????;1?byte
????????????????imul?ecx,?ecx,?4??????????????????????;3?bytes
????????????????add?ebx,?ecx??????????????????????????;2?bytes
????????????????inc?dword?ptr?[ebx]??????????????????;2?bytes
????????????????popad????????????????????????????????;1?byte


????????可以優化一點,但是好像沒人用:
????????2)??????inc?dword?ptr?[ebx+4*ecx]????????????;3?bytes
????????一條指令就節省6字節,而且速度更快,更易讀,但好像沒有什么人用?...why?
????????還可以有立即數:
????????3)??????pushad????????????????????????????????;1?byte
????????????????imul?ecx,?ecx,?4??????????????????????;3?bytes
????????????????add?ebx,?ecx??????????????????????????;2?bytes
????????????????add?ebx,?1000h????????????????????????;6?bytes
????????????????inc?dwor?ptr?[ebx]????????????????????;2?bytes
????????????????popad????????????????????????????????;1?byte
????????優化為:
????????4)??????inc?dword?ptr?[ebx+4*ecx+1000h]??????;7?bytes
????????節省了8字節!
?
????????看一下lea指令能為我們干點什么呢?
????????????????lea?eax,?[12345678h]
????????eax的最后結果是什么呢?正確答案是12345678h.
????????假設?EBP?=?1
????????????????lea?eax,?[ebp?+?12345678h]
????????結果是123456789h....呵呵比較一下:
????????????????lea?eax,?[ebp?+?12345678h]????????????;6?bytes
????????????????==========================


????????????????mov?eax,?12345678h????????????????????;5?bytes
????????????????add?eax,?ebp??????????????????????????;2?bytes
?
????????5)?看看:
????????????????mov?eax,?12345678h????????????????????;5?bytes
????????????????add?eax,?ebp??????????????????????????;2?bytes
????????????????imul?ecx,?4??????????????????????????;3?bytes
????????????????add?eax,?ecx??????????????????????????;2?bytes
????????6)?用lea來進行一些計算我門將從體積上得到好處:
????????????????lea?eax,?[ebp+ecx*4+12345678h]????????;7?bytes
????????速度上一條lea指令更快!不影響標志位...記住下面的格式,在許多地方善用他們
你可以節省時間和空間.
????????????????OPCODE?[BASE?+?INDEX*SCALE?+?DISPLACEMENT]
?
10.下面是關于病毒重定位優化的,懼毒人士請繞行...
?
????????下面的代碼你不應該陌生
????????1)??????call?gdelta
????????gdelta:?pop?ebp
????????????????sub?ebp,?offset?gdelta
????????在以后的代碼中我們這樣使用delta來避免重定位問題
????????????????lea?eax,?[ebp?+?variable]


????????這樣的指令在應用內存數據的時候是不可避免的,如果能優化一下,我門將會得到
數倍收益,打開你的sice或者trw或者ollydbg等調試器,看看:
????????3)??????lea?eax,?[ebp?+?401000h]??????????????;6?bytes
?
????????假如是下面這樣
????????4)??????lea?eax,?[ebp?+?10h]??????????????????;3?bytes
????????也就是說如果ebp后面變量是1字節的話,總的指令就只有3字節
????????修改一下最初的格式變為:
????????5)??????call?gdelta
????????gdelta:?pop?ebp
????????在某些情況下我們的指令就只有3字節了,可以節省3字節,嘿嘿,讓我們看看:
????????6)??????lea?eax,?[ebp?+?variable?-?gdelta]????;3?bytes
????????和上面的是等效的,但是我們可以節省3字節,看看CIH...
?
11.其他技巧:
??????如果EAX小于80000000h,edx清0:
????????--------------------------------------------------
????????1)??????xor?edx,?edx??????????????????????????;2?bytes,?but?faster
????????換種寫法:
????????2)??????cdq??????????????????????????????????;1?byte,?but?slower
????????我一直使用cdq,為什么不呢?體積更小...
?


????????下面這種情況一般不要使用esp和ebp,使用其他寄存器.
????????-----------------------------------------------------------
????????1)??????mov?eax,?[ebp]????????????????????????;3?bytes
????????2)??????mov?eax,?[esp]????????????????????????;3?bytes
????????3)??????mov?eax,?[ebx]????????????????????????;2?bytes
?
????????交換寄存器中4個字節的順序?用bswap
????????---------------------------------------------------------
????????????????mov?eax,?12345678h????????????????????;5?bytes
????????????????太長了,這樣:
????????????????bswap?eax????????????????????????????;2?bytes
????????????????;eax?=?78563412h?now
?
????????Wanna?save?some?bytes?replacin'?CALL??
????????---------------------------------------
????????1)??????call?_label_??????????????????????????;5?bytes
????????????????ret??????????????????????????????????;1?byte
????????改為如下:
????????2)??????jmp?_label_??????????????????????????;2/5?(SHORT/NEAR)
????????如果僅僅是優化,并且不需要傳遞參數,請盡量用jmp代替call
?
????????比較?reg/mem?時如何節省時間:


????????------------------------------------------
????????1)??????cmp?reg,?[mem]????????????????????????;slower
????????這樣寫:
????????2)??????cmp?[mem],?reg????????????????????????;1?cycle?faster
?
????????乘2除2如何節省時間和空間?
????????------------------------------------------------------------
????????1)??????mov?eax,?1000h
????????????????mov?ecx,?4????????????????????????????;5?bytes
????????????????xor?edx,?edx??????????????????????????;2?bytes
????????????????div?ecx??????????????????????????????;2?bytes
????????移位:
????????2)??????shr?eax,?4????????????????????????????;3?bytes
????????除法呢?
????????3)??????mov?ecx,?4????????????????????????????;5?bytes
????????????????mul?ecx??????????????????????????????;2?bytes
????????當然也一樣拉
????????4)??????shl?eax,?4????????????????????????????;3?bytes
?
????????loop指令
????????------------------------
????????1)??????dec?ecx??????????????????????????????;1?byte



????????????????jne?_label_??????????????????????????;2/6?bytes?(SHORT/NEAR)
????????分特,loop沒學過?
????????2)??????loop?_label_??????????????????????????;2?bytes
????????再看:
????????3)??????je?$+5????????????????????????????????;2?bytes
????????????????dec?ecx??????????????????????????????;1?byte
????????????????jne?_label_??????????????????????????;2?bytes
????????記住loop
????????4)??????loopXX?_label_?(XX?=?E,?NE,?Z?or?NZ)??;2?bytes
????????loop體積小,但486以上的cpu上執行速度會慢一點...

?
????????交換寄存器:
????????---------------------------------------------------------
????????1)??????push?eax??????????????????????????????;1?byte
????????????????push?ebx??????????????????????????????;1?byte
????????????????pop?eax??????????????????????????????;1?byte
????????????????pop?ebx??????????????????????????????;1?byte
????????明明有指令嘛:
????????2)??????xchg?eax,?ebx????????????????????????;1?byte
?
????????3)??????xchg?ecx,?edx????????????????????????;2?bytes
????????如果僅僅是想移動數值,用mov,在pentium上會有較好的執行速度:


????????4)??????mov?ecx,?edx??????????????????????????;2?bytes
?
????????比較以下程序:
????????--------------------------------------------
????????1)?未優化:
????????lbl1:??mov?al,?5????????????????????????????;2?bytes
????????????????stosb????????????????????????????????;1?byte
????????????????mov?eax,?[ebx]????????????????????????;2?bytes
????????????????stosb????????????????????????????????;1?byte
????????????????ret??????????????????????????????????;1?byte
????????lbl2:??mov?al,?6????????????????????????????;2?bytes
????????????????stosb????????????????????????????????;1?byte
????????????????mov?eax,?[ebx]????????????????????????;2?bytes
????????????????stosb????????????????????????????????;1?byte
????????????????ret??????????????????????????????????;1?byte
??????????????????????????????????????????????????????---------
??????????????????????????????????????????????????????;14?bytes
????????2)?優化了:
????????lbl1:??mov?al,?5????????????????????????????;2?bytes
????????lbl:????stosb????????????????????????????????;1?byte
????????????????mov?eax,?[ebx]????????????????????????;2?bytes
????????????????stosb????????????????????????????????;1?byte


????????????????ret??????????????????????????????????;1?byte
????????lbl2:??mov?al,?6????????????????????????????;2?bytes
????????????????jmp?lbl??????????????????????????????;2?bytes
????????要善于利用代碼哦?:)???????????????????????????---------
??????????????????????????????????????????????????????;11?bytes
?
??????讀取常數變量,試試在指令中直接定義:
??????-----------------------------
??????mov?eax,?[ebp?+?variable]????????????;6?bytes
????????????????...
??????mov?[ebp?+?variable],?eax????????????;6?bytes
????????????????...
????????????????...
??????variable?dd??????12345678h????????????????????;4?bytes
?
??????2)?優化為:
??????mov?eax,?12345678h????????????????????;5?bytes
??????variable?=?dword?ptr?$?-?4
????????????????...
????????????????...
??????mov?[ebp?+?variable],?eax????????????;6?bytes
????????呵呵,好久沒看到這么有趣的代碼了,前提是編譯的時候支持代碼段的寫入屬性要


????????最后介紹未公開指令SALC,現在的調試器都支持...什么含義呢:就是CF位置1的話
就將al置為0xff
????????------------------------------------------------------------------
????????1)??????jc?_lbl1??????????????????????????????;2?bytes
????????????????mov?al,?0????????????????????????????;2?bytes
????????????????jmp?_end??????????????????????????????;2?bytes
??????????_lbl:?mov?al,?0ffh??????????????????????????;2?bytes
??????????_end:?...
????????當然用SALC啦
????????2)??????SALC??db????0d6h????????????????????;1?byte?;)

?

轉自:http://www.newsmth.net/bbsanc.php?p=567-6-1-3


from:?http://blog.csdn.net/pennyliang/article/details/6156830

總結

以上是生活随笔為你收集整理的汇编级代码优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。