Linux C语言内联汇编使用 .
来源:互联网 发布:镜片清洗液 知乎 编辑:程序博客网 时间:2024/06/06 09:53
本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性。
参考资料:《Linux内核完全剖析》,《新版汇编语言程序设计》,《Linux C编程一站式学习》
最近要改个C语言算法的关键部分用汇编语言实现,Linux里嵌入汇编基本使用AT&T汇编,比如Linux系统的启动部分用的就是AT&T汇编 。以前学过AT&T汇编,但学过一段时间就忘了,但对Intel汇编基础比较熟悉,两者使用方法基本相似,所以对着Intel汇编,花点时间看AT&T汇编也就容易了。
下面看一下两者的区别,然后给出Linux语言中嵌入AT&T汇编的具体的例子。
一、AT&T汇编和Intel汇编主要区别
1,两者源和目的操作数次序相反。 AT&T的源和目的是从左到右,并且其寄存器前要加“%”;Intel的是右到左,不需要加"%"。
例如:AT&T: movl %ecx, %eax (ecx为源操作数,eax为目的操作数)
Intel: mov dx, bx (bx为源操作数,dx为目的操作数
2,AT&T立即操作数前需要加"$";Intel的不用
例如:AT&T:movl $2, %eax
Intel:mov ax, 2
3,AT&T中内存操作的长度由操作码最后一个字符来确定。"b","w","l"分别表示内存引用为1字节8位,2字节16位,4字节32位。
Intel使用操作前缀byte ptr, word ptr, dword ptr
例如:AT&T:movl %ecx, %eax
Intel:mov al, byte ptr ttt
这三点是最重要的区别,除此之外还有跳转/调用时不太一样。
二、嵌入汇编基本格式
asm("汇编语句"
"输出寄存器"
"输入寄存器"
"会被修改的寄存器"//告诉编译器在执行这条__asm__语句时这里指定的寄存器要被改写,所以在此期间不要用这里的寄存器保存其它值。
)
//asm.c
#include <stdio.h>
unsigned int LeftShift(unsigned int uiNumber, unsigned char iBits)
{
register unsigned int _res;
__asm__("rol %1, %%eax;"
:"=a" (_res)
:"c" (iBits),"0"(uiNumber)
);
return _res;
}
int main(void)
{
unsigned int ret = 0;
ret = LeftShift(4, 2);
printf("1,ret:%u\n", ret);
return 0;
}
[root@xxx asm_study]# gcc asm.c -o app
[root@xxx asm_study]# ./app
1,ret:16
以上给出一个循环左移的例子,不关注循环左移指信rol本身,只关注AT&T汇编用法。
首先定义了个寄存器变量_res,用其保存返回值。
因为AT&T汇编使用寄存器,其前面需要带“%”,而在c语言中“%”是个特殊格式字符,所以需要两个百分号“%%”才最终表示一个“%”,这个和转义字符有点类似。
:"=a"(_res)表示用寄存器eax的值输出给_res,用%0表示此寄存器,
:"c" (iBits),"0"(uiNumber),c表示输入寄器ecx,0表示使用上面的输出寄存器eax,所以ecx和eax分别保存iBits和uiNumber变量值。指令中的%1指寄存器ecx,所以其编号规则是从“输出寄器”开始从左到右,从上到下进行的。
可以发现rol %1,%%eax其实可以直接写成:rol %1, %0
三、C语言版循环左移
给出一个C语言版循环左移代码,有兴趣的朋友可以和上面的汇编版进行对比。
//ori.c
unsigned int LeftShift2(unsigned int uiNumber, unsigned char iBits)
{
int i=0;
unsigned int iret=uiNumber;
unsigned int iR=0x01;
for(i=0;i<iBits;i++)
{
iR=iret&0x80000000;
iret=iret<<1;
iR=iR>>31;
iret=iret|iR;
}
return iret;
}
int main(void)
{
unsigned int ret = 0;
ret = LeftShift2(4,2);
printf("2,ret:%u\n", ret);
return 0;
}
[root@xxx asm_study]# gcc ori.c -o app
[root@xxx asm_study]# ./app
2,ret:16
四、宏定义版汇编
#define LeftShift(uiNumber, iBits) \
({\
register unsigned int __res;\
__asm__("rol %%cl, %%eax;" \
:"=a"(__res)\
:"c" (iBits),"a"(uiNumber));\
__res;})
和普通的汇编区别是每一行后面都要加"\",返回值写最后,如上面最后的__res。
五、c程序转变为汇编程序
1,把*.c程序转变为AT&T格式汇编*.s
[root@xxx asm_study]# gcc -S asm.c -o asm.s
[root@xxx asm_study]# ls -al asm.s
-rw-r--r-- 1 root root 1387 06-30 10:41 asm.s
2,把*.c程序转变为Intel格式汇编*.s
[root@xxx asm_study]# gcc -masm=intel test.c -o test.s
当然,要想把c程序转为Intel汇编时,其中不能包含AT&T格式的汇编,否则无法转。
- Linux C语言内联汇编使用
- Linux C语言内联汇编使用
- Linux C语言内联汇编使用
- Linux C语言内联汇编的使用
- Linux C语言内联汇编使用 .
- Linux C语言内联汇编使用
- Linux C内联汇编
- linux C 内联汇编
- Linux C内联汇编用法
- Linux下C内联汇编小例子
- 在C中使用内联汇编
- 在C中使用内联汇编
- C/C++中使用内联汇编
- C内联汇编
- C 内联汇编
- c/c++内联汇编
- C内联汇编
- C内联汇编
- 网络子系统——notifier测试程序
- SQL-SERVER 性能查询死锁、堵塞
- 如何查看进程打开了哪些文件? .
- sharepoint 2010 扩展调查字段属性(4)-增加图片支持-多选
- 分布式协调器ZooKeeper3.4—入门
- Linux C语言内联汇编使用 .
- 分享:某类程序不支持64位的程序在win2008R2与IIS7.5上运行的问题的解决方法
- Commons Io 包 学习笔记~
- python中列表(list)和字典(dict)数据排序
- Length of S(n) hdu4148 水题
- 在服务器上处理请求时出现未知错误。服务器返回的状态码为500。的处理方法。
- 连接不上sql server
- Teradata数据库复制表
- 开源Commons包的 使用粗劣总结~