GCC內聯彙編(2)GCC生成彙編程式碼簡單例項
GCC內聯彙編(2)GCC生成彙編程式碼簡單例項
- 作者:柳大·Poechant(鍾超)
- 郵箱:zhongchao.ustc#gmail.com(# -> @)
- 部落格:Blog.CSDN.net/Poechant
- 日期:July 8th, 2012
1 準備示例
先看一個空的 main 函式會生成怎樣的彙編程式碼。要注意的是我這裡是在 Mac OS X 上進行的測試,編譯器是 Apple’s version of GCC,實際上用的是 llvm-gcc。
[程式碼段-1]
int main() {
return 0;
}
[命令列-1]
gcc -S main.c
生成的彙編如下(這裡只擷取主要部分,下同):
[程式碼段-2]
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
movl $0, -8(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
pop %rbp
ret
Leh_func_end1:
如果開啟優化編譯選項呢?一定會有一些變化吧。
[命令列-2]
gcc -S main.c -O3
[程式碼段-3]
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
xorl %eax, %eax
popq %rbp
pop %rbp
ret
Leh_func_end1:
是的,一些“廢話”被優化掉了。
[程式碼段-4]
int main() {
int a = 19, b = 100;
return 0;
}
看下面的簡單例項,宣告兩個整形變數,並賦以初值。
[命令列-3]
gcc -S main.c
生成的彙編程式碼如下。可以看到 a 代表的區域性變數值 19 被壓入棧中,位置是棧基址減去 12,b 代表的區域性變數壓入棧中,位置是棧基址減去 16,而返回值所使用的立即數 0 被放入棧基址減去 8。
[程式碼段-5]
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
movl $19, -12(%rbp)
movl $100, -16(%rbp)
movl $0, -8(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
pop %rbp
ret
Leh_func_end1:
如果開啟優化編譯選項編譯,則會把int a = 19, b = 100
這句優化掉,從而與[程式碼段-3]一樣。
2 內聯彙編例項
int main(){
int a = 19, b = 100;
__asm__ (
"addl %2, %1";
: "=a"(a)
: "a"(a), "b"(b)
: "%eax", "%ebx"
)
return 0;
}
生成的彙編如下:
_main:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
pushq %rbx
subq $24, %rsp
Ltmp2:
movl $19, -20(%rbp) # 區域性變數 a 的位置是棧基址減去 20
movl $100, -24(%rbp) # 區域性變數 b 的位置是棧基址減去 24
# 處理內斂彙編的入口
movl -20(%rbp), %eax
movl -24(%rbp), %ecx
movl %ecx, %ebx
## InlineAsm Start
addl %ebx, %eax;
## InlineAsm End
movl %eax, -20(%rbp) # 返回值放在指定的區域性變數 a 中
# 剩下的部分與前面的簡單例項一樣,就是處理返回值
movl $0, -16(%rbp)
movl -16(%rbp), %eax
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
popq %rbx
popq %rbp
ret
Leh_func_end1:
#include <stdio h=""></stdio><stdio h=""><span class="keyword" style="font-weight: bold; ">int</span> main() {
<span class="keyword" style="font-weight: bold; ">int</span> a = <span class="number" style="color: rgb(0, 136, 0); ">19</span>, b = <span class="number" style="color: rgb(0, 136, 0); ">100</span>;
__asm__ (
<span class="string" style="color: rgb(136, 0, 0); ">"addl %1, %0;"</span>
: <span class="comment" style="color: rgb(136, 136, 136); ">//no output</span>
: <span class="string" style="color: rgb(136, 0, 0); ">"a"</span>(a), <span class="string" style="color: rgb(136, 0, 0); ">"b"</span>(b)
: <span class="string" style="color: rgb(136, 0, 0); ">"%eax"</span>, <span class="string" style="color: rgb(136, 0, 0); ">"%ebx"</span>
);
<span class="keyword" style="font-weight: bold; ">return</span> <span class="number" style="color: rgb(0, 136, 0); ">0</span>;
}
</stdio>
_main:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
pushq %rbx
Ltmp2:
# Immediate numbers
movl $19, -20(%rbp)
movl $100, -24(%rbp)
# Input
movl -20(%rbp), %eax
movl -24(%rbp), %ecx
movl %ecx, %ebx
## InlineAsm Start
addl %ebx, %eax;
## InlineAsm End
# Note: no output
# Similar to above examples
movl $0, -16(%rbp)
movl -16(%rbp), %eax
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
popq %rbx
popq %rbp
ret
Leh_func_end1:
也間接證實了%0
,%1
,%2
⋯⋯ 是從輸出開始排序的,如果沒有輸出,就從輸入開始排序。
另外使用m
則可以表示memory
,即變數是在記憶體中,而非暫存器中。如下示例:
#include <stdio h=""></stdio><stdio h=""><span class="keyword" style="font-weight: bold; ">int</span> main() {
<span class="keyword" style="font-weight: bold; ">int</span> a = <span class="number" style="color: rgb(0, 136, 0); ">17</span>, b = <span class="number" style="color: rgb(0, 136, 0); ">100</span>;
__asm__ (
<span class="string" style="color: rgb(136, 0, 0); ">"addl %2, %1;"</span>
: <span class="string" style="color: rgb(136, 0, 0); ">"=m"</span>(a)
: <span class="string" style="color: rgb(136, 0, 0); ">"m"</span>(a), <span class="string" style="color: rgb(136, 0, 0); ">"b"</span>(b)
: <span class="string" style="color: rgb(136, 0, 0); ">"memory"</span>, <span class="string" style="color: rgb(136, 0, 0); ">"%ebx"</span>
);
printf(<span class="string" style="color: rgb(136, 0, 0); ">"%d\n"</span>, a);
<span class="keyword" style="font-weight: bold; ">return</span> <span class="number" style="color: rgb(0, 136, 0); ">0</span>;
}
</stdio>
生成的彙編程式碼的主要部分如下:
movl $17, -20(%rbp)
movl $100, -24(%rbp)
movl -24(%rbp), %eax
movl %eax, %ebx
## InlineAsm Start
addl %ebx, -20(%rbp)
## InlineAsm End
## 下面的部分同此前的所有程式碼段,略去
可以看到是直接加到操作上的,而非暫存器。
-
轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant
-
相關文章
- GCC 內聯彙編GC
- GCC內聯彙編(1)Get startedGC
- GCC編譯過程(預處理->編譯->彙編->連結)GC編譯
- GCC編譯選項GC編譯
- GCC 編譯選項GC編譯
- gcc 從語言編譯全過程 預處理---->編譯---->彙編----->連結GC編譯
- gcc編譯GC編譯
- GCC使用基本方法彙總GC
- 彙編程式碼Helloworld
- 編譯器如何生成彙編編譯
- gcc常用的編譯選項對程式碼的影響(轉)GC編譯
- gcc 和 g++ 的聯絡和區別,使用 gcc 編譯 c++GC編譯C++
- 09. C語言內嵌彙編程式碼C語言
- CatFly【彙編程式碼還原】
- gcc編譯cpp檔案GC編譯
- GCC編譯器的使用GC編譯
- 開源編譯器 GCC 跨越 5.0,釋出 GCC 5.1編譯GC
- GCC 使用指南及gcc最佳編譯引數(轉)GC編譯
- gcc 編譯器與 clang 編譯器GC編譯
- 在Visual C++中使用內聯彙編C++
- js簡單富文字編輯器效果程式碼例項JS
- GNU 編譯器家族 GCC 內部探密(轉)編譯GC
- WebAssembly 系列(三)編譯器如何生成彙編Web編譯
- C語言的本質(32)——C語言與彙編之C語言內聯彙編C語言
- js實現的字串簡單編碼和解碼程式碼例項JS字串
- iOS彙編入門教程(二)在Xcode工程中嵌入彙編程式碼iOSXCode
- Linux中gcc編譯工具LinuxGC編譯
- linux下的gcc編譯LinuxGC編譯
- gcc 編譯多個原始檔GC編譯
- gcc最佳編譯引數(轉)GC編譯
- 安裝 GCC 編譯器(轉)GC編譯
- Solidity之旅(十八)內聯彙編 [inline assembly]Solidinline
- 在Visual C++中使用內聯彙編 (轉)C++
- 在Visual C++中使用內聯彙編(轉)C++
- Linux 中 x86 的內聯彙編(轉)Linux
- js自定義實現的簡單編碼和解碼程式碼例項JS
- 探索gcc編譯最佳化細節 編譯器最佳化gcc -o3GC編譯
- gcc編譯階段列印巨集定義的內容GC編譯