C嵌入汇编
概述:linux内核源码中,有很多C语言中嵌入了汇编语句,如何理解这些汇编语句,对理解内核有很重要的作用。
具有输入和输出参数的嵌入式汇编语句的基本格式为:
asm("汇编语句"
:输出寄存器
:输入寄存器
:会被修改的寄存器);
除第一行以外,后面带冒号的行若不使用就都可一省略。其中 “asm” 是内联汇编语句关键词。"汇编语句"是你写汇编指令的地方。“输出寄存器”表示当这段嵌入汇编执行完之后,那些寄存器用于存放输出数据。这些寄存器会分别对应一C语言表达式值或一个内存地址。“输入寄存器”表示在开始执行汇编代码时,这里指定的一些寄存器中应存放的输入值,它们也分别对应着一C变量或常数值。“会被修改的寄存器”表示你已对其中列出的寄存器中的值进行了改动,gcc编译器不能再依赖于它原来对这些寄存器加载的值。如果必要的话,gcc需要重新加载这些寄存器。因此我们需要把那些没有在输出/输入寄存器中的部分列出,但是在汇编语句中明确使用到或隐含使用到的寄存器名列在这个部分。
1 #define get_seg_byte(seg,addr) \
2 ( { \
3 register char _res ; \ //定义了一个寄存器变量——res
4 _asm_("push %%fs ; \ //保存fs寄存器原值
5 mov %%ax,%%fs ; \ //用seg设置fs
6 movb %%fs:%2,%%al ; \ //取seg:addr处1字节内容到al寄存器
7 pop %%fs " \ //恢复fs寄存器原内容
8 : "=a" (_res) \
9 : "0" (seg), "m" ( * (addr) ) ) ; \
10 _res ; } )
这段代码定义了一个嵌入式汇编语言函数。通常使用汇编语言最方便的方法是把他们放在一个宏内。用圆括号括住的组合语句(花括号中的语句)“({})”可以作为表达式使用,其中最后一行的变量_res是该表达式的输出值。
因为宏语句需要定义在一行上,因此这里使用反斜杠“\”将这些语句连成一行。这条红第一将被替换到程序中引用改宏名称的地方。第一行定义了宏的名称,即宏函数名称get_seg_byte(seg,addr)。第三行定义了一个寄存器变量_res。该变量将被保存在一个寄存器中,以便快速访问和操作。如果想指定寄存器(如eax),那么我们可以把改句写成"register char _res asm("ax");",其中asm也可以写成_asm_。第四行上的_asm_表示嵌入式汇编语句的开始。第4-7行的4条语句是AT&T格式的汇编语句。另外,为了让gcc编译产生的汇编语言程序中寄存器名称前有一个百分号“%”,在嵌入汇编语句寄存器名称前就必须写上两个百分号“%%”。
第8行即输出寄存器,该语句的含义是在这段代码运行结束后将eax所代表的的寄存器的值放入_res变量中,作为本函数的输出值,“=a”中的“a”称为加载代码,“=”表示这是输出寄存器,并且其中的值将被输出值替代。加载代码是CPU寄存器,内存地址以及一些数值的简写字母代号。第9行表示在这段代码开始运行时将seg放到eax寄存器中,“0”表示使用与上面相同位置上的输出寄存器。而((*addr))表示一个内存偏移地址值。为了在上面汇编语句中使用该地址值,嵌入式汇编程序规定把输出和输入寄存器按统一顺序编号,顺序是从输出寄存器序列从左到右从上到下以“%0”开始,分别记为%0、%1···%9.因此,输出寄存器的编号是%0(这里只有一个输出寄存器),输入寄存器前一部分(“0”(seg))的编号是%1,而后部分的编号是%2。上面第6行上的%2即代表(*(addr))这个内存偏移量。
常用寄存器加载代码说明
| 代码 | 说明 | 代码 | 说明 |
| a | 使用寄存器eax | m | 使用内存地址 |
| b | 使用寄存器ebx | o | 使用内存地址并可以加偏移值 |
| c | 使用寄存器ecx | I | 使用常数0-31 |
| d | 使用寄存器edx | J | 使用常数0-63 |
| S | 使用esi | K | 使用常数0-255 |
| D | 使用edi | L | 使用常数0-65535 |
| q | 使用动态分配字节可寻址寄存器(eax,ebx,ecx或edx) | M | 使用常数0-3 |
| r | 使用任意动态分配的寄存器 | N | 使用1字节常数(0-255) |
| g | 使用通用有效的地址即可(eax,ebx,ecx,edx或内存变量) | O | 使用常数0-31 |
| A | 使用eax与edx联合(64位) | = | 输出操作数,输出值将替换前值 |
| + | 表示操作数可读可写 | & | 早期汇编的操作数。表示在使用完操作数之前,内容会被修改 |
本文来源:谁不小心的CSDN博客 C嵌入汇编
外部参考:linux内核完全剖析第三章
C嵌入汇编的更多相关文章
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- [汇编] C语言中嵌入汇编
>_<" 下面是在C语言中嵌入汇编的例子,下面是三点要注意的~ 1.内联式汇编 2._asm关键字 3.并不是所有中断都能被支持 #include<iostream> ...
- 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call. 系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变 ...
- neon汇编,C嵌入汇编
1. Neon-intrics.pdf中的 void vst2q_u16(__transfersize(16) uint16_t * ptr, uint16x8x2_t val);// VST2.16 ...
- GCC 嵌入汇编代码
The format of basic inline assembly is very much straight forward. Its basic form is 基本汇编嵌入格式如下: asm ...
- 通过库函数API和C代码中嵌入汇编代码剖析系统调用的工作机制
作者:吴乐 山东师范大学<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 本次实验的主要内容就是分别采用A ...
- 第一个嵌入汇编的C程序
最近两天开始学习linux内核,看了赵炯博士的<linux内核完全注释>感觉受益匪浅.今天看到第三章 嵌入汇编部分,于是写了一个小程序试验了一下,用gcc编译通过.代码如下: #inclu ...
- KEIL C51 中嵌入汇编以及C51与A51间的相互调用
如何在 KEIL C51(v6.21) 中调用汇编函数的一个示例 有关c51调用汇编的方法已经有很多帖子讲到,但是一般只讲要点,很少有对整个过程作详细描述,对于初学者是不够的,这里笔者通过一个简单例子 ...
- 3.3.2 嵌入汇编(摘自<linux内核完全剖析>)
内核C语言程序嵌入式汇编代码又叫内联汇编,具有输入和输出参数的嵌入汇编语句的基本格式为: ************************************************** asm( ...
- 在C中嵌入汇编
早前公布了C和汇编混编的温度控制器程序,收到一些朋友的询问,他们无法在自己程序中使用我的18B20的汇编子程序或无法正常通过混编后的程序编译. 其实在KEIL中嵌入汇编的方法很简单.如图一,在C文件中 ...
随机推荐
- HTML 5 Web Storage 使用
在html中,可以使用 Web Storage API 来保存数据在浏览器客户端,这样可以避免重复从服务器加载数据. 有两种API, sessionStorage 和 localStorage ,它们 ...
- 已知的CPropertysheet bug: 切换焦点导致无响应
当一个页面内容比较多时我们首先可能考虑用Tab Control,但如果有很多页面内容需要动态加载则用CPropertySheet比较好点~ CPropertySheet有两种不同的显示模式.一种就是向 ...
- poj 3368 Frequent values(段树)
Frequent values Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13516 Accepted: 4971 ...
- Mac删除废纸篓中的单一文件和文件夹
http://www.macappbox.com/tips/159/ 通过Automator创建教程: 1.打开Automator并选择新建 2.选择服务类型 3.搜索Run Shell Script ...
- git gitk命令
通过gitk命令,在单独的界面上查看项目源码在各个时间点上的代码提交情况. 各个commit 各个tag ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` 更多详细的介绍 ...
- Android常用秘籍总结
一.无法向模拟器push文件,显示read-only file system $adb shell mount -o remount rw/ 确保模拟器有sd卡 二.Android模拟按键 #adb ...
- 17.1 Replication Configuration 复制:
17.1 Replication Configuration 复制: 17.1.1 How to Set Up Replication 17.1.2 Replication Formats 17.1. ...
- GDOI2015——已成梦
今年GDOI(2015)在韶关北江中学(没记错的话应该是武江区)举行,感觉这五天就是一场梦,一场包含苦辣的梦. Day0 坐了一个上午的车,而且车内的空气又不好,感觉整个人都累倒下了. 到了北江之后吃 ...
- springmvc + jquery easyui实现分页显示
如有不明确的地方,戏迎增加QQ群交流:66728073 推荐一本Java学习的书:深入理解Java7 一,下载并导入jquery easyui的导 <link rel="st ...
- Python 获取时间戳
Python 获取时间通过 time 模块 如下代码,是通过获取当前的时间,按照格式输出 Python默认获取当前的时间返回的都是时间的元组,下面是元组的,字符串时间的一个转换输出 # -*- cod ...