在gcc中使用intel风格的内联汇编
来源:互联网 发布:华大基因难进吗 知乎 编辑:程序博客网 时间:2024/06/07 01:09
很简单,内联汇编使用asm(“.intel_syntax noprefix/n”)声明一下,以后的内联汇编就可以用intel风格了,构建可执行文件时给gcc加上-masm=intel参数。
先写一个小程序测试一下:
[root@jcwkylk src]# gcc -masm=intel test.c -o test
/tmp/ccgWTkUF.o: In function `main':
test.c:(.text+0x1a): undefined reference to `a'
collect2: ld returned 1 exit status
出错,说符号a没有定义。看看编译后的结果是什么样子:
[root@jcwkylk src]# gcc -S test.c
输出不长,把test.s的内容全部贴出来:
从上面看出来,夹在#APP和#NO_APP之间的部分就是.intel_syntax,它保持了原样,而代码中的a原本是个局部变量,只有在函数运行时它才会动态在栈上分配,使用ebp加上偏移量来访问它,这就是问题所在。因为全局变量的变量名会保存在符号表中,所以如果要在内联汇编中使用变量名,也只能使用全局变量的变量名。只为在内联汇编中用名称来访问变量而把一个局部变量变成全局的是不合理的,所以我们这里也用ebp+offset的方式来访问局部变量。
要这么做,就得了解gcc编译时是如何为函数分配栈的,以及调用函数时寄存器约定是怎样的。从上面的汇编代码可以看出来:
这几行代码用来初始化mai函数的调用栈,和cl编译器不同的是在push ebp前面多出来了几行,有个esp &= -16的操作,-16=0xfffffff0,这个作用可能是为了对齐,esp应该是保持16字节对齐的。但这些细节在这里作用都不大。最关键的是这三行:
pushl %ebp
movl %esp, %ebp
pushl %ecx
有一个把ecx寄存器压栈的操作,所以第一个局部变量的起始地址应该是ebp-8。
另一个注意的地方是printf的调用:
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
在这个代码中printf有两个参数,但却没有看到期望的push。gcc用了另外一种方法:直接操作esp。上面这三行代码,首先把[ebp-8]也就是第一个局部变量即a的值给了eax,然后把这个值传递到esp+4这个地址指向的内存单元,然后esp指向printf的第一个参数——那个格式控制字符串。之后call printf会把下一条指令的地址压入栈中,然后跳转到printf,所以,对printf来说,ebp+4仍然是返回地址,ebp+8仍然是第一个参数,ebp+0xc仍然是第二个参数。一切都没变。
最后有这一行代码:movl $0, %eax
看来返回值仍然是存放在eax寄存器中。
好,现在写一个比较完整的测试程序:
[root@jcwkylk src]# gcc -masm=intel test.c -o test
[root@jcwkylk src]# ./test
10
35
- 在gcc中使用intel风格的内联汇编
- LLVM/GCC中如何使用Intel格式的汇编
- LLVM/GCC中如何使用Intel格式的汇编
- 在Visual C++中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在C中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在C中使用内联汇编
- 在Visual C++中使用内联汇编
- 在Visual C++ 中使用内联汇编
- 在Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 在 Visual C++ 中使用内联汇编
- 我眼中的澳门---庆祝澳门回归十周年
- 验证电话号码合理性,电话号码验证合理性,电话号码合理性验证。
- Apache 目录配置文件--[.htaccess]
- jsp中文编码详解(转)
- 中meta属性详解——转
- 在gcc中使用intel风格的内联汇编
- Wince中几个工程文件简介
- C 中运算注意的地方
- 纪念贴
- 沉痛哀悼我们的电骡和BT中国联盟
- 2009-12-12 Sat
- C中的volatile用法
- 实现菜单绑定xml文件
- 关于背景图片位置的控制!