2.2.1内嵌汇编
内容来源于《庖丁解牛Linux内核分析》-孟宁等
|-- 第2章操作系统是如何工作的
|--2.2借助Linux内核部分源代码模拟存储程序计算机工作模型及时钟中断
|--2.2.1内嵌汇编
有修改,大部分一样
C语言内嵌汇编语法如下:
__asm__ __volatile__ (
汇编代码
输出部分
输入部分
破坏性描述部分(可以省略)
);
下面通过一个简单的例子来熟悉内嵌汇编的语法规则
#include <stdio.h>
int main()
{
/* val1+val2=val3 */
unsigned int val1 = 1;
unsigned int val2 = 2;
unsigned int val3 = 0;
printf("val1:%d,val2:%d,val3:%d\n", val1, val2, val3);
asm volatile(
"movl $0,%%eax\n\t" /* clear %eax to 0 */
"addl %1,%%eax\n\t" /* %eax += val1 */
"addl %2,%%eax\n\t" /* %eax += val2 */
"movl %%eax,%0\n\t" /* val2 = %eax */
: "=m" (val3) /* output =m mean only write output memory variable */
: "c" (val1), "d" (val2) /* input c or d mean %ecx/%edx */
);
printf("val1:%d+val2:%d=val3:%d\n", val1, val2, val3);
return 0;
}
这个例子是用汇编代码是想val3=val1+val2
的功能(能在windows10, mingw-gcc上编译运行正确),具体解释如下
__asm__
是GCC关键字asm
的宏定义,是内嵌汇编的关键字,表示这是一条内嵌汇编语句。__asm__
和asm
可以互相替换使用:#define __asm__ asm
。__volatile__
是GCC关键字volatile
的宏定义,告诉编译器不要优化代码,汇编指令保留原样。__volatile__
和volatile
可以互相替换使用:#define __volatile__ volatile
。- 内嵌汇编关键字
asm volatile
的括号内部第一部分是汇编代码,即前四句双引号代码。- 寄存器前会多一个
%
转义符号,即两个%
(%%
) %数字
表示后面输出部分、输入部分、破坏性描述部分的编号。按照这几部分里变量的出现顺序从0开始编号,具体来说%0
表示变量val3
,%1
表示变量val1
,%2
表示变量val2
(注意并不是按照前面c语言的声明顺序)- 注意
%数字
和$数字
区分,后者才是立即数的意思
- 寄存器前会多一个
- 先解释后面的输出输入部分,前面的汇编代码部分就能理解了。
- 输出输入部分以
:
开头,这点和汇编代码部分不一样。 - 大体的规则是:
: "位置" (c上下文的变量名)
,其中位置里m表示memory,c表示ecx寄存器,d表示edx寄存器;通过上面说的%数字
将汇编和C语言变量名进行绑定。=
表示输出。 - 没有输出/输入也要有
:
来占行占位。
- 输出输入部分以
因此,可以把这个模型的内嵌汇编看成是一个函数,第一部分是函数体,第二部分是返回值,第三部分是参数列表。