在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函数的更多相关文章

  1. linux源码阅读笔记 fork函数

    在阅读源码的过程中,发现找不到fork函数的定义.后来在linux/init/main.c中找到了这样一条语句 static inline _syscall0(int,fork) 原来这里就是fork ...

  2. linux源码阅读笔记 数组定义

    在阅读linux源码的过程中遇到了下面的略显奇怪的结构体数组定义. static struct hd_struct{ long start_sect; long nr_sects; }hd[10]={ ...

  3. linux源码阅读笔记 move_to_user_mode()解析

    在linux 0.11版本源代码中,在文件linux/include/asm/system.h中有一个宏定义  move_to_user_mode() 1 #define move_to_user_m ...

  4. linux源码阅读笔记 #define 语句的妙用

    #define 语句用于宏定义,在c中,我们可以用其实现函数的功能.如下语句 #define test(a,b)  a>b?a:b 很显然,这是一个比较大小的语句.这里a,b相当于函数中的参数. ...

  5. linux源码阅读笔记 void 指针

    void 指针的步长为1,而其他类型的指针的步长与其所定义的数据结构有关. example: 1 #include<stdio.h> 2 main() 3 { 4 int a[10]; 5 ...

  6. linux源码阅读笔记 jmpi指令(转)

    jmpi是段间跳转指令,用于x86实模式下, 如:BOOTSEG = 0x0c70 jmpi    4, #BOOTSEG 假如当前段CS==00h,那么执行此指令后将跳转到段CS==0x0c70,当 ...

  7. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  8. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  9. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...

随机推荐

  1. (转)Yale CAS + .net Client 实现 SSO(3)

    第一部分:安装配置 Tomcat 第二部分:安装配置 CAS 第三部分:实现 ASP.NET WebForm Client 1. 下载.NET CAS client. .NET CAS Client ...

  2. javascript 获取项目根路径

    /** * http://localhost:8088/projectName */ function getRootPath(){ //获取当前网址,如: http://localhost:8088 ...

  3. tomcat之JNDI数据源配置

    一.docbase包含方式部署项目 D:\apache-tomcat-6.0.29\conf\server.xml里面添加如下内容   <Host name="localhost&qu ...

  4. HTML文件中使用Java程序

    HTML文件中使用Java程序:简而言之,在HTML文件中引入java应用程序,并通过javascript调用其方法.   一. 运行环境 1.JAVA_HOME.CLASSPATH.PATH配置正确 ...

  5. Silverlight引用WebService时取消对ServiceReferences.ClientConfig文件的依赖

    做过Silverlight项目的朋友都知道一般来说我们在Silverlight项目中都需要引用WebService或是WCF,引用的方式是在Visual Studio窗口中通过“添加服务引用”来添加引 ...

  6. javascript a=a||"" 表达式

    其实: a=a||"defaultValue"; 与: if(!a){ a="defaultValue"; } 和: if(a==null||a==" ...

  7. RAID 0+1

    正如其名字一样RAID 0+1是RAID 0和RAID 1的组合形式,也称为RAID 01. 以四个磁盘组成的RAID 0+1为例,其数据存储方式如图所示:RAID 0+1是存储性能和数据安全兼顾的方 ...

  8. 使用jQuery获取GridView的数据行的数量

    一个同事在群里抛出了上述的问题,另一个同事给出了答案,试了一下,还不错.贴出代码和效果图: <html xmlns="http://www.w3.org/1999/xhtml" ...

  9. mysql基本知识---20151127-1

    2015年11月27日,作为PHPer的我开始全面学习mysql数据库. 基本语法: 1.连接服务器: mysql>mysql -h host -u root -p 回车 输入密码(本地环境可以 ...

  10. jQuery 单选按钮切换

    html代码片段一: <div class="row"> <div class="col-sm-12"> <label for=& ...