linux源码阅读笔记 asm函数
在linux源码中经常遇到__asm__函数。它其实是函数asm的宏定义
#define __asm__ asm,asm函数让系统执行汇编语句。
__asm__常常与__volatile__一起出现。__volatile__限制编译器不能对下面的汇编语句进行优化处理。
分析下面语句
__asm__("movb %3,%%dh\n\t" \
"movb %2,%%dl\n\t" \
"shll $16,%%edx\n\t" \
"movw %1,%%dx" \
:"=d" (__base) \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7))); \
__base;})
首先它的基本格式为:
__asm__ ("InstructionList"
:Output
:Input
:Clobber/Modify);
%0,%1,%2,%3分别对应OutPut和Input中出现的操作数,称为占位符。在此例中,对应关系如下:
%0 __base
%1 (*((addr)+2))
%2 (*((addr)+4))
%3 (*((addr)+7))
这样的占位符最多有10个。在操作数之前还有一个字符串,该字符串表示将操作数放入对应的位置进行处理。
例如,"=d" (__base),表示将操作数__base放入寄存器%edx。也就是%edx代表了__base,=表示该操作数是WRITE—ONLY的。
而"m"表示内存。这就是所谓的操作约束。
注意,如果操作约束是“m“,也就是内存的话。无论是输入参数还是输出参数,对这些参数的改变会反映在内存中。
例如:
int c=0;
__asm__("mov $100,%0\n\t"\
::"m" c)
c的值会被改变为100
具体的寄存器缩写以及各个符号的含义见下。
每一个Input和Output表达式都必须指定自己的操作约束Operation Constraint,这里将讨论在80386平台上所可能使用的操作约束。
当前的输入或输出需要借助一个寄存器时,需要为其指定一个寄存器约束,可以直接指定一个寄存器的名字。
常用的寄存器约束的缩写
约束 意义
r 表示使用一个通用寄存器,由 GCC 在%eax/%ax/%al,%ebx/%bx/%bl,%ecx/%cx/%cl,%edx/%dx/%dl中选取一个GCC认为合适的。
g 表示使用任意一个寄存器,由GCC在所有的可以使用的寄存器中选取一个GCC认为合适的。
q 表示使用一个通用寄存器,和约束r的意义相同。
a 表示使用%eax/%ax/%al
b 表示使用%ebx/%bx/%bl
c 表示使用%ecx/%cx/%cl
d 表示使用%edx/%dx/%dl
D 表示使用%edi/%di
S 表示使用%esi/%si
f 表示使用浮点寄存器
t 表示使用第一个浮点寄存器
u 表示使用第二个浮点寄存器
如果一个Input/Output 操作表达式的C/C++表达式表现为一个内存地址,不想借助于任何寄存器,则可以使用内存约束。比如:
__asm__("lidt%0":"=m"(__idt_addr));
__asm__("lidt%0"::"m"(__idt_addr));
修饰符 输入/输出 意义
= O 表示此Output操作表达式是Write-Only的。
+ O 表示此Output操作表达式是Read-Write的。
& O 表示此Output操作表达式独占为其指定的寄存器。
% I 表示此Input 操作表达式中的C/C++表达式可以和下一 个Input操作表达式中的C/C++表达式互换
linux源码阅读笔记 asm函数的更多相关文章
- linux源码阅读笔记 fork函数
在阅读源码的过程中,发现找不到fork函数的定义.后来在linux/init/main.c中找到了这样一条语句 static inline _syscall0(int,fork) 原来这里就是fork ...
- linux源码阅读笔记 数组定义
在阅读linux源码的过程中遇到了下面的略显奇怪的结构体数组定义. static struct hd_struct{ long start_sect; long nr_sects; }hd[10]={ ...
- linux源码阅读笔记 move_to_user_mode()解析
在linux 0.11版本源代码中,在文件linux/include/asm/system.h中有一个宏定义 move_to_user_mode() 1 #define move_to_user_m ...
- linux源码阅读笔记 #define 语句的妙用
#define 语句用于宏定义,在c中,我们可以用其实现函数的功能.如下语句 #define test(a,b) a>b?a:b 很显然,这是一个比较大小的语句.这里a,b相当于函数中的参数. ...
- linux源码阅读笔记 void 指针
void 指针的步长为1,而其他类型的指针的步长与其所定义的数据结构有关. example: 1 #include<stdio.h> 2 main() 3 { 4 int a[10]; 5 ...
- linux源码阅读笔记 jmpi指令(转)
jmpi是段间跳转指令,用于x86实模式下, 如:BOOTSEG = 0x0c70 jmpi 4, #BOOTSEG 假如当前段CS==00h,那么执行此指令后将跳转到段CS==0x0c70,当 ...
- Linux 0.11源码阅读笔记-总览
Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- Linux 0.11源码阅读笔记-文件管理
Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...
随机推荐
- 《Apache服务之php/perl/cgi语言的支持》RHEL6——服务的优先级
安装php软件包: 安装文本浏览器 安装apache的帮助文档: 测试下是否ok 启动Apache服务关闭火墙: 编辑一个php测试页测试下: perl语言包默认系统已经安装了,直接测试下: Apac ...
- ADO.NET笔记——使用通用数据访问
相关知识: 前面所有示例,君是访问特定的数据库(SQL Server),因此注入SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter等类名都添加了 ...
- jQuery1.9 $.browser 的替代方法
jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support . 在更新的 2.0 版本中,将不再支持 IE 6/7/8. ...
- php 判断字符串在另一个字符串中位置
$email='user@example.com'; //定义字符串$result=strstr($email,'@'); //返回子字符串echo $result; / ...
- (IIS8/8.5/Apache)301域名重定向
用Apache的.htaccess来做301域名转向1.开启apache支持.htaccess,方法:在Apache的配置文件httpd.conf中,找到<Directory /> ...
- [转]WPF 依赖项属性
from:http://blog.csdn.net/datoumimi/article/details/8033682 ps:环境限制,发的东西一长就会被拦截,所以删了一部分 UI软件中经常会用到大量 ...
- Makefile之wildcard
1.wildcard : 扩展通配符2.notdir : 去除路径3.patsubst :替换通配符 例子:建立一个测试目录,在测试目录下建立一个名为sub的子目录$ mkdir test$ cd t ...
- JVM基础:深入学习JVM堆与JVM栈
转自:http://developer.51cto.com/art/201009/227812.htm JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题, ...
- Jira 6.0.3 安装与破解
如果你还没有使用Jira做项目跟踪与管理,那就赶紧试用一下吧.下面教你一步一步安装Jira 6.0.3,以及如何破解试用版. 一. 安装准备 1. 去Jira官方网站下载http://www.at ...
- MVC的小知识点
1.MVC的前台页面编译完之后,也会生成一个前台页面类.在前天页面中加入这段代码this.GetType().Assembly.GetLocation()得到当前类所在的程序集,可以查看其所在的程序, ...