设为首页 加入收藏

TOP

Linux C语言内联汇编使用
2014-11-24 12:07:18 来源: 作者: 【 】 浏览:0
Tags:Linux 语言 内联 汇编 使用

参考资料:《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


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;
}


以上给出一个循环左移的例子,不关注循环左移指信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


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Java编程程序比C++的优劣分析 下一篇Python最简单直接的自定义模块导..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·PostgreSQL 索引 - (2025-12-25 22:20:43)
·MySQL Node.js 连接 (2025-12-25 22:20:41)
·SQL 撤销索引、表以 (2025-12-25 22:20:38)
·Linux系统简介 (2025-12-25 21:55:25)
·Linux安装MySQL过程 (2025-12-25 21:55:22)