GCC内联汇编(2)GCC生成汇编代码简单实例
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
-
分享到:
相关推荐
ARM GCC 内联汇编参考手册
gcc 内联汇编官方手册最新版 ThisHOWTOexplainstheuseandusageoftheinlineassemblyfeatureprovidedbyGCC.
GCC内联汇编, C语言嵌入汇编,AT&T Intel语法区别
GCC内联汇编入门[参照].pdf
gcc 内联汇编 1 AT&T 与 INTEL 的汇编语言语法的区别 1.1 大小写 1.2 操作数赋值方向 1.3 前缀 1.4 间接寻址语法 1.5 后缀 1.6 指令 2 GCC 内嵌汇编 2.1 简介 2.2 内嵌汇编举例 2.3 语法 2.3.1 汇编语句...
ARM GCC 内联汇编参考手册 - 中文版
翻译原文为GCC-Inline-Assembly-HOWTO,介绍gcc内联汇编的使用方法。
GCC内联汇编, C语言嵌入汇编,AT&T Intel语法区别
GCC内联汇编, C语言嵌入汇编,AT&T Intel语法区别
GCC内联汇编基础[借鉴].pdf
在Linux的核心代码中,还是存在相当一部分的汇编语言代码。如果你想顺利阅读Linux代码的话,你...另一部分则是利用gcc的内嵌式汇编语言语句asm嵌在Linux的C语言代码中的。这篇文章主要是介绍第二种形式的汇编语言代码。
GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC代码生成器GCC...
AT&T汇编语言与GCC内嵌汇编简介 linux 内核 汇编 介绍以上内容。pdf文件
NULL 博文链接:https://chong-zh.iteye.com/blog/1670997
AT&T汇编语言与GCC内嵌汇编简介.pdf
GCC内联汇编(INLINE ASSEMBLY) 什么是内联汇编(Inline assembly)? 1、这是GCC对C语言的扩张,是在C代码里面去写汇编代码 2、可以直接在C的语句中插入汇编指令 有何用处? 1、C语言不足以完成所有...
较为详细的说明了在gcc平台下,如何在c中嵌入汇编语法