|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2007-12-11, 02:13 PM | #1 |
註冊會員
|
疑問 - 請問一下在別版看到的一個有趣寫法??
我在微風C++版看到有人提出 兩個變數進行數值交換時
可以使用XOR的方式來交換 印象中好像是 a^= b^= a ^= b 反正就是利用XOR的特性直接進行數值交換 但是有某大提出效率的問題 他說這種方法效率會比多設一個變數還要少一半 且他也有自己用程式進行了一億次的試驗證明這個說法 只是很好奇說利用XOR的特性來寫 程式看起來相當的簡單整潔 為什麼效率會比多設一個變數來交換還要慢?? |
送花文章: 0,
|
2007-12-11, 03:19 PM | #2 (permalink) |
管理版主
|
這個人也蠻好奇的
所以做了以下實驗 先寫一段 語法:
#include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { int a=100,b=99; a^= b^= a ^= b; /* 寫的平民化一點就是 a=a^b; b=a^b; a=a^b; */ system("PAUSE"); return EXIT_SUCCESS; } 因為 99的16進制值 是 63 search一下就找到以下程式碼 語法:
MOV DWORD PTR SS:[EBP-4],64 ; | MOV DWORD PTR SS:[EBP-8],63 ; | MOV EDX,DWORD PTR SS:[EBP-8] ; | LEA EAX,DWORD PTR SS:[EBP-4] ; | XOR DWORD PTR DS:[EAX],EDX ; | MOV EDX,DWORD PTR SS:[EBP-4] ; | LEA EAX,DWORD PTR SS:[EBP-8] ; | XOR DWORD PTR DS:[EAX],EDX ; | MOV EDX,DWORD PTR SS:[EBP-8] ; | LEA EAX,DWORD PTR SS:[EBP-4] ; | XOR DWORD PTR DS:[EAX],EDX ; | MOV DWORD PTR SS:[ESP],專案1.00440000 ; |ASCII "PAUSE" CALL <JMP.&msvcrt.system> ; \system 接著再來比較用暫存變數的方式 a^= b^= a ^= b; 改成 tmp=a; a=b; b=tmp; 同樣觀察編組譯後的組合語言碼 語法:
MOV DWORD PTR SS:[EBP-4],64 ; | MOV DWORD PTR SS:[EBP-8],63 ; | MOV EAX,DWORD PTR SS:[EBP-4] ; | MOV DWORD PTR SS:[EBP-C],EAX ; | MOV EAX,DWORD PTR SS:[EBP-8] ; | MOV DWORD PTR SS:[EBP-4],EAX ; | MOV EAX,DWORD PTR SS:[EBP-C] ; | MOV DWORD PTR SS:[EBP-8],EAX ; | MOV DWORD PTR SS:[ESP],專案1.00440000 ; |ASCII "PAUSE" CALL <JMP.&msvcrt.system> ; \system 但仔細一看 原來還是編譯器在作祟 用暫存變數的方式之程式碼只花了 10行 而用互斥或方式之程式碼花了 13行 多出了 3行 LEA 機械碼 至於為何 互斥或方式 要用到 LEA呢 ? LEA 指令: 語法:
LEA 是 80x86 CPU 指令集的一員,在 8086 CPU 就已經有這個指令,這個指令是用來取得變數的位址,其語法是: LEA 暫存器,變數名 這個指令和 OFFSET 假指令的功能幾乎一樣,但是它是在 CPU 執行時,才取得變數的位址;而 OFFSET 則是在組譯時就取得位址。因此 LEA 可以用在變數位址可能會改變的情形,例如取得區域變數的位址。 可看出 堆疊節區 是用來做運算暫存的 資料節區 用來擺放結果 而 使用 mov 編譯器 只會用到 堆疊節區 (及暫存器) 資料在 堆疊節區 及 暫存器 之間移動 那一定要這麼做嗎? (xor) 這當然有它(編譯器)的理由 只是別人(編譯器)都這麼做了 除非你要 改寫編譯器 或 事後改寫機械碼(組合語言) 否則問這一句 沒有多大意義 當然 c/c++ 是很活的語言 你也可以自己寫 嵌入式組合語言在 c/c++裡 這樣編譯器就拿你沒則了 不過 在編譯後 有可能反而會再多出幾行 機械碼也不一定 (畢竟c/c++的嵌入式組合語言 編譯器 可不是照單全收的) 此帖於 2007-12-11 08:54 PM 被 mini 編輯. 原因: 打錯... |
送花文章: 2015,
|
|
|
相似的主題 | ||||
主題 | 主題作者 | 討論區 | 回覆 | 最後發表 |
請問一下關於照片做成vcd的一個問題 | hyc56721 | 一般電腦疑難討論區 | 2 | 2003-07-15 10:33 AM |